Cosa ho imparato oggi

Coso ho imparato oggi

(professore FONTECEDRO https://www.youtube.com/watch?v=aqTmhBca7f8 )

Dopo aver insistito col farmi dare un server da poter usare per metterci redmine e gogs, mi sono ritrovato oggi a dover far girare i due docker insieme e farli interagire.

C’è da dire che di docker non ci capisco nulla, quindi oggi ho imparato ad usare quello che mi serve di docker.

Prima di tutto sono container, ovvero sono basati sull’esecuzione di un processo bindato (perché dire bendato non da abbastanza l’idea) rispetto al resto del sistema. In sostanza quasi una macchina virtuale, ma gira sullo stesso kernel dell’os nel quale lo si lancia, è basato su concetto di cgroups di linux, e siccome non lo so rimando a https://en.wikipedia.org/wiki/Cgroups

Quello che interessava a me era di tirar su una immagine docker di redmine e una di gogs e farle girare nel server, e in più collegare i due container integrare un sistema per il controllo del progetto che desse delle statistiche aggiornate della situazione.

Ecco, quest’ultima parte è particolarmente complicata se non sai niente di docker.

*Come si fa girare un docker.*

Sostastanzialmente ho capito che per far girare un docker devi prima prendere l’immagine e poi avviarlo. Inizialmente avevo inteso che bastasse riferirsi alla immagine e scrivere

docker run image/name [altrivari parametri]

e così esso faceva tutto. Ho poi scoperto che questa è una visione un po’ miope. In effetti mi sono trovato con immagini nelle quali era già definito lo script di start. In generale al comando “docker run” si specifica il nome dell’immagine (che docker scarica in una qualche maniera da un repository delle immagini) e il comando da eseguire all’interno del container contestualmente creato al momento in cui viene eseguito run. Frase contorta, disgustorama, come direbbe il professor Fontecedro. Ma in realtà il comando

$ docker run -d -p 80:80 my_image nginx -g ‘daemon off;’
60baacd90721 # valore restituito

carica l’immagine my_image, crea un container, e, all’interno di quello esegue il comando “nginx -g ‘daemon off;'”.
Ora, visto che si tratta di una immagine personale, evidentemente devi essere a conoscenza che contiene il programma nginx, e quindi lo puoi eseguire. In generale io ho immagini nelle quali è definito all’interno dello script start.sh l’avvio di un server.

Ecco esattamente quello è il concetto di immagine: cosa c’è dentro il microservice che viene eseguito tramite docker.

Importante è anche il concetto di container: l’esecuzione della immagine con i relativi parametri di esecuzione.

Così, mi pare di aver capito, che se eseguo “docker run” con tutti i parametri del caso, ottengo un container id, è una chiave unica, sembra sha256, che identifica il container. A quel punto posso fermarla o riavviarla alla bisogna. Così:

docker stop 60baacd90721
docker start 60baacd90721

e 60baacd90721 è l’id del container che viene restuito dal comando “docker run”

Ho poi capito che se ho bisogno di entrare nella “quasi-macchina-virtuale” posso eseguire un comando a piacere in un virtual terminal di quella macchina, così

docker exec -ti 60baacd90721 bash

e posso specificare l’utente col quale eseguirlo

docker exec -u redmine -ti 60baacd90721 bash

perché avevo il problema di dover controllare il risultato del comando “git ls-remote -h ssh://…” per controllare l’accessibilità all’altro container.

A proposito del far girare più container sulla stessa macchina, il problema è stato farli communicare tra loro (magari con una sola m). E per questo c’è

docker network

sembra che docker sia un’insieme di sotto programmi, un po’ come è git. Quindi

docker network ls

elenca le reti definite nel sistema.

docker network inspect [networkname]

mostra la definizione della rete

docker network connect [networkname] [containerid]

connette una rete al container. E questa cosa è magica. In pratica se 2 container non riescono a vedersi è perché, generalmente, sono stati definiti tramite il comando run o tramite docker-compose. Nel primo caso il container avrà associata la rete “bridge” di default, nel secondo caso viene creata una rete on-the-fly da docker (c’è da controllare cosa sia docker-compose, il comando, per capire perché), e il suo nome è dato dal nome della definizione col postfisso “_default” (cioè se docker-compose.yaml è nella cartella “sfortuna” al momento della esecuzione di docker-compose, la rete creata si chiamerà sfortuna_default), nel mio caso si chiamava bugs:

$ sudo docker network ls
NETWORK ID NAME DRIVER SCOPE
e0af7dce8070 bridge bridge local
ac43047ffe4f bugs_default bridge local
e117f156b39d host host local
b2a366b4b71a none null local

host è un tipo particolare di network, consiste nel risiedere nella stessa interfaccia del server dove gira … posso solo immaginare i casini nella gestione, ma è più veloce, evidentemente, perché non è emulata.

Ora, quello che ho trovato veramente fantistico oggi (eh, ma ho sudato parecchio per arrivarci) è proprio

docker network connect [netname] [containerid]

e

docker network disconnect [netname] [containerid]

in pratica si opera su un container esistente, e in esecuzione, e gli si aggiunge una scheda di rete virtuale, e la si toglie.

Cosmico.

È così che il container di redmine può vedere la rete del container gogs, e può richiedere cose tipo

git ls-remote -h ssh://git@172.17.0.2:10022/danieldock/privatetest.git

Ovviamente il viaggio di oggi è stato infarcito di “boh … non funziona, lascio stare .. ma…” e dal leggere cose tipo “I’ll merge if it is the case” https://github.com/dergachev/redmine_git_remote/issues/34 (no, che dici, quanti devono ancora scoronare?)

 

Ok. Tutto funziona e abbiamo un sistema per monitorare l’andamento dello sviluppo delle features, la gestione delle anomalie, vediamo chi sta lavorando a cosa e come, eccetera.

Era ora.

 

App cross platform basate su webengines.

====================================
Cross platform basati su webengines.
====================================

(o motori di rendering)

– inglobare una pagina web in una finestra del browser senza le limitazioni tipiche imposte dal browser (accesso al filesystem e ai vari dispositivi), per creare una applicazione nativa (più o meno)

– **Meteor**: applicazione js+html che non ha limitazioni di accesso al filesystem. Richiede l’installazione di node e di altri pacchetti nella macchina target, non crea un vero e proprio eseguibile, ovvero non compila il codice. Ha il vantaggio di avere come target anche

– **Electron**: permette di creare applicazione js+html senza limitazioni. In più compila nativamente il codice per la macchina target. Ha un rendiring engine basato su webkit (chromium) e non supporta target come iOS e Android per la compilazione.

– **Cordova**: framework pensato specificamente per dispositivi mobile. Cordova definisce una serie di plugin per accedere alle risorse del dispositivo, l’applicazione dichiara a quali risorse vuole poter accedere, quindi da Javascript sarà possibile richiamare i metodi ad esse associate, ovvero associati ai plugin caricati. Tutto questo è pensato per i dispositivi mobile dove la lista di permessi deve essere dichiarata al momento della installazione di una applicazione. Es.:

Dal punto di vista della applicazione js+html si può usare quello che si preferisce, ad esempio qui

si usa react + webpack

– **ionic** è semplicemente un framework basato su Cordova, con dei componenti standard che cerca di unificare e velocizzare la creazione di applicazioni per più target di Cordova, mantenendo la coerenza tra esse.

– **Positron** è stato un tentativo di usare il rendering engine di firefox per fare la stessa cosa che fa Electron. Poi *chiuso*.

– Servo based runtime (idea)

un backend in python e webkit per html+js. Da l’opportunità di usare moduli python per controllare la webview, ma ovviamente richiede l’installazione di python (analogamente a come Meteor richiede l’installazione di Node.js).

qualcosa di molto simile a Electron (firefox engine)

– Edge che vantaggi si hanno con Edge? si possono esportare moduli scritti in C# verso node.js, quindi usarli all’interno della webview.

un fork

– **ReactNative** non è un vero e proprio html+js, permette infatti di usare i componenti disponibili, e comporli per creare una applicazione, ma non l’html vero e proprio. Compila nativamente per iOS e Android, vere e proprie applicazioni native.

Questo articolo è una bozza, evidentemente.

Tracciare lo sguardo per cambiare il focus della tastiera

Io ho questa idea da un po’. Poi stamattina ho letto un articolo, https://blog.acolyer.org/2017/04/26/improving-user-perceived-page-load-time-using-gaze/ (riguarda la priorizzazione del caricamento dei contenuti per rendere migliore la percezione del tempo di caricamento, ma …) trovo questo

https://sourceforge.net/projects/gazepointer/

Avendo diversi monitor non è raro guardare da una parte e scrivere da un’altra, non so quindi quanto questo si utile.

Ma capita di iniziare a scrivere e accorgersi in un secondo momento che il focus è in un’altra finestra. Possono succedere casini, ma anche la sola perdita di tempo.

Mi piaccerebbe capire cosa è possibile fare. Ovviamente non voglio fare a meno del mouse, perché è utile, vorrei piuttosto avere 2 puntatori, uno controllato dal mouse, l’altro dallo sguardo, quando necessario cliccare, impostare una combinazioni di tasti per far cliccare il puntatore controllato dallo sguardo.

Questa sarebbe una cosa piuttosto utile e produttiva

Ci sono altri utilizzi interessanti:

https://github.com/lexasss/etudriver-web

 

Indutria 4.0, NAS, SAN, FUJI, VMWare, e soiel

Due giorni di convegni e non ho scritto nulla.

Il primo, ieri pomeriggio organizzato da Confindustria Ancona, riguardante Industria 4.0.

Non avevo idea di cosa fosse, così mi sono iscritto. In pratica è l’utilizzo dell’informazione nel contesto della produzione industriale per migliorare l’efficienza, andare incontro alla domanda, monitorare il gradimento di un prodotto, migliorare il rapporto col cliente, prevedere i bisogni.

La rivoluzione sarebbe quella di portare i meccanismi di feedback direttamente a livello industriale, senza passaggi intermedi. Altro vettore di informazione sono poi le macchine e le loro azioni, e i sensori, che facendo rete possono migliorare la efficienza produttiva.

Tutto ciò infarcito da una infrastruttura burocratica, ed Industrial Innovation Hub, che dovrebbbero far sì che questa rivoluzione avvenga. E qui sono rimasto un po’ stupito di come una rivoluzione possa provenire da una infrastruttura burocratica di livello europeo (e piramidale, fino arrivare agli hub locali) e non da esigenze o innovazioni introdotte da attori presenti nel mercato. Cioè, quasi ho avuto l’impressione di ascoltare qualcosa di simile ad un comitato di difesa della rivoluzione.

E perché mai gli industriali non pensano di loro iniziativa di introdurre innovazioni?

Cosa guardano durante la loro attività?

Perché non innovano di loro iniziativa?

Me ne sono andato presto. Tutto molto interessante e assolutamente giusto, ma anche tecnologie che conosco già, ma gli industriali sembra di no.

L’altro stamattina, a Civitanova, VMWare, Fuji e SOIEL International hanno organizzato un evento formativo, o pubblicitario sullo storage.

Ecco. Qui mi sono trovato a non capire niente, terminologie mai incontrate, forse perché non è il mio campo, eppure è storage, e si tratta di server che io potrei usare (è vero che non mi è mai capitato). Così, tornando in treno, mi documento un po’ e scopro cose interessanti.

Partendo dalle sigle:

  • NAS: Network Area Storage. È il semplice fileserver. Le tecnologie sono NFS, Samba/CIFS, etc.
  • SAN: Storage Area Network. È uno storage distribuito su rete locale o globale.

E su SAN viene il bello. Esistono 2 protocolli:

  • FC: Fiber Channel
  • iSCSI: internet Small Computer System Interface
  • (e FCoE: Fiber Channel over Ethernet)

FC è stato il primo, è un protocollo dedicato che funziona solo su reti dedicate, appunto, e garantisce velocità maggiori e affidabilità dei dati di un livello superiore.

Mentre iSCSI è stato sviluppato successivamente ed ha il vantaggio di essere più semplice e facilmente implementato perché è un protocollo che si poggia sopra TCP/IP.

Essendo storage distribuiti c’è il concetto di unità indirizzabile, in particolare queste 2 acronimi:

  • LUN: Logical Unit Numbers
  • IQN: iSCSI Qualified Name

il secondo dovrebbe essere un nome simbolico, quindi ha bisogno del suo omologo dns che si chiama:

iSNS: internet Storage Name Service

Nel caso iSCSI i pacchetti girano sopra TCP/IP, quindi nascono intrinsecamente problemi di sicurezza, che vanno affrontati. Qui non mi andava più di leggere, ma IPSec è una possibile soluzione, altre non ho approfondito.

Durante il convegno VMWare pubblicizzava il su vSAN, virtual SAN, mentre FUJI il suo sistema di storage integrato che forniva una soluzione completa. In realtà i 2 attori non sono concorrenti, ovviamente, ma FUJI tra le proprie proposte di storage ha una offerta comprensiva di software, il quale software è in qualche modo concorrente alle soluzioni VMWare.

Mentre SOIEL ( www.soiel.it ) organizzava l’evento ed ha condotto una indagine riguardo a come le aziende percepiscano il problema dello storage in un contesto dove la quantità di dati è in costante aumento.

Ora ho scritto qualcosa.

My beloved DevOps tool, gnu make

Oh, yes, there is a lot of tool around for Really DevOps(TM).

But I just want to automate the task to sync remote folders with my working tree, anything else is managed with git, and that’s fine.

So I thought: rsync + fuse (file system user level mounting, I hate to launch filezilla or similae)

But I really does not need gulp, grunt or anything else, a Makefile is enough, no?

put:
	sshfs remuser @ remhost.domain.com:/home/remuser /home/daniele/remhostuser
	rsync -artv --exclude-from='rsync_exclude_from.txt' . /home/daniele/remhostuser/MyApp/
	fusermount -u /home/daniele/remhostuser

Then in the excude file:

Makefile
*~
.git
Docs
rsync_exclude_from.txt

Well I just wrote 2 files, a 4-lines file and a 5-lines files, one time. And for upload my code I just have to run:

make put

 and …

everything else are just TMs

Qualche difficoltà nel capire nel php l’implementazione della closure

In javascript tutto è più semplice. Ora sto usando/imparando Phalcon e il secondo esempio/tutorial è strambo un bel po’ (INVO).

Definisce una class Services, derivata da \Base\Services, a sua volta derivata da \Phalcon\Di\FactoryDefault.

In \Base\Services è definito un metodo, bindServices(), che cicla sui metodi definiti per la classe stessa, controllando che abbiano almeno 4 lettere, e che le prime 4 siano ‘init’. In caso affermativo fa … meglio incollare il codice:

    protected function bindServices()
    {
        $reflection = new \ReflectionObject($this);
        $methods = $reflection->getMethods();
        
        foreach ($methods as $method) {

            if ((strlen($method->name) > 10) && (strpos($method->name, 'initShared') === 0)) {
                $this->set(lcfirst(substr($method->name, 10)), $method->getClosure($this));
                continue;
            }
            
            if ((strlen($method->name) > 4) && (strpos($method->name, 'init') === 0)) {
                $this->set(lcfirst(substr($method->name, 4)), $method->getClosure($this));
            }

        }
        
    }

 

strano no? Poi in \Services vengono definiti i vari metodi initDb, initUrl, … e così via.

Elegante? Forse, ma oscuro per me, io non voglio scrivere così.

Innanzi tutto voglio ereditare direttamente da \Phalcon\Di\FactoryDefault, che sia chiaro. Poi se aggiungo una qualche inizializzazione che sia esplicita e non implicita nel nome, perché altrimenti mi sa di magico e la magia la si maneggia male, secondo me.

Ecco, va a finire che il mio bindServices() è:

    private function bindServices()
    {
        $reflection = new \ReflectionObject($this);
	$this->set('url', $reflection->getMethod('initUrl')->getClosure($this));
        
    }

 

avrei la tentazione di ciclare, ma forse così:

    private function bindServices()
    {
        $reflection = new \ReflectionObject($this);
	$services = ['url' => 'initUrl','db'=>'initDb'];
	foreach($services as $service => $method) {
		$this->set($service, $reflection->getMethod($method)->getClosure($this));
	}
    }

 

almeno definizione e uso sono vicini, e si capisce, e si capisce anche come si usa ReflectionObject (ed esiste il metodo getMethod(), senza ‘s’ finale!).

A beh, riguardo al riuso, potrei anche capirlo, ma allora basterebbe definire $services come una proprietà dell’oggetto che eredita

 

    protected $services = [];
    protected function bindServices()
    {
        $reflection = new \ReflectionObject($this);
	foreach($this->services as $service => $method) {
		$this->set($service, $reflection->getMethod($method)->getClosure($this));
	}
    }

(ma cosa vuoi riusare poi?) comunque trovo una pessima idea andare a fare magheggi con i nomi di metodi su di una classe che eredito da un framework, il quale potrebbe introdurre altri metodi in futuro e costringermi ad aggiungere eccezioni (al magheggio). Vero è che se aggiungeressero initUrl a \Phalcon\Di\FactoryDefault dovrei comunque rivedere il codice, ma solo cambiando l’array services e il nome del mio metodo, non andare ad aggiungere uno special-case nel loop.

Non c’è, sembra, un modo per fare il binding di un method al proprio oggetto, ovvero come sarebbe in javascript passare il nome del metodo tipo this.methodName.bind(this).

Le funzioni native accettano array($this, ‘methodName’), ma Phalcon vuole una Closure, altro non lo digerisce.

p.s.: il codice a cui mi riferisco è qui : https://github.com/phalcon/invo in particolare https://github.com/phalcon/invo/blob/master/app/library/Base/Services.phphttps://github.com/phalcon/invo/blob/master/app/Services.php

DBus vs ZeroMQ

Cerco un message system. Quello che vorrei è poter sottoscrivere un servizio e ricevere i messaggi, oppure semplicemente chiedere ad un processo con diritti maggiori alcune informazioni o di compiere azioni, senza dover aprire una porta tcp e gestire tutto a mano.

Devo fare delle azioni sull’hardware e penso che forse DBus già ha qualcosa fatto.

Cosa trovo:

 

dbus-send --session           \
  --dest=org.freedesktop.DBus \
  --type=method_call          \
  --print-reply               \
  /org/freedesktop/DBus       \
  org.freedesktop.DBus.ListNames

e

dbus-send --system            \
  --dest=org.freedesktop.DBus \
  --type=method_call          \
  --print-reply               \
  /org/freedesktop/DBus       \
  org.freedesktop.DBus.ListNames

rif.: http://unix.stackexchange.com/questions/46301/a-list-of-available-dbus-services

mi da l’idea di cosa sia dbus, un sistema che permette di registrare un servizio, di sottoscrivere un servizio e ricevere messaggi, organizzati in maniera gerarchica (es.: org.freedesktop.DBus), mandare messaggi, aprire una sessione, eventualmente con tanto di autenticazione.

Ad esempio, con DBus + udev potrei fornire un servizio che mi dice se qualcuno ha attaccato un dispositivo usb, eventualmente permettendo al client di richiedere delle azioni da intraprendere (chiedere che tipo di dispositivo è, elencare le azioni disponibili fornite dal driver … beh, non esageriamo con la duttilità, potrebbe diventare complesso). Ancora, con DBus + UDisk2 posso aprire la finestra di una cartella di un dispositivo di storage appena inserito, ad esempio.

Se ho un dispositivo piccolino, senza desktop, tipo RaspberryPI, posso usare dbus e la sua interfaccia node, https://github.com/sidorares/node-dbus, per capire se è stato inserito un dispositivo usb, in tal caso presentare il servizio disponibile sulla interfaccia web (usando websocket (push) o usando una richiesta attiva) e permettendo di intraprendere azioni. Se ad esempio inserisco un device di storage, posso metterlo a disposizione come target per un trasferimento, se inserisco una webcam potrei fornire lo stream video su di una porta o servizio, etc.

Ovviamente ci sono binding DBus per diversi linguaggi. Quel che ho capito è che non è strettamente necessario il concetto di desktop per farne uso, è qualcosa di complesso, un IPC, con le sue caratteristiche, pro e contro, ma con dei servizi di partenza standard che potrebbero essere interessanti per arrivere dritti al punto. DBus != Desktop bus, anche se è stato pensato/creato per questo.

Approfondisco un po’ perché mi interessa usare ZeroMQ per altri progetti, pare, http://comments.gmane.org/gmane.comp.freedesktop.dbus/12827, che DBus sia meno efficiente di ZMQ, e anche di CORBA, ma ha altre caratteristiche necessarie come la gestione della sicurezza, ma deficia di altre presenti in ZMQ.

ZMQ è più articolato di quanto mi aspettassi. Ad esempio ci sono diverse modalità di aprire un canale, ovvero diversi patterns. Ma in definitiva è facile da capirsi.

La conclusione è che andrò ad utilizzare ZMQ per un piccolo applicativo, sostanzialmente perché ZMQ è quello che abbiano pianificato di usare anche in un altro progetto che ha bisogno di essere distribuito su più macchine, ma l’aver dato un’occhiata a DBus l’ha reso meno misterioso.

wordpress do not redirect after post

Problem seems to be reported here and there, but I can not found what I really need to fix this during the morning:

https://wordpress.org/support/topic/redirect-after-post?replies=2

https://wordpress.org/support/topic/redirect-doesnt-work-1

… nope, nothing. I found this:

http://wordpress.stackexchange.com/questions/76991/wp-redirect-not-working-after-submitting-form and second reply:

 

add_action( 'wp_loaded', 'wpa76991_process_form' );
function wpa76991_process_form(){
    if( isset( $_POST['my_form_widget'] ) ):
        // process form, and then
        wp_redirect( get_permalink( $pid ) );
        exit();
    endif;
}

but it does not work, I ask myself why, and try to print the required url, that was in fact from menu_page_url(), but this is in administration menu, so, after some investigation I found out that the good hook is ‘admin_menu

So:

add_action( 'admin_init', 'myplugin_admin_form_process' );

function myplugin_admin_form_process()
{
  if(!isset($_POST['form_id']) || $_POST['form_id'] != 'myplugin_admin_form') {
    return;
  }
  if($_POST['action'] = '....') {
    process_post();
    wp_redirect(menu_page_url( 'myplugin-admin-main', false ));
    exit();
  }
}

and it worked

javascript Promise chaining: augmenting the unique argument

There are two things that, IMHO, make code cleaner when using Promises Idioma:

  1. use an unique object argument (and its attributes as you would use argument legacy)
  2. return resolve with the object given as argument augmented by attribute of the action executed by the function

i.e., say I want to ask db for data about a person, I define the method (function) that got an object {person: {personstruct}} and return the augmented object {person:{personstruct}, contactdata: {contactdatastruct}}

 

function addContactData(o){
   return new Promise(function(resolve,reject) {
     //check existense of attributes, reject with reason
     mysql.query({sql:"select * from cdata where pid=?",values:[o.person.pid]},function(err,rows) {
       if(err) {
          o.err = err.toString();
          reject(o);
       } else {
          if(rows.length>0) {
            o.contactdata = rows[0];
          } else {
            o.contactdata = null;
          }
          resolve(o);
       }
     });
   });
}

 That could look not very optimized but it is a practice that make things look cleaner and consistent. Pros:

  1. testing is simply composable, just pass some good object and test if it augments: there is an idioma testing
  2. you have no surprise
  3. you have not to deal with “how do I access previous promise result in a .then() chain” problem, where Bergi show some drawback with this solution, that really are worth paying for the cleaness

Also object is passed by reference, and test on required attributes is a matter of enstabilish a protocol, like attrlist with type required.

Note: image source http://www.geograph.org.uk/photo/1804846 chain at the launch of SS Great Eastern (sailing ship), Isle of Dogs, England