Skip to content

Commit

Permalink
Merge pull request #16 from keesschollaart81/dev
Browse files Browse the repository at this point in the history
V4.0
  • Loading branch information
keesschollaart81 authored Sep 3, 2018
2 parents 1f25b85 + 63e1375 commit d948725
Show file tree
Hide file tree
Showing 79 changed files with 197 additions and 6,568 deletions.
97 changes: 97 additions & 0 deletions Marketplace.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
# ARM Outputs

This extension enables you to use the ARM Deployment outputs in your VSTS environment.

This step will use the last successful deployment within the selected resource group. If this deployent has outputs, all of them are copied to VSTS variables by the ARM Output key.

This outputs can then be used by default VSTS ways: ```$(same-key-as-in-arm-template)```

Usually this task is ran directly after the 'Azure Resource Group Deployment' task.

[![screenshot-1](images/screenshots-vsts-arm-outputs-1.png "Screenshot-1")](images/screenshots-vsts-arm-outputs-1.png)

## Release notes

### Version 4.0 - 03-09-2018

- Support for complex outputs
- Now based on AzurePowershell task handler
- Improved performance
- Less dependencies
- Easier to port to Linux agents Powershell Core on VSTS becomes a thing

### Version 3.0 - 01-02-2018

- Filter on deployment name

### Version 2.0 - 18-11-2017

- LastDeploymentBehaviour added

### Version 1.0 - 13-04-2017

- Initial version

## Parameter usage

### Secrets

If your output is of type ```SecureString``` the output value cannot be read and these outputs are therefore ignored.

You can off course output your secrets as string but then these values might be exposed in logfiles (and visible via the Azure Portal as well)

### Prefix

Using the 'prefix' parameter, it is possible to prefix the variables used within VSTS. A prefix can be used to distinct variables coming out of ARM from regular VSTS variables. A prefix can also be to prevent collisions between ARM Output names and VSTS Variable names.

### Output Names

Using the 'Output Names' parameter, it is possible to process only a subset of the ARM Outputs. When this field is left empty (it is by default) all ARM Outputs are used.

### When last deployment is failed

Using the 'When last deployment is failed' parameter, you can choose the behaviour when the last deployment to a resource group has failed. There are two options, 1. fail the task (the default) or 2. take the last succesful deployment.

### Filter deployment name

Optional string to filter deployments by. This can be useful if you have concurrent deployments to the same resource group. Deployment names in VSTS are the name of the json file plus date and time, so a file CreateKeyVault.json could have a deployment name of CreateKeyVault-20180025-151538-0688. In this case, if you want to filter to deployments of this file enter CreateKeyVault as the filter

## Complex outputs

If your output is not a single value but a complex type, like:
``` json
{
"parameters": {},
"resources": {},
"outputs": {
"someKey":"someValue",
"second": {
"foo":"bar",
"oops": {
"asdasdasd":true,
"array": [
{
"asd":"qqq"
},
{
"efg":"aaa"
}
]
}
}
}
}
````
This will result in the following 5 variables:

```
complex_someKey => someValue
complex_second_foo => bar
complex_second_oops_asdasdasd => True
complex_second_oops_array_0_asd => qqq
complex_second_oops_array_1_efg => aaa
```
## Help & Contact
Find me at http://case.schollaart.net/. Experiencing problems, or do you have an idea? Please let me know via [Twitter](https://twitter.com/keesschollaart) or by [mail](mailto:[email protected]). Or even better, raise an issue on [GitHub](https://github.com/keesschollaart81/vsts-arm-outputs/issues).
24 changes: 3 additions & 21 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,28 +10,10 @@ Usually this task is ran directly after the 'Azure Resource Group Deployment' ta

[![screenshot-1](images/screenshots-vsts-arm-outputs-1.png "Screenshot-1")](images/screenshots-vsts-arm-outputs-1.png)

## Secrets
## How to use

If your output is of type ```SecureString``` the output value cannot be read and these outputs are therefore ignored.

You can off course output your secrets as string but then these values might be exposed in logfiles (and visible via the Azure Portal as well)

## Prefix

Using the 'prefix' parameter, it is possible to prefix the variables used within VSTS. A prefix can be used to distinct variables coming out of ARM from regular VSTS variables. A prefix can also be to prevent collisions between ARM Output names and VSTS Variable names.

## Output Names

Using the 'Output Names' parameter, it is possible to process only a subset of the ARM Outputs. When this field is left empty (it is by default) all ARM Outputs are used.

## When last deployment is failed

Using the 'When last deployment is failed' parameter, you can choose the behaviour when the last deployment to a resource group has failed. There are two options, 1. fail the task (the default) or 2. take the last succesful deployment.

## Filter deployment name

Optional string to filter deployments by. This can be useful if you have concurrent deployments to the same resource group. Deployment names in VSTS are the name of the json file plus date and time, so a file CreateKeyVault.json could have a deployment name of CreateKeyVault-20180025-151538-0688. In this case, if you want to filter to deployments of this file enter CreateKeyVault as the filter
Checkout the docs in the [Marketplace page](Marketplace.md)

## Help & Contact

Find me at http://case.schollaart.net/
Find me at http://case.schollaart.net/. Experiencing problems, or do you have an idea? Please let me know via [Twitter](https://twitter.com/keesschollaart) or by [mail](mailto:[email protected]). Or even better, raise an issue on [GitHub](https://github.com/keesschollaart81/vsts-arm-outputs/issues).
53 changes: 37 additions & 16 deletions arm-outputs/arm-outputs.ps1 → arm-outputs/Out-ARMOutput.ps1
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
Write-Verbose "Entering script arm-outputs.ps1"
Write-Verbose "Entering script Out-ARMOutput.ps1"

. .\Select-OutputsFromObjectTree.ps1

Write-Debug "ResourceGroupName= $resourceGroupName"

$lastResourceGroupDeployments = Get-AzureRmResourceGroupDeployment -ResourceGroupName $resourceGroupName | where {$_.DeploymentName -match $deploymentNameFilter -or $deploymentNameFilter -eq $null} | Sort-Object Timestamp -Descending
#region Get Latest Deployment

$lastResourceGroupDeployments = Get-AzureRmResourceGroupDeployment -ResourceGroupName $resourceGroupName | Where-Object {$_.DeploymentName -match $deploymentNameFilter -or $deploymentNameFilter -eq $null} | Sort-Object Timestamp -Descending
$lastResourceGroupDeployment = $lastResourceGroupDeployments | Select-Object -First 1

if ($whenLastDeploymentIsFailed -eq "latestSuccesful" ) {
Expand Down Expand Up @@ -30,28 +34,45 @@ if (!$lastResourceGroupDeployment.Outputs) {
Write-Warning "No output parameters could be found for the deployment '$deploymentName' of Resource Group '$resourceGroupName'."
return;
}
#endregion

$outputNamesArray = $null

if ($outputNames) {
$outputNamesArray = $outputNames.split(',') | ForEach-Object { $_.Trim() }
}
$outputNamesCount = $outputNamesArray.length

foreach ($key in $lastResourceGroupDeployment.Outputs.Keys) {
$type = $lastResourceGroupDeployment.Outputs.Item($key).Type
$value = $lastResourceGroupDeployment.Outputs.Item($key).Value
#region generate array with all outputs

$Outputs = @()

if ($outputNamesCount -gt 0 -and $outputNamesArray -notcontains $key) {
Write-Debug "Variable '$key' is not one of the $outputNamesCount given key's to set, ignoring..."
continue;
$lastResourceGroupDeployment.Outputs.GetEnumerator() | ForEach-Object {
$value = $_.Value.Value

if ($outputNamesArray.length -gt 0 -and $outputNamesArray -notcontains $_.Key) {
Write-Debug "Variable '$($_.Key)' is not one of the $($outputNamesArray.length) given key's to set, ignoring..."
return
}

if ($type -eq "SecureString") {
Write-Verbose "Variable '$key' is of type SecureString, ignoring..."
}
else {
Write-Verbose "Updating VSTS variable '$key' to value '$value'"
Write-Host "##vso[task.setvariable variable=$prefix$key;$isSecret]$value"
}
if ($_.Value.Type -eq "SecureString") {
Write-Verbose "Variable '$($_.Key)' is of type SecureString, ignoring..."
return
}

if ($value.GetType().Name -eq "JObject"){
$objectOutput = ConvertFrom-Json $value.ToString() # Is this really needed?
$Outputs += Select-OutputsFromObjectTree -Object $objectOutput -PathName $_.Key -Level 0 -MaxLevels 7
return
}

$Outputs += [PSCustomObject]@{
Key = $_.Key
Value = $value
}
}
#endregion

$Outputs | ForEach-Object {
Write-Verbose "Updating VSTS variable '$($_.Key)' to value '$($_.Value)'"
Write-Host "##vso[task.setvariable variable=$prefix$($_.Key);]$($_.Value)"
}
30 changes: 30 additions & 0 deletions arm-outputs/Select-OutputsFromObjectTree.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
function Select-OutputsFromObjectTree($Object, $MaxLevels="7", $PathName = "", $Level=0)
{
# Recursivly traverse over (nested) objects, flattening the object-tree to: parent.child.propery: value

$OutputArray = @()

$Object | Get-Member | Where-Object { $_.MemberType -match "Property"} | ForEach-Object {
$key = "$($PathName)_$($_.Name)"
$value = $Object | Select-Object -ExpandProperty $_.Name

switch ($value.GetType().ToString())
{
"System.Management.Automation.PSCustomObject" {
$OutputArray += Select-OutputsFromObjectTree -Object $value -PathName $key -Level ($Level + 1) -MaxLevels $MaxLevels
}
"System.Object[]"{
For ($i=0; $i -lt $value.Length; $i++) {
$OutputArray += Select-OutputsFromObjectTree -Object $value[$i] -PathName "$($key)_$i" -Level ($Level + 1) -MaxLevels $MaxLevels
}
}
default{
$OutputArray += [PSCustomObject]@{
Key = $key
Value = $value
}
}
}
}
return $OutputArray;
}
Loading

0 comments on commit d948725

Please sign in to comment.