Di recente mi sono imbattuto in una creatura non molto popolare nel mondo del DevOps: i pipeline di Azure DevOps. Ho subito avvertito l'assenza di chiare istruzioni o articoli sull'argomento; non so a cosa sia dovuto, ma Microsoft ha chiaramente del lavoro da fare per promuovere questo strumento. Oggi costruiremo un pipeline per test automatizzati all'interno del cloud di Azure.
Quindi, la missione:
Abbiamo del software che viene costruito utilizzando lo stesso Azure DevOps, assemblato da un progetto su WIX. Se c'è interesse, scriverò anche di questo strumento. In effetti, si tratta di un modo più ottimizzato per l'automazione della creazione di installer per Windows, che sostituisce il tradizionale InstallShield. Quindi, il nostro software si compila con successo e genera un artefatto, un certo setup.exe, che installa l'applicazione nel sistema Windows. È necessario installare questa applicazione in una virtual machine simile a quella di produzione, copiare lì i test automatizzati preparati dal team di testing, eseguirli e recuperare i risultati per valutare se il branch sia buono o cattivo, prima di effettuare un merge. Tutto come su GitLab, solo che tramite l’altro….
Come ambiente di virtualizzazione per eseguire i nostri test, utilizziamo ovviamente Azure DevTest Labs, un'entità all'interno degli abbonamenti Azure, creata appositamente per eseguire diverse operazioni di test a un prezzo ragionevole.
1. Integrazione sul lato cloud
Per prima cosa, dobbiamo integrare il nostro DevTest Labs con Azure DevOps, per il quale è necessario un Service Principal, essenzialmente un account di servizio che consente ai pipeline di accedere al cloud e di creare / eliminare risorse per noi.
Andiamo all'abbonamento e troviamo il servizio Azure Active Directory

C'è una sezione per le App Registrations; clicchiamo su New Registration per creare il nostro Service Principal. Non entrarò nei dettagli delle impostazioni da selezionare durante la creazione, poiché possono variare a seconda degli abbonamenti.

Ora dobbiamo dare i diritti al nostro Service Principal. Per fare questo, andiamo negli abbonamenti, clicchiamo sull'icona della chiave. Selezioniamo il nostro abbonamento.

Successivamente, nella sezione Access Control facciamo clic su Role Assignment e cerchiamo il nome appena creato. Assegnamo il ruolo di Contributor, questo è sufficiente.

Dopo, torniamo al nostro Service Principal in Azure AD e apriamo le sue proprietà. In seguito, avremo bisogno di tutti gli ID che ci sono, quindi li salviamo.
Con questo, le impostazioni del nostro portale si concludono e passiamo a Azure DevOps.
2. Integrazione nella parte di Azure DevOps
Per prima cosa, entriamo nelle impostazioni del progetto e selezioniamo Connessioni di Servizio. Creiamo un nuovo elemento di tipo Azure Resource Manager.

Ora abbiamo bisogno di tutti gli ID che abbiamo annotato. Clicchiamo su usa la versione completa della finestra di dialogo della connessione di servizio. E inseriamo tutti i dati che abbiamo ricevuto da Service Principal. Facciamo clic su verifica e, se tutto va bene, salviamo la connessione. Ora i nostri pipeline possono utilizzarla per connettersi al cloud.

3. Creazione del pipeline
Ora passiamo alla parte più interessante, la costruzione effettiva del pipeline. Apriamo il menu Pipelines-Builds

Ci trova davanti il menu di creazione di un nuovo build, che per impostazione predefinita cercherà di creare un file YAML con la configurazione appropriata. Cortesemente rifiutiamo questo e scegliamo l'opzione classica. È comprensibile il desiderio di Microsoft di rendere tutto più umano e di offrire la massima personalizzazione dei pipeline attraverso YAML, ma la documentazione scarsa e la semplice non funzionalità pratica di molti moduli ci dicono che è ancora presto per utilizzare questa funzionalità.

Tra la varietà di modelli, avremo bisogno di un semplice Empty Pipeline. Dopo la sua creazione, ci troveremo di fronte a una finestra di editing vuota, in cui trascorreremo abbastanza tempo.

Quindi, clicchiamo su + e accediamo a un negozio di moduli, da dove abbiamo bisogno dei seguenti componenti.

Prima di procedere alla configurazione dei task del pipeline, dobbiamo formare e inserire nel progetto alcuni file. Questi saranno il template ARM della nostra macchina virtuale, che genereremo in Azure DevTest Labs, uno script per ottenere l'IP della macchina dopo la sua creazione e, se desiderato, script per i nostri test o ciò che vogliamo eseguire sull'host.
4. Generazione del template ARM
Per creare la macchina virtuale, dobbiamo prima generare il template, un file json che inseriremo nel codice del progetto affinché il pipeline possa leggerlo.
Andiamo nel nostro laboratorio e troviamo il menu Formulas (basi riutilizzabili), clicchiamo per crearne una nuova.

Ci accoglierà un lungo elenco di immagini come base, la scelta della dimensione della macchina, tutto come per la creazione di una virtual machine. A questo punto non ci fermeremo, ma passeremo direttamente all'ultimo punto delle proprietà della macchina, cioè agli artefatti. Puoi utilizzare qualsiasi configurazione necessaria per il tuo ambiente. Ad esempio, aggiungo una macchina in un dominio e aggiungo a essa un account di servizio come amministratore, in modo che il pipeline possa poi accedere a questa macchina con questo account. Tutto ciò può variare, ma per un test del codice di successo ci serve un artefatto su cui ci soffermeremo di più. Per installare l'ultima versione del software che stiamo testando sulla nostra macchina, utilizzeremo l'artefatto "Download Azure Pipelines Artifact and Run Script". Ricordate che all'inizio ho detto che da qualche parte viene raccolto un build con l'installer dell'app? Ecco, in questo momento dobbiamo dire alla macchina virtuale, o meglio al template, di andare a prelevare questo artefatto. E non solo prelevarlo, ma anche installarlo, per cui riempiamo i campi speciali indicando il progetto, il nome del build e la chiave segreta. La chiave segreta, come in tutti i sistemi di questo tipo, viene generata nell'account, in questo caso in Azure DevOps e conservata in Secrets nel vostro laboratorio. Qui c'è una piccola avvertenza, nel Secrets la conserveremo, ma al template non cambierà nulla, poiché verrà eseguito già con un altro utente all'interno del pipeline; perciò dovremo inserire manualmente la chiave segreta nel template ancora una volta.
Un altro artefatto da includere obbligatoriamente è "Configure WinRM", che ci servirà per l'accesso successivo alla macchina. C'è solo un parametro, hostname. Poiché non lo conosciamo in anticipo, utilizziamo la variabile %COMPUTERNAME%.

Ora che abbiamo aggiunto tutti gli artefatti necessari, passiamo a ciò per cui siamo qui. Recuperiamo il Template ARM generato nella scheda Advanced della stessa finestra di creazione della formula.

Copia il contenuto della pagina nel file VMtemplate.json e posizionalo nella radice del progetto. Non abbiamo più bisogno del cloud, torniamo al pipeline.
5. Configurazione del pipeline
Iniziamo con la cosa più importante e interessante, la creazione della macchina virtuale; è per questo che abbiamo realizzato tutte queste integrazioni e modelli. Nella sezione Azure RM Subscription, selezioniamo la nostra connessione al servizio, che abbiamo configurato nel punto 2. Successivamente dovrebbe apparire l'ambiente di laboratorio disponibile per noi. Poi selezioniamo il file JSON che abbiamo generato e definiamo alcune variabili obbligatorie. Possiamo impostare il login e la password della macchina o direttamente o tramite variabili, ma non sono affatto sicuro che funzioni; qualunque cosa scrivessi, non sono riuscito ad accedere alla macchina con quelle credenziali. È importante assegnare un nome alla macchina, affinché sia sempre unico, se possibile. Per questo utilizzo una variabile dell'ambiente di build.

Successivamente, configuriamo un altro aspetto importante. Dopo che la macchina sarà avviata, dobbiamo in qualche modo conoscerne i parametri, e sarebbe meglio che a farlo sia il pipeline, non noi. A tal fine, creiamo uno script, ad esempio GetLabVMParams.ps1, e lo posizioniamo nel progetto. Il testo dello script l'ho preso dal sito Microsoft, ma l'ho modificato un po' per il mio ambiente, poiché estraeva PublicIP e FQDN della macchina. Non ho né l'uno né l'altro, ma ho un PrivateIP che non è così facile da ottenere, quindi ho aggiunto un pezzo di codice.
Param( [string] $labVmId)
$labVmComputeId = (Get-AzureRmResource -Id $labVmId).Properties.ComputeId
# Ottieni il nome del gruppo risorse della VM di lab
$labVmRgName = (Get-AzureRmResource -Id $labVmComputeId).ResourceGroupName
# Ottieni il nome della VM di lab
$labVmName = (Get-AzureRmResource -Id $labVmId).Name
# Ottieni l'indirizzo IP pubblico della VM di lab
# $labVMIpAddress = (Get-AzureRmPublicIpAddress -ResourceGroupName $labVmRgName -Name $labVmName).IpAddress
# Ottieni il FQDN della VM di lab
# $labVMFqdn = (Get-AzureRmPublicIpAddress -ResourceGroupName $labVmRgName -Name $labVmName).DnsSettings.Fqdn
# Ottieni l'indirizzo IP privato della VM di lab
$VmNetworkdetails= (((Get-AzureRmVM -ResourceGroupName $labVmRgName -Name $labVmName).NetworkProfile).NetworkInterfaces).Id
$nicname = $VmNetworkdetails.substring($VmNetworkdetails.LastIndexOf("/")+1)
$labVMnetwork = (Get-AzureRmNetworkInterface -Name $nicname -ResourceGroupName $labVmRgName)|Select-Object -ExpandProperty IPConfigurations
$labVMIpAddress = $labVMnetwork.PrivateIpAddress
# Imposta una variabile labVmRgName per memorizzare il nome del gruppo risorse della VM di lab
Write-Host "##vso[task.setvariable variable=labVmRgName;]$labVmRgName"
# Imposta una variabile labVMIpAddress per memorizzare l'indirizzo IP della VM di lab
Write-Host "##vso[task.setvariable variable=labVMIpAddress;]$labVMIpAddress"
# Imposta una variabile labVMFqdn per memorizzare il nome FQDN della VM di lab
Write-Host "##vso[task.setvariable variable=labVMFqdn;]$labVMFqdn"
Write-Output $labVMIpAddress
Set-Item wsman:localhostclienttrustedhosts * -ForceDa tutto ciò che legge lo script, abbiamo bisogno solo della variabile labVMIpAddress. Potrebbe servire altro a voi, quindi non ho rimosso nulla, ma ho semplicemente commentato il superfluo.
Spiegherò anche l'ultima riga dello script, essa consente alla nostra macchina di build di accedere a qualsiasi host tramite WinRM.
Il passo successivo consiste nel lanciare il nostro fantastico script. Avrà bisogno della stessa connessione al cloud e di una variabile d'ingresso con l'ID della macchina, che sarà già nota dal passo precedente. Come? Qui bisogna menzionare una cosa straordinaria, chiamata Output Variables. Ogni passaggio può avere un elenco di variabili che vengono trasmesse ai passaggi successivi della pipeline. Pertanto, per il nostro super script, tale variabile sarà labVMIpAddress, non dimenticate di specificarlo.

Successivamente eseguo operazioni piuttosto semplici, che, inoltre, possono variare da caso a caso. Eseguo uno script remoto per creare una condivisione, in cui poi caricherò i miei script.
New-Item "C:test" –type directory
New-SMBShare –Name "test" –Path "C:test" –FullAccess everyoneDal titolo delle attività, è chiaro che stiamo copiando uno script di esempio sulla macchina e, in un ulteriore passaggio, lo eseguiamo. Come indirizzo della macchina remota utilizzeremo la nostra variabile $(labVMIpAddress). Poi utilizziamo l'attività "recupera artefatto dalla condivisione" e copiamo i risultati dell'esecuzione dello script nella nostra ambiente di build, successivamente con la stessa attività standard salvaguardiamo questi file nell'artefatto di build. Quando la macchina non ci serve più, nell'ultimo passaggio la distruggiamo. La principale difficoltà, come si evince dalla lunghezza dell'articolo, è integrarsi con il cloud e stabilire un contatto con la macchina virtuale che hai creato; da lì puoi divertirti quanto vuoi.
Questo è il mio primo articolo, quindi non giudicate severamente, i commenti sono ben accolti.
Fonte: habr.com
