Come dare fastidio a chi ascolta la radio in spiaggia ( a volume molto alto ) e interrompe il vostro momento zen

Un saluto estivo a tutti i lettori di devopsrecipes.info ūüėČ

Le mie vacanze si avvicinano e presto potrò finalmente allontanarmi dal caos cittadino… Nel mio zaino, oltre ad set di birre ricercatissime ( una paio di Peroni da 66 ) quest’anno ci sarà anche un trasmettitore radio FM pirata, nel caso qualcuno disturbi il mio sonno sentendo la radio ad alto volume… Se vi siete drogati, è molto probabile che la musica che sentite non è trasmessa da alcun vicino, per cui andate a prendervi un Calippo.

listening-to-old-time-radio-on-the-beach

Procuratevi pi√Ļ o meno le seguenti cose, oppure compratevi un trasmettitore radio su Amazon ( per√≤ sappiate che √® poco fico comprarlo gi√† fatto o scaricare app )

  1. Un Raspberry PI
  2. Un alimentatore portatile per smartphone ( meglio se ad energia solare)
  3. Una pennetta wireless
  4. Uno script in php per la gestione tramite interfaccia web (https://github.com/lucky-sideburn/piratepiwave.git)
  5. Il software https://github.com/rm-hull/pifm per l’erogazione del segnale FM
  6. Il…

View original post 203 more words

Advertisements

Docker images pruning with Openshift Origin

openshift-card

In order to test the Docker images pruning with Openshift Origin I made the following test.

Environment:

  • Two nodes, one master + infra and a workload node.
  • Cluster version: Openshift Origin 3.6

First of all I have built a Docker image based on NodeJS within a large file. The file.out is of 50M and after compression it decreases little.

Structure of my NodeJS app

[root@origin-master nodeapp]# ls -lhas

total 51M

 0 drwxr-xr-x. 2 root root 106 May 27 16:41 .

 0 drwx------. 6 vagrant vagrant 228 May 27 09:09 ..

4.0K -rw-r--r--. 1 root root 136 May 27 16:22 Dockerfile

4.0K -rw-r--r--. 1 root root 261 May 27 16:18 create_fake_images.sh

 50M -rw-r--r--. 1 root root 50M May 27 16:18 file.out

4.0K -rw-r--r--. 1 root root 265 May 27 09:09 package.json

4.0K -rw-r--r--. 1 root root 539 May 27 15:19 server.js

The Dockerfile is very simple!

[root@origin-master nodeapp]# cat Dockerfile

FROM node

# Create app directory

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 8080

CMD [ "npm", "start" ]

The following script helped me to generate many images with additional and differents layers. Each iterations copy the 50M file inside the image.

for i in $(seq 1 1000)

do

 echo "RUN echo $i" >> Dockerfile

 echo "COPY file.out ./$i.out" >> Dockerfile

 docker build -t docker-registry-default.origin.local/test/nodeapp:latest .

 docker push docker-registry-default.origin.local/test/nodeapp:latest

done

Let's see how the Docker registry folder increase size during create_fake_images.sh execution.

1a4c7633d886: Pushing [=======> ] 8.325 MB/52.43 MB

e36035decad2: Pushing [=======> ] 7.768 MB/52.43 MB

bb1e26b5f124: Pushing [=======> ] 7.768 MB/52.43 MB

13c3d2712668: Pushing [===========> ] 11.67 MB/52.43 MB

dbc4876ab96c: Pushing [=======> ] 8.327 MB/52.43 MB

[root@origin-master vagrant]# du -chs /data/origin/

 782M /data/origin/

 782M total

[root@origin-master vagrant]# du -chs /data/origin/

 956M /data/origin/

 956M total

[root@origin-master vagrant]# du -chs /data/origin/

 1.2G /data/origin/

 1.2G total

Describing image stream nodeapp we can see the latest images pushed to the registry

[root@origin-master nodeapp]# oc describe is

Name: nodeapp

Namespace: test

Created: 2 hours ago

Labels: <none>

Annotations: <none>

Docker Pull Spec: docker-registry.default.svc:5000/test/nodeapp

Image Lookup: local=false

Unique Images: 5

Tags: 1

latest

 pushed image

* docker-registry.default.svc:5000/test/nodeapp@sha256:6f517f2bd667280587daebd57c456c723df4e97d72903100cad441821203e4ec

 22 seconds ago

 docker-registry.default.svc:5000/test/nodeapp@sha256:421155780252a908de9c4968c65a508c65b12b259a6248278b73dd20edee20fb

 About a minute ago

 docker-registry.default.svc:5000/test/nodeapp@sha256:b26f1d2cac95a73632891a6cfec875baed0b1a4165c381e59e0ce4d1bfc403f9

 About a minute ago

 docker-registry.default.svc:5000/test/nodeapp@sha256:6d6f63093aae64198fb1d7af2cd2a361cec991817c8e6944910cb84420a52c1b

 20 minutes ago

 docker-registry.default.svc:5000/test/nodeapp@sha256:6e82ae61a154788ff70ff3ed69cf3a088845e0c7c2d1441de4123c213a0f0116

 23 minutes ago

I changed the Dockerfile in order to have an image that does not import large file. So I have built and pushed the following Docker image

[root@origin-master nodeapp]# cat Dockerfile

FROM node

# Create app directory

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . .

EXPOSE 8080

CMD [ "npm", "start" ]

Let’s start to prune

tree-pruning1

  1. Delete old deployments
[root@origin-master nodeapp]# oc adm prune deployments --orphans --keep-complete=1 --keep-failed=1 --keep-younger-than=1m

Dry run enabled - no modifications will be made. Add --confirm to remove deployments

NAMESPACE NAME

test nodeapp2-23

test nodeapp2-22

test nodeapp2-21

test nodeapp2-20
  1. Prune the unused images and keep only one revision
[root@origin-master nodeapp]# oc adm prune images --keep-tag-revisions=1 --keep-younger-than=1m --confirm

Deleting references from image streams to images ...

STREAM IMAGE TAGS

test/nodeapp sha256:6e82ae61a154788ff70ff3ed69cf3a088845e0c7c2d1441de4123c213a0f0116 latest

test/nodeapp sha256:421155780252a908de9c4968c65a508c65b12b259a6248278b73dd20edee20fb latest

test/nodeapp sha256:b26f1d2cac95a73632891a6cfec875baed0b1a4165c381e59e0ce4d1bfc403f9 latest

Deleting registry repository layer links ...

REPO LAYER LINK

test/nodeapp sha256:3de138bf364bf3e2684c78468d07a0e2ca786ba08f83bd1b7e3373a1e0b407e5

test/nodeapp sha256:a75ed4d808fc563081de632debf91580a6dbe6d694971ca6888b5be4433f55cc

test/nodeapp sha256:677e3bfb00ad311212b46be4ddb20f5b762765fef676c6d4a85e5dbcb943c4a4

test/nodeapp sha256:29510362ff8e174edf88563f6099141b9e82efd5cd48b14aeaa74fea532e6d43

test/nodeapp sha256:35dc109c74dfcab9f1f027ccc1404e7ef3f524d6efea226e3920959051819f2c

test/nodeapp sha256:f3d40164b23c42356d717da92b91774402632a8df22cd5ddfb7926fc3a7292f6

test/nodeapp sha256:fe03b24c2c84648d09331dbd72a8065b8ed550be991155edc72ad1166f1ef666

test/nodeapp sha256:8eaf1a821a6b8a2e325cebce83311c5d3b33427140d84954f504ed59bab51109

test/nodeapp sha256:684c30e67a270d2115cb4be1c9712193bf0b4393ffa04b3c625e76fadd6bda12

test/nodeapp sha256:7d6ad63a8e94a938a95fa1e27106bbc7ecfa3680b3ff3a11c7bdb43ae610eb18

test/nodeapp sha256:e1614bf81372b99eb86c74ac9c023c01077061db81c4daeaf6683e27299e48cc

test/nodeapp sha256:a92bff6ede96a89a94fe2ca794115e1c374312d05e895698e6b1638c3b647645

test/nodeapp sha256:2d9ccccdee639671c6cb24110e529b738535453a3ccdf68989ac31ea6894929d

test/nodeapp sha256:1e920f3f2676bc50c60a95c9d8710cb91429ab07278616c02680b0f38af2d224

test/nodeapp sha256:90b58c4583c3de52b6f6762c83a02d42dd18747a2541bafb483a9cdbc5e55f8b

test/nodeapp sha256:d041de45e8895ee77b4e6ba112959e361d888b5694910b44f54fb88f0ef3fb4f

Deleting registry layer blobs ...

BLOB

sha256:3de138bf364bf3e2684c78468d07a0e2ca786ba08f83bd1b7e3373a1e0b407e5

sha256:a75ed4d808fc563081de632debf91580a6dbe6d694971ca6888b5be4433f55cc

sha256:677e3bfb00ad311212b46be4ddb20f5b762765fef676c6d4a85e5dbcb943c4a4

sha256:29510362ff8e174edf88563f6099141b9e82efd5cd48b14aeaa74fea532e6d43

sha256:35dc109c74dfcab9f1f027ccc1404e7ef3f524d6efea226e3920959051819f2c

sha256:f3d40164b23c42356d717da92b91774402632a8df22cd5ddfb7926fc3a7292f6

sha256:fe03b24c2c84648d09331dbd72a8065b8ed550be991155edc72ad1166f1ef666

sha256:8eaf1a821a6b8a2e325cebce83311c5d3b33427140d84954f504ed59bab51109

sha256:684c30e67a270d2115cb4be1c9712193bf0b4393ffa04b3c625e76fadd6bda12

sha256:7d6ad63a8e94a938a95fa1e27106bbc7ecfa3680b3ff3a11c7bdb43ae610eb18

sha256:e1614bf81372b99eb86c74ac9c023c01077061db81c4daeaf6683e27299e48cc

sha256:a92bff6ede96a89a94fe2ca794115e1c374312d05e895698e6b1638c3b647645

sha256:2d9ccccdee639671c6cb24110e529b738535453a3ccdf68989ac31ea6894929d

sha256:1e920f3f2676bc50c60a95c9d8710cb91429ab07278616c02680b0f38af2d224

sha256:90b58c4583c3de52b6f6762c83a02d42dd18747a2541bafb483a9cdbc5e55f8b

sha256:d041de45e8895ee77b4e6ba112959e361d888b5694910b44f54fb88f0ef3fb4f

Deleting registry repository manifest data ...

REPO IMAGE

test/nodeapp sha256:6e82ae61a154788ff70ff3ed69cf3a088845e0c7c2d1441de4123c213a0f0116

test/nodeapp sha256:421155780252a908de9c4968c65a508c65b12b259a6248278b73dd20edee20fb

test/nodeapp sha256:b26f1d2cac95a73632891a6cfec875baed0b1a4165c381e59e0ce4d1bfc403f9

Deleting images from server ...

IMAGE

sha256:6e82ae61a154788ff70ff3ed69cf3a088845e0c7c2d1441de4123c213a0f0116

sha256:421155780252a908de9c4968c65a508c65b12b259a6248278b73dd20edee20fb

sha256:b26f1d2cac95a73632891a6cfec875baed0b1a4165c381e59e0ce4d1bfc403f9

Check the size of  registry folder

[root@origin-master nodeapp]# du -chs /data/origin/
608M /data/origin/
608M total

Ok from 1.6gb we went down to 608M !

Provisioning di grandi monoliti con Vagrant

Il post di oggi vorrei usarlo per tenere traccia di alcune metodologie che sto usando per il provisioning di stack pesanti e che richiedono tempi lunghissimi.

Il software interessato rientra nella categoria del “monolite”. Lo stack monolitico √® una sorta di amico enorme e per portarlo in giro bisogna prendere determinate precauzioni.

√ą tipo Zangief…

hqdefault

Per il raggiungimento del risultato finale, ovvero il bootstrap di ambienti completi, sto implementando un giro di provisioning fatto da cookbook Chef, script shell e Rubygem custom.

Alcuni ostacoli del progetto:

  1. Per un provisioning completo ci vogliono pi√Ļ di 3 ore
  2. La fase di installazione e configurazione è composta da centinaia di esecuzioni di script, chiamate a servizi REST e numerosi riavvii di servizi systemd. Tutto deve essere rigorosamente idempotente.
  3. Gli errori durante il provisioning sono da evitare assolutamente. Ripartire nel mezzo dell’installazione non √® mai come partire da zero.

La scelta del provisioner e per cosa usarlo

Di base, a meno che non ci siano vincoli progettuali, siamo in grado di fare quasi tutto con i pi√Ļ importanti configuration management tool come Chef, Puppet e Ansible.

√ą importante capire cosa far fare al provisioner e cosa no.¬†Alcune operazioni che sono specifiche per il mio ambiente di laboratorio le metto tranquillamente in blocchi shell script (che alla fine √® anch’esso un provisioner di Vagrant)

 
 $script = <<-SCRIPT echo I am provisioning... date > /etc/vagrant_provisioned_at
 SCRIPT

Vagrant.configure("2") do |config|
 config.vm.provision "shell", inline: $script
 end

Per usare o meno un proxy pu√≤ essere utile una semplice variabile d’ambiente.

if ENV['NO_CUSTOMER_PROXY']
 config.vm.provision 'shell',
 inline: '> /etc/profile.d/proxy.sh'
 config.vm.provision 'shell',
 inline: '> /etc/environment'
 else
 config.proxy.http = 'http://CUSTOMER.PROXY.LOCAL:8080'
 config.proxy.https = 'http://CUSTOMER.PROXY.LOCAL:8080'
 config.proxy.no_proxy = ''
 end

 

Roadmap delle box

Il punto √® che non vogliamo fare e rifare¬†il lunghissimo provisioning tutte le volte ma poter “debuggare” stati diversi della macchina.
Per esempio, nel caso esistano i seguenti possibili stati:

  1. macchina con prerequisiti installati, aggiornamenti OS e personalizzazioni.
  2. macchina con monolite installato.
  3. macchina con monolite configurato.
  4. macchina con applicazioni del monolite configurate.

Rifare tutto da zero pu√≤ richiedere parecchio tempo per cui ho utilizzato il “package” di Vagrant…

vagrant package --base $id --output os_ok.box; vagrant box os_ok.box
vagrant package --base $id --output monolite_ok.box; vagrant box add monolite_ok.box
vagrant package --base $id --output monolite_configurato.box; vagrant box monolite_configurato.box
vagrant package --base $id --output monolite_con_applicazioni_configurate.box; vagrant box add monolite_con_applicazioni_configurate.box

All’occorrenza, nel Vagrantfile e nel bocco relativo alla vm, ho usato la box che mi serviva in determinato punto.

Archivi pesanti in /vagrant

Durante il provisioning ho avuto bisogno di scaricare da locazioni remote archivi anche di grandi dimensioni.

Questo durante le prove¬† non √® performante per cui i puntamenti, dei ruoli Chef nel mio caso,¬† sono tutti verso src: “file:////vagrant/foo.tar.gz”. Naturalmente √® opportuno dichiararli nel .gitignore.

Ciao

il mio ultimo libro…

Nel tempo libero ho iniziato a scrivere libri e uno di questi ho pensato di pubblicarlo…

Il protagonista di Skynet (così ho chiamato il libro) è un giovane hacker romano che si troverà a dover combattere un potere occulto che cerca di danneggiare Roma fin dai tempi della sua fondazione.

Si troverà faccia a faccia con le temibili sorelle della Toga Nigra, ovvero delle combattenti molto arrabbiate per il Ratto delle Sabine e che negli anni sono diventate le attuali suore.

Si, il racconto parla di suore hacker e combattimenti alla Matrix.

Ho optato per alcuni luoghi di internet dove condividere il libro

  1. su Github
  2. come ebook su Amazon
  3. come pdf

68190-skynet-il-perche-a-roma-non-funzionano-le-cose

Saluti!

DevopsTribe fase 1

Ho passato settimane a pensare quale nuovo nome dare al blog e alla fine ho scelto DevopsTribe.

Non √® stata una scelta facile vista l’enorme quantit√† di spunti che mi proponevo da solo. Il nome √® importante perch√® ti serve nel momento in cui condividi a qualcuno il tuo blog.

Tipo…

Hey ti passo il mio blog, titolohackeroso.com (√® rischioso avere la parola hacker nell’indirizzo… Fa troppo bimbo cibernetico indaco).

Hey ti passo il mio blog, comegestiresistemi.com (tipo wiki-how o qualcosa di aranzulliano… non ci piace).

Hey ti passo il mio blog, .com (serve un dominio di secondo livello).

Hey ti passo il mio blog, devops$qualcosa.it (questo mi piace. Faccio robe devops per cui ci sta).

Rimaneva quindi da definire il $qualcosa da attaccare a devops.

devops.it? (già preso..)
devopsattack.it (pare tipo ArtAttack, meglio di no)

head.jpg

devopsbofh.it (un nome, una contraddizione. Le operation agili contro la vecchia ma saggia scuola BOFH)

devopsparty.it (meglio un rave party che un party di smanettoni)

Alla fine ho scelto “tribe”.

Tribe come le mitiche Korg Electribe ES1 mkII e Korg Electribe EA1

…e tribe come la community che non pu√≤ mancare intorno alle tematiche su cui lavoro.

Tribe anche come RomeDevopsTribe che è un meetup e prossimamente mi piacerebbe organizzare e vedere in attività!

Bella

Cos’√® che fa di un Devops un Devops, signor Lebowski?

Vorrei parlare dei principi base del Devops che negli ultimi 5 anni ho potuto assimilare lungo il cammino.
Questo perchè dovevo preparare delle noiosissime slide. Mi serviva uno scopo, e un post sul blog ci sta tutto.

Inoltre, ho preso il dominio ziopinguino.it e sto pensando di migrare tutto il blog l√¨…

Quali sono i caratteri distintivi dell’area Devops?
Quali sono gli stereotipi e le considerazioni ricorrenti tipiche degli ambiti innovativi a cavallo tra buzzword e vera innovazione?

Cos’√® che fa di un devops un devops, signor Lebowski?

Essere una BaaS? Buzzword as a service?

Lo era sicuramente all’inizio una buzzword, ma ora non pi√Ļ.
Lo è se si legge solo nei blog di Devops, se non si è potuto toccarne con mano i benefici e i risultati.

Nei contesti dove c’√® stata una vera rivoluzione, la parola “Devops” descrive perfettamente figure professionali che svolgono attivit√† di collegamento tra i gruppi di sviluppo e le operation. Queste attivit√† si individuano nella forma di integrazioni di sistemi, sviluppo di piccoli tool e pubbliche relazioni (quando dai supporto…).

I Devops seguono tutta la catena di montaggio partendo dal codice fino al delivery e monitoring delle applicazioni.

Sono sistemisti che scrivono del buon codice, o programmatori che si muovono agili sulla shell.
Giocano con molte tecnologie e spesso trovano la parola chiave corretta su Google che gli risolve la giornata.

Stare attento a quando dici “alla vecchia maniera”?

Nell’IT non √® previsto l’utilizzo di espressioni come “ai tempi miei” o “come si faceva un tempo”.

Un paio di scarpe fatto alla vecchia maniera √® resistente e di qualit√†, ma un sistema fatto cos√¨, pur essendo stabile, verrebbe inevitabilmente visto come “anziano”.

Saggio in quanto anziano, ma con la barba bianca e lunga al posto dei baffetti hipster.
Non entro in merito sulla correttezza di tale giudizio, ma è innegabile dire che in molti contesti ciò accade.

Molte delle cose fatte un tempo funzionano egregiamente anche oggi e comunque le usiamo volentieri.

Dir√≤ solo una cosa “Bash Rocks!”.

bash-logo-web

A volte però il cambiamento è fortemente consigliato.

Ad esempio, non √® possibile sostituire un configuration management tool come Chef o Puppet con dello shell scripting. Concetti come idempotenza e auto-discovery richiedono comunque un effort nella loro realizzazione. E’ meglio quindi usare strumenti supportati da una community, piuttosto che scrivere componenti di cui poche persone mantengono la memoria storica.

Essere preparato su GIT?

Non può mancare una conoscenza approfondita di Git.
Servir√† quando uno sviluppatore ti chieder√† aiuto o quando prenderai in giro il tuo amico perch√® lavora dove ancora distribuiscono il codice e le nuove release su aeroplanini di carta. Sull’ala destra c’√® il messaggio di commit e su quella sinistra la versione. Se l’aeroplanino ritorna indietro per via di forti correnti contrarie hai fatto rollback.

Il pattern di “infrastructure as code” non pu√≤ mancare e quindi serve “versionare”.

E’ importante sapere che lavoriamo in un ambiente deterministico e che possiamo pilotare piattaforme tramite codice.

Cos√¨ “ciao ciao” documentazione, si legga il playbook di Ansible o il cookbook Chef (tutto questo in mondo immaginario…il “documentone” verr√† sempre chiesto, per√≤ ultimamente sono sceso a compromessi per cui anche un bel markdown fatto bene pu√≤ andare)

Ho imparato che tutto il lavoro svolto deve essere portabile. Un modulo Puppet o un cookbook Chef deve essere chiaro e leggibile. Sembra scontato ma non lo è.
Spesso automatismi e meccanismi agili all’interno delle nostre infrastrutture risiedono solo nella nostra conoscenza perch√® le abbiamo sviluppate noi. Questo √® poco Devops, perch√® diventa comunque un silos. Un “agile silos”.

Scegliere i tool con senso critico?

Il landscape dei tool Devops è enorme.
E’ costellato di programmi che fanno a volte la stessa cosa e che competono a suon di stellette su github e loghi accattivanti.

Alcuni di essi sono veramente utili ed √® divertente contribuire alle loro community. Altri vengono proposti “a cazzo di cane” in conversazioni di gruppo dove il tema parrebbe essere “spariamo a nomi a caso”.

Una specie di cyber flusso di coscienza << kubernetes! Prometheus!! Openshift!! Spark!! Mesos! Puppy Linux!! >>

Comunque… un Devops, come sceglie i tool da usare nell’opensource?

Evitare sicuramente di giudicare solo in base alla popolarità.

Se tale software viene utilizzato e contemporaneamente lo si reputa mediocre, si dovrebbe contribuire con quello che pensiamo possa portare un miglioramento.

L’opensource del resto √® un qualcosa di tutti, potrebbe in un futuro prossimo diventare un bene di tutti. Forse il paragone √® esagerato, ma migliorare il software contruibuendo √® come pulire una strada per il bene della comunit√†, perch√® hai necessit√† di percorrerla e se la percorri imprecando sembri un predicatore matto.

Condividere il knowledge, abbattere i silos e fare team?

Assolutamente si. Senza questi tre elementi probabilmente il mio lavoro sarebbe molto noioso. Sono punti fondamentali.

Mi viene in mente un modo di dire che ho coniato qualche minuto fa per cui non ne certifico la concretezza e neanche un senso logico: se detieni l’ownership di una procedura noiosa, non detieni l’ownership del tempo lavorativo mentre la fai.

Intendo che se ci è richiesto di intervenire solo perchè conosciamo una procedura che noi e solo pochi eletti siamo in grado di eseguire siamo distanti anni luce dalle metodologie Devops.

Non siamo owner di quel tempo che impieghiamo a concludere il task perchè qualcuno prima di noi ha deciso quanto sarebbe dovuto durare scrivendo passo passo un documento procedurale.

E’ compito di un Devops, a mio parere, arrivare al risultato scegliendo la soluzione pi√Ļ smart possibile.

Ecco tutto questo per√≤ dimenticatelo il venerd√¨ pomeriggio… ben venga il noioso, il ripetivo e pure il “se funziona non lo toccare”.

E pure il “eh vecchio mio, mi ricordo quando mettevamo il notepad in cluster…”.

unnamed high-availabilityunnamed.png

Be pushy With Chef from Ruby application using “Foodpusher” gem.

Hi guys,

recently for some work tasks I needed to interact with Chef Push Jobs not from knife command line tool but through ruby code…

Screen Shot 2017-08-14 at 11.43.02

For this reason, I decided to write a Ruby gem and I hope it will be useful for the Chef community ūüôā

You can find code and instructions here https://github.com/lucky-sideburn/foodpusher.

Below some code, just to have a look about how to use of this gem.

Let’s say you want push chef-client execution on client01.local and chef-server.

require 'chef/knife'
require 'chef/knife/foodpusher'

job = { 'command' => 'chef-client',
        'nodes' => ['client01.local', 'chef-server'],
        'quorum' => 1,
        'capture_output' => false,
        'env' => {} }

Chef::Config.chef_server_url = 'https://chef.devops.foobar.lan/organizations/chef'
Chef::Config.client_key = '/vagrant/chef-server.local/.chef/chef.pem'
Chef::Config.node_name = 'chef'
Chef::Config.ssl_verify_mode = :verify_none
pusher = FoodPusher.new(job)

# Start Job
myjob = pusher.start
puts "Job uri #{myjob}"
status = (pusher.status myjob)['status']

# Check Job Status
while status == 'running'
  status = (pusher.status myjob)['status']
  puts status
  sleep 1
end

# Check Node Status
(pusher.node_status job['nodes']).each do |result|
  puts result
end

Launch the script and that’s the output

Job uri {"uri"=>"https://chef.devops.foobar.lan/organizations/chef/pushy/jobs/336d0bf2dc771d3127dffead469381b5"}
running
running
running
running
running
complete
{"node_name"=>"client01.local", "status"=>"online", "availability"=>"available"}
{"node_name"=>"chef-server", "status"=>"online", "availability"=>"available"}

Thanks!