Closed andyofengland closed 5 years ago
Hi @andyofengland thanks for your feedback. That was actually also part of a plan. Not sure yet, when I can include something like this. But it should come!
Just one question Did you try the current task? Does this work for you?
Hi - I didn't try the current one - the info didn't seem to mention Blueprints so I assumed it wasn't supported.
It doesn't yet. Just hoped if you used the policy task :-) haven't gotten any feedback yet. But check in to see if a new task is added soon :-)
Hahaha - that's a good reason :)
At the moment, I don't need a policy task so I didn't try the others; I didn't want to have to roll my own PS1 script/code to call Blueprints so scoured the marketplace instead and your modules seemed the closest fit.
For now I might just roll some PS1 code and replace it with something less "funky" once your code is added.
When you're looking to start this piece, it may be worth making it so that the module executes the blueprint if it's not already been executed - as in, the step is re-runnable.
I've got it all working using a PS1 script - self validating, re-runnable and so on but as it's PS1 driven, it's not as nice as a module in the pipeline.
I've got it all working using a PS1 script - self validating, re-runnable and so on but as it's PS1 driven, it's not as nice as a module in the pipeline.
Would you be able to provide the script to me? Maybe I would be faster in integrating it, since my task will be using PowerShell as well.
Would you be able to fork my repository and edit the branch "AzureBlueprintTask" with this file and paste your basic code? And then make a pull request into this source repo into the same branch?
Of course only if you want! If not I would figure it out myself as well.
It seems that you have a folder in the branch that can't be created in Windows "AHttps:"
FYI - the recently released Az.Blueprint Powershell library is what I'm using - if you take a look at that module, it's all actually a piece of cake and only needs 2 or 3 commands...
function InstallPSModuleIfMissing()
{
Param
(
$searchModuleKey,
$moduleName
)
if (Get-Module -ListAvailable -Name $searchModuleKey) {
Write-Host "Blueprint Assignment - $moduleName module already installed"
}
else {
Write-Host "Blueprint Assignment - $moduleName module does not exist, installing"
Install-Module $moduleName -AllowClobber -Force -SkipPublisherCheck -Scope CurrentUser
}
}
function CheckModules()
{
InstallPSModuleIfMissing -searchModuleKey "Az.Websites" -moduleName "Az"
InstallPSModuleIfMissing -searchModuleKey "Az.Blueprint" -moduleName "Az.Blueprint"
}
function CurrentSubscriptionId()
{
return (Get-AzContext).Subscription.Id
}
function AllowedLocation()
{
Param
(
$targetLocation
)
$allowedLocations = @("uksouth", "ukwest")
foreach($loc in $allowedLocations)
{
if ($targetLocation -eq $loc)
{
return $true
}
}
throw "Blueprint Assignment - The specified location is not allowed"
}
function GetBlueprint() {
Param
(
$blueprintName
)
$blueprints = Get-AzBlueprint
foreach ($print in $blueprints) {
if ($print.Name -eq $blueprintName) {
return $print
}
}
throw "Blueprint Assignment - Cannot find blueprint [$blueprintName]"
}
function Wait
{
Param
(
[Int]
$seconds,
[string]
$waitMessage
)
Write-Host "Blueprint Assignment - Waiting... [$waitMessage]"
Start-Sleep -Milliseconds ($seconds * 1000)
}
function Set-Blueprint
{
Param
(
$targetLocation,
$blueprintName,
$assignmentName,
$blueprintParameters
)
# Get the test blueprint
$subscriptionId = CurrentSubscriptionId
Write-Host "Blueprint Assignment - Using Current Subscription Id [$subscriptionId]"
Write-Host "Blueprint Assignment - Assignment Id [$assignmentName]"
# Check to see if the assignment has alreay been run
$assigned = Get-AzBlueprintAssignment -SubscriptionId $subscriptionId -Name $assignmentName -ErrorAction SilentlyContinue
if ($assigned -eq $null)
{
Write-Host "Blueprint Assignment - Looking for Blueprint [$blueprintName]"
$blueprint = GetBlueprint -blueprintName $blueprintName
Write-Host "Blueprint Assignment - Found Blueprint"
Write-Host "Blueprint Assignment -" $blueprint.Name
$assignment = New-AzBlueprintAssignment -Name $assignmentName -Blueprint $blueprint -SubscriptionId $subscriptionId -Location $targetLocation -Parameter $params
$assigned = Get-AzBlueprintAssignment -SubscriptionId $subscriptionId -Name $assignmentName
while ($assigned.ProvisioningState -eq "Creating" -or $assigned.ProvisioningState -eq "Deploying" -or $assigned.ProvisioningState -eq "Waiting")
{
$waitMessage = "Blueprint Assignment - Current Status: " + $assigned.ProvisioningState
Wait -seconds 10 -waitMessage $waitMessage
$assigned = Get-AzBlueprintAssignment -SubscriptionId $subscriptionId -Name $assignmentName
}
$finalState = $assigned.ProvisioningState
Write-Host "Blueprint Assignment - Final State: " ($finalState)
return $finalState
}
else
{
return "Duplicate"
}
}
function AssignBlueprint()
{
Param
(
$subscriptionId,
$targetLocation,
$blueprintName,
$assignmentName,
$blueprintParameters
)
CheckModules
AllowedLocation -targetLocation $targetLocation | Out-Null
$provState = Set-Blueprint -subscriptionId $subscriptionId -targetLocation $targetLocation -blueprintName $blueprintName -assignmentName $assignmentName -blueprintParameters $params
if ($provState -eq "Succeeded")
{
Write-Host "Blueprint Assignment - Provisioning Completed Successfully"
}
else
{
if ($provState -eq "Duplicate")
{
Write-Host "Blueprint Assignment - Assignment Already Performed"
}
else
{
Write-Error "Blueprint Assignment - Something didn't quite go right... [$provState]"
}
}
}
There are some specific use-case bits in the above (region checking) and I had some issues getting the Get-AzBlueprint to work as defined using the Name parameter so I simply enumerated them all and did a PS1 based loop.
In the above script, I also have a child script that wraps the execution to reduce some of the complexity, such as:
Write-Host "Executing Add Resource Group Blueprint"
$blueprintName = "AddResourceGroup-bp"
$blueprintAssignmentId = "PS-BlueprintApply-$blueprintName-$platformTeamName-$resourceGroupName"
#Whatever params are defined by the blueprint
$params = @{
"location" = $targetLocation;
"blueprintParam1" = $param1;
"blueprintParam2" = $param2;
"blueprintParam3" = $param3;
"[Usergrouporapplicationname]:Owner_RoleAssignmentName" = @($ownerRoleGuid);
"[Usergrouporapplicationname]:Reader_RoleAssignmentName" = @($readerRoleGuid);
"[Usergrouporapplicationname]:Contributor_RoleAssignmentName" = @($contributorRoleGuid);
}
AssignBlueprint `
-targetLocation $targetLocation `
-blueprintName $blueprintName `
-assignmentName $blueprintAssignmentId `
-blueprintParameters $params
This is then the script that's triggered by DevOps - but it could be simplified I suppose.
The DevOps YAML looks like:
steps:
- task: AzurePowerShell@4
displayName: 'Execute Blueprint'
inputs:
azureSubscription: 'xxxxx-xxxxx-xxxxx-xxxxx'
ScriptPath: '$(System.DefaultWorkingDirectory)/<PathToPS1Script.ps1>'
ScriptArguments: '<argument list as per the PS1 script>'
azurePowerShellVersion: LatestVersion
As mentioned before, it works (providing the DevOps service account has the necessary permissions) but it has room for improvement.
I checked your script. There is one problem. This is using the Az module currently. I am using the AzureRM module still.
So it could be, that it takes a bit longer before I can integrate it. :-)
Changing the AzureRM Ps1 script to use the Az version is pretty much a search and replace. That said, you gotta test of course.
There is however a big problem with blueprints in Azure... the account they run under needs owner access to a subscription - that is something I have a concern with but, shouldn’t impact the plugin.
Hey, thanks. I already figured that. I still need to write some test. Had already small problems with the current task because of missing tests.
There is no way around the owner role, since it can do all sorts of thing that need ownership:
to cover everything, there is not even a new / custom role that would make sense. The question is maybe how to improve security with that. Maybe not allowing assignment in a pipeline, but rather only definition deployment.
Btw. this is the current status how the task would look like. This will currently only deploy blueprints in the end and not assign them. But that is already a lot in my opinion. ;-)
Assigning would come later. But this would be another task.
Nice! Being able to publish a blueprint is key for the pipeline. Just the actual blueprint pipeline not the consumer/assignee. Nice work.
@andyofengland I am closing this issue. I didn't have time to look into it much, but since Az.BluePrints has been published as part of the Az module and also the following repository is maintained by an MS employee of the BluePrint team it does not make much sense to include this one in this extension.
https://github.com/neilpeterson/azure-blueprints-pipeline-tasks
More a feature request than an issue.
Az MS have released (in Preview at this time) Azure Blueprints to allow a governed definition of "stuff", it would be great to be able to have a nice integration into DevOps whereby the pipeline can execute a Blueprint as a release step.
Whilst it is currently possible to fire off a REST call, this is neither elegant nor desired but a "user friendly" plugin would be much better.