Ein zentrales Repository anlegen
Zunächst sollte ein Repository angelegt werden. Dieses soll unsere Powershell Scripts und YML Templates beinhalten. Ich schlage hierfür folgende Ordnerstruktur vor:
Das Powershell Script
Als nächstes sollte das Powershell Script angelegt werden. Ein solches Script könnte wie folgt aussehen:
[CmdletBinding()]
param (
# Name of the Event Grid Domain.
[Parameter(Mandatory=$true, HelpMessage="Name of the Event Grid Domain.")]
[Alias("n")]*
[string]$Name,
# Name of the Location, like westeurope.
[Parameter(Mandatory=$true, HelpMessage="Name of the Location.")]
[Alias("l")]
[string]$Location,
# Name of the Resource Group.
[Parameter(Mandatory=$true, HelpMessage="Name of the Resource Group.")]
[Alias("g")]
[string]$ResourceGroup
)
Write-Verbose"Deploy Event Grid Domain $Name..."
azeventgriddomaincreate--name"$Name"-g"$ResourceGroup"-l"$Location"
$endpoint= $(azeventgriddomainlist-g"$ResourceGroup"--query"[?name=='$Name'].endpoint"-otsv)
Write-Output ("##vso[task.setvariable variable=DeployEventGridDomainOutput.Endpoint;issecret=true]$endpoint")
$domainKey= $(azeventgriddomainkeylist--name"$Name"--resource-group"$ResourceGroup"--query"key1"-otsv)
if (!$domainKey)
{
Write-Error"EventGrid Domain key '$Key' could not be found in EventGrid Domain '$Name'!"
}
else
{
Write-Output ("##vso[task.setvariable variable=DeployEventGridDomainOutput.Key;issecret=true]$domainKey")
}
Write-Verbose"Event Grid Domain created"
Das YML Template
Anschließend können wir ein YML Step Template erzeugen, dieses könnte in etwa so aussehen:
parameters:
- name: AzureSubscription
type: string
- name: Name
type: string
- name: Location
type: string
- name: ResourceGroup
type: string
- name: ScriptPath
type: string
default: '$(Build.SourcesDirectory)/shared/pipelines/scripts'
steps:
- task: AzureCLI@2
displayName: 'Deploy EventGrid Domain ${{ parameters.Name }}'
inputs:
azureSubscription: ${{ parameters.AzureSubscription }}
scriptType: pscore
scriptPath: '${{ parameters.ScriptPath }}/Deploy-EventGrid-Domain.ps1'
arguments: '-Name "${{ parameters.Name }}" -Location "${{ parameters.Location }}" -ResourceGroup "${{ parameters.ResourceGroup }}"'
powerShellErrorActionPreference: stop
addSpnToEnvironment: false
useGlobalConfig: false
failOnStandardError: false
powerShellIgnoreLASTEXITCODE: false
Das Template nimmt die Parameter entgegen, die das PowerShell Script selbst benötigt und leitet diese als Argumente weiter. Außerdem nimmt es den ScriptPath als Parameter entgegen, gibt hierfür jedoch einen Standardpfad an. Das erlaubt es uns, das zugehörige Script auch als lokale Kopie einzubinden, falls Beispielsweise kurzzeitig etwas am Script lokal getestet werden soll.
Einbinden in eine Pipeline
Nun, da das YML-Template und das Powershell-Script existieren, können wir das Ganze in einer tatsächlichen Pipeline einbauen und verwenden.
name: '1.$(Year:yy).$(DayOfYear)$(Rev:rr)'
# TODO: Hier stünden natürlich noch Dinge wie Trigger, Pools, Variablen etc.
resources:
pipelines:
- pipeline: shared
source: My.Project.SharedPipelineRepository
stages:
- stage: deploy_eventgrid_domain_stage
displayName: Deploy EventGrid Domain
dependsOn: [dependency_stage_a, dependency_stage_b]
jobs:
- deployment: deploy_eventgrid_domain_job
displayName: Deploy EventGrid Domain
workspace:
clean: all
environment: $(MyProject.Environment)
strategy:
runOnce:
deploy:
steps:
- checkout: self
path: s
- checkout: shared
path: shared
- template: templates/steps/Deploy-EventGrid-Domain.yml@shared
parameters:
AzureSubscription: $(Shared.ServiceConnection.Stateful)
Name: $(MyProject.EventGridDomainName)
Location: $(MyProject.DefaultLocation)
ResourceGroup: $(MyProject.ResourceGroupNameStateless)
Wichtig sind hierbei folgende Punkte:
- Wenn ein Repository wie shared eingebunden wurde, und etwas aus dem eigentlichen Repository benötigt wird, muss self, sofern im Job benötigt, explizit ausgecheckt werden. Hierbei sollte der Pfad auf den Wert „s“ gesetzt werden, da dies das Standardverhalten wäre, wenn der Checkout nicht explizit vorgenommen werden würde.
- Das shared-Repository sollte mit dem Pfad „shared“ ausgecheckt werden. Im Template haben wir den Standardpfad so konfiguriert, dass dieser automatisch passt. Sollte ein anderer Name gewollt sein, so sollte dieser überall angepasst werden
Schlusswort
Dieses Beispiel stellt natürlich keine komplette Pipeline dar, sondern lediglich einen simplen Step. Man kann sich damit aber wunderbar Module aufbauen, um alles Mögliche zu erreichen und einzustellen, ganz nach den jeweiligen Bedürfnissen.
Und da man alle Steps und Scripte an einem Ort hat, kann man diese einfacher pflegen und verhindert so gekonnt, dass sich mehrere Pipelines individuell auseinanderentwickeln.