Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Workflow per gestione di container di sviluppo per applicazione Django #90

Open
edigiacomo opened this issue Mar 28, 2023 · 5 comments
Open
Assignees
Labels
question Further information is requested

Comments

@edigiacomo
Copy link
Member

Una premessa: questa non è una issue ma un appunto su come gestire lo scenario descritto sotto usando moncic-ci come tool di test. In fondo, ho messo un po' di considerazioni/dubbi.

Lo scenario è il seguente: ho un'applicazione Django in un repository git che vorrei testare man mano che faccio modifiche usando monci-ci e vorrei che il tutto rimanesse autoconsistente, quindi con un git clone posso fare le stesse operazioni su un altro server, senza setup particolari.

Ho a disposizione un playbook Ansible per il provisioning dei vari ambienti (per ora, deploy e test): nel caso di quello di test i task fondamentali sono:

  1. Installazione pacchetti
  2. Creazione DB Postgres
  3. Configurazione DB Postgres
  4. Installazione virtualenv
  5. Esecuzione test

Al momento, ho messo in piedi il seguente workflow:

  1. Creo il file YAML dell'immagine in .moncic-ci/simclog2.yaml
  2. Faccio il bootstrap make bootstrap
  3. Eseguo il provision make provision-development
  4. Eseguo il test con monci run -I .moncic-ci -W . bash -c "DJANGO_SETTINGS_MODULE=logmetarpa.settings.development python3 manage.py test

Il Makefile risultante è

IMAGEDIR=.moncic-ci
IMAGENAME=simclog2

bootstrap: $(IMAGEDIR)/.boostrap-state

$(IMAGEDIR)/.boostrap-state: $(IMAGEDIR)/$(IMAGENAME).yaml
	monci bootstrap -I $(IMAGEDIR) --recreate $(IMAGENAME)
	touch $@

provision-development: $(IMAGEDIR)/.provision-development-state

$(IMAGEDIR)/.provision-development-state: development.yml
	monci run -I $(IMAGEDIR) --bind-ro $(CURDIR):/src --maintenance --root simclog2 ansible-playbook -i 127.0.0.1 -c local -l 127.0.0.1 -e 'ansible_python_interpreter=/usr/bin/python3' /src/development.yml
	touch $@

test: provision-development
	monci run -I $(IMAGEDIR) -W . simclog2 bash -c "cd web/logmetarpa && DJANGO_SETTINGS_MODULE=logmetarpa.settings.development /venv/bin/python3 manage.py test"

Note:

  • Il provisioning viene separato dal bootstrap perché non ho idea di come eseguire il playbook Ansible dal file YAML dell'immagine (né se sia possibile).
  • Il provisioning viene montando il repository con --bind-ro perché le opzioni -W, -w, --clone non vanno d'accordo con --maintenance: il comando monci --root -W . --maintenance fallisce perché prova a creare l'utente 1000 (forse perché tra le modifiche salvata dall'opzione --maintenance c'è anche il mount della directory?)
  • Se volessi testare il deploy dell'applicazione dovrei avere una seconda immagine, perché ho "sporcato" quella presente con l'opzione --maintenance. Ci sono modi più furbi di create un'immagine base simclog2.yaml e due derivate simclog2-production.yaml e simclog2-development.yaml e poi usare queste ultime?
  • Non mi sono ancora posto il problema di testare l'applicazione, ma si tratterebbe solo di fare il deploy su un'immagine (vedi punto precedente) e poi tenerla su con un monci run o monci shell.
@edigiacomo edigiacomo added the question Further information is requested label Mar 28, 2023
@edigiacomo
Copy link
Member Author

  • Non mi sono ancora posto il problema di testare l'applicazione, ma si tratterebbe solo di fare il deploy su un'immagine (vedi punto precedente) e poi tenerla su con un monci run o monci shell.

Per "testare l'applicazione" intendo qualcosa di analogo a uno staging environment, in cui posso interagire manualmente con l'applicazione web.

@spanezz
Copy link
Contributor

spanezz commented May 8, 2023

Ci sono tanti punti. Provo a rispondere quotandoli uno a uno qui, poi se finisce che github non si presta a discussioni articolate di questo tipo, possiamo organizzare una piccola call.

Il provisioning viene separato dal bootstrap perché non ho idea di come eseguire il playbook Ansible dal file YAML dell'immagine (né se sia possibile).

Al momento non è possibile, ma mi piacerebbe che lo fosse. Ci sono due possibili strategie:

  1. Farlo senza installare ansible nell'immagine. Qui c'è quello che so su come far girare ansible su macchine nspawn. È fattibile.
  2. Installare ansible dentro l'immagine. Qui c'è il problema di come passare tutti gli asset di cui ha bisogno ansible, e in realtà me l'hai risolto tu con l'idea di usare bind-ro per passare la directory del playbook, sperando che sia tutto autocontenuto lí dentro.

L'opzione piú pulita è di solito la 1. L'altro problema è che ansible è leeeento! Vorrei fare provisioning delle macchine con ansible invece di uno script hardcoded nella loro configurazione, ma la latenza nella manutenzione di molte immagini purtroppo diventa ingestibile :/

Il provisioning viene montando il repository con --bind-ro perché le opzioni -W, -w, --clone non vanno d'accordo con --maintenance: il comando monci --root -W . --maintenance fallisce perché prova a creare l'utente 1000 (forse perché tra le modifiche salvata dall'opzione --maintenance c'è anche il mount della directory?)

Prova a usare forward_user nella configurazione della macchina, per dire alla manutenzione di fare setup dell'utente una volta per tutte, e poi vedere se le altre opzioni iniziano ad andare

Se volessi testare il deploy dell'applicazione dovrei avere una seconda immagine, perché ho "sporcato" quella presente con l'opzione --maintenance. Ci sono modi più furbi di create un'immagine base simclog2.yaml e due derivate simclog2-production.yaml e simclog2-development.yaml e poi usare queste ultime?

Certo, usare extends. Fai la simclog2, poi crei simclog2-production.yaml che invece di dire distro: … dice extends: simclog2. Il bootstrap di simclog2-production partirà con uno snapshot della simclog2 invece che un bootstrap di una distribuzione da zero

Non mi sono ancora posto il problema di testare l'applicazione, ma si tratterebbe solo di fare il deploy su un'immagine (vedi punto precedente) e poi tenerla su con un monci run o monci shell

Esatto: al momento il namespace di rete è lo stesso del sistema host, per cui django lanciato dentro l'immagine è perfettamente accessibile da fuori.

Il rovescio della medaglia è che postgres che gira nel sistema host è perfettamente accessibile da dentro, e quindi rischi un conflitto sulle porte quando provi a tirar su django dentro alla macchina guest

@edigiacomo
Copy link
Member Author

Grazie @spanezz per i sempre ottimi suggerimenti!

Ti rispondo punto per punto, anche se sto creando ramificazioni che immagino porteranno a una call :)

Il provisioning viene separato dal bootstrap perché non ho idea di come eseguire il playbook Ansible dal file YAML dell'immagine (né se sia possibile).

  1. Farlo senza installare ansible nell'immagine. Qui c'è quello che so su come far girare ansible su macchine nspawn. È fattibile.
  2. Installare ansible dentro l'immagine. Qui c'è il problema di come passare tutti gli asset di cui ha bisogno ansible, e in realtà me l'hai risolto tu con l'idea di usare bind-ro per passare la directory del playbook, sperando che sia tutto autocontenuto lí dentro.

L'idea (almeno la mia) è quella di poter fare un git clone del progetto e poi un make check, quindi per me l'autocontenimento è una caratteristica desiderata e in entrambi i casi mi pare che possa essere soddisfatta.

L'opzione piú pulita è di solito la 1.

Concordo! E grazie per il link, inizio a sperimentare!

L'altro problema è che ansible è leeeento! Vorrei fare provisioning delle macchine con ansible invece di uno script hardcoded nella loro configurazione, ma la latenza nella manutenzione di molte immagini purtroppo diventa ingestibile :/

Drammaticamente verissimo, ma ha il vantaggio di essere uno standard de facto e inoltre potrei usare lo stesso playbook (credo) per tutti gli ambienti. Credo che l'unica soluzione sia comprare una spada di legno :)

Il provisioning viene montando il repository con --bind-ro perché le opzioni -W, -w, --clone non vanno d'accordo con --maintenance: il comando monci --root -W . --maintenance fallisce perché prova a creare l'utente 1000 (forse perché tra le modifiche salvata dall'opzione --maintenance c'è anche il mount della directory?)

Prova a usare forward_user nella configurazione della macchina, per dire alla manutenzione di fare setup dell'utente una volta per tutte, e poi vedere se le altre opzioni iniziano ad andare

Usando forward_user nella configurazione, il comando monci run -I $IMAGE_DIR -W . --root --maintenance $IMAGE_NAME ansible-playbook ... non dà errori. Tuttavia, nello scenario in cui l'utente fa un git clone && make check, dovrei generare a tempo di compilazione la configurazione dell'immagine per impostare forward_user: $(id -un). Ti devo aprire un bug sul fatto che senza forward_user va in errore?

Se volessi testare il deploy dell'applicazione dovrei avere una seconda immagine, perché ho "sporcato" quella presente con l'opzione --maintenance. Ci sono modi più furbi di create un'immagine base simclog2.yaml e due derivate simclog2-production.yaml e simclog2-development.yaml e poi usare queste ultime?

Certo, usare extends. Fai la simclog2, poi crei simclog2-production.yaml che invece di dire distro: … dice extends: simclog2. Il bootstrap di simclog2-production partirà con uno snapshot della simclog2 invece che un bootstrap di una distribuzione da zero

Bellissimo! ❤️

Non mi sono ancora posto il problema di testare l'applicazione, ma si tratterebbe solo di fare il deploy su un'immagine (vedi punto precedente) e poi tenerla su con un monci run o monci shell

Esatto: al momento il namespace di rete è lo stesso del sistema host, per cui django lanciato dentro l'immagine è perfettamente accessibile da fuori.

Il rovescio della medaglia è che postgres che gira nel sistema host è perfettamente accessibile da dentro, e quindi rischi un conflitto sulle porte quando provi a tirar su django dentro alla macchina guest

Mannaggia, vero! Così a occhio mi viene da dire che la possibilità più semplice è di configurare tutti i servizi della macchina su porte diverse, però va un po' in conflitto con lo spirito del git clone && make check (è possibile che la porta sia già presa).

@spanezz
Copy link
Contributor

spanezz commented May 10, 2023

Usando forward_user nella configurazione, il comando monci run -I $IMAGE_DIR -W . --root --maintenance $IMAGE_NAME ansible-playbook ... non dà errori. Tuttavia, nello scenario in cui l'utente fa un git clone && make check, dovrei generare a tempo di compilazione la configurazione dell'immagine per impostare forward_user: $(id -un). Ti devo aprire un bug sul fatto che senza forward_user va in errore?

Sí, il bug merita comunque aprirlo, cosí poi vediamo nella discussione del bug il modo migliore per gestire la cosa

Mannaggia, vero! Così a occhio mi viene da dire che la possibilità più semplice è di configurare tutti i servizi della macchina su porte diverse, però va un po' in conflitto con lo spirito del git clone && make check (è possibile che la porta sia già presa).

Questo è un problema che mi piacerebbe affrontare meglio, perché il caso d'uso è importante. Ci spostiamo in #22?

@edigiacomo
Copy link
Member Author

Dopo la chiacchierata con @spanezz (as in: lui parlava, io ascoltavo 😄 ), ho aggiornato il Makefile delle applicazioni mie applicazioni Django, usando monci image invece che la configurazione di un'immagine.

In questo modo, posso usare le directory standard di moncic-ci (/var/lib/machines, ~/.config/moncic-ci) e ottimizzare lo spazio con monci dedup.

.moncic-ci-bootstrap:
	monci image $(MONCI_IMAGE) extends rocky8
	monci image $(MONCI_IMAGE) install $(PACKAGES)
	touch .moncic-ci-bootstrap

check: .moncic-ci-bootstrap
	monci run -W . $(MONCI_IMAGE) bash -c "ansible-playbook ... && python3 runtest.py"

security-check: .moncic-ci-bootstrap
	monci run -W . $(MONCI_IMAGE) bash -c "bandit -r . && safety ..."

clean:
	monci remove --purge $(MONCI_IMAGE)
	$(RM) .moncic-ci-bootstrap .moncic-ci-bootstrap

.PHONY: check

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Further information is requested
Projects
None yet
Development

No branches or pull requests

3 participants