Prerequisites:
- Octopus environments
- Octopus variable sets
- Octopus project with variable sets attached
Let's identify how we configure a project and variable sets in the Octopus. Following image shows the Octopus variable and values defined with the scope.
You can see the variable name and values. As example, we use st-#{projectPrefix}-user value in prod and uat environment. If the deployment done to any other environment, variable value should be #{xamdevStorageAccountName} which is referring to another variable in another variable set. Like wise we can define variable values for each scope. another thing you need to know here is, if variable value starts with #{ it means this is defined in another variable set. You refer another variable set to read the real value.So, once you read the value from this variable set, you should be able to get the real value by referring the other variable set. To do this, you can create an Octopus project and add both variable sets to it. Then it resolve the variable references within another variable set as value of given variables and return the real variable value for you.
Now let's see how we access the octopus REST API and and read variable values using the PowerShell script.
In this script we have defined few parameters. Before reading the variable values, we need to build up a connection with octopus. For that purpose, we have to provide Octopus server URL and Octopus API key. After build up the connection we can provide the octopus space name where we have the octopus project, Octopus project name and environment. In this sample PowerShell script we read values from the variable set and update the values in App.config file. So, we need to provide the path of the App.config file. Further, if we need to read values from Azure key vault, it is possible to do using this script. If you want to read values from key vault, you can provide Azure account user, password and subscription id.
Param(
[Parameter(Mandatory=$true)]
[string] $octopusUrl,
[Parameter(Mandatory=$true)]
[string] $octopusAPIKey,
[Parameter(Mandatory=$true)]
[string] $environmentName = 'DEV',
[Parameter(Mandatory=$true)]
[string] $octopusSpaceName = 'Default',
[Parameter(Mandatory=$true)]
[string] $octopusProjectName,
[Parameter(Mandatory=$true)]
[string] $appConfigFilePath,
[Parameter(Mandatory=$false)]
[string] $azureAccoutUser,
[Parameter(Mandatory=$false)]
[string] $azureAccoutUserPwd,
[Parameter(Mandatory=$false)]
[string] $azureSubscriptionId
)
Write-Host ("Get content of " + $appConfigFilePath +"...")
# Read the App.config content
$doc = ((Get-Content -path $appConfigFilePath) -replace "`0", "")
-as [xml];
# Find the space
$spaceList = Invoke-RestMethod "$OctopusUrl/api/spaces?Name=$spaceName"
-Headers $header
$spaceFilter = @($spaceList.Items | Where {$_.Name -eq $octopusSpaceName})
$spaceId = $spaceFilter[0].Id
Write-Host "The spaceId for Space Name $octopusSpaceName
is $spaceId"
# Find the environment
$environmentList = Invoke-RestMethod "$OctopusUrl/api/$spaceId/environments?skip=0&take=1000&name=$environmentName"
-Headers $header
$environmentFilter = @($environmentList.Items | Where {$_.Name -eq $environmentName})
$environmentId = $environmentFilter[0].Id
Write-Host "The environmentId for Environment Name
$environmentName in space $octopusSpaceName is $environmentId"
# Find the project
$projects = Invoke-RestMethod -UseBasicParsing "$OctopusUrl/api/$spaceId/projects/all?skip=0&take=1000&name=$projectName&"
-Headers $header
$projectFilter = @($projects | Where {$_.Name -eq $octopusProjectName})
$projectId = $projectFilter[0].Id
Write-Host "The projectId for Project Name
$octopusProjectName in space $octopusSpaceName is $projectId"
# Get the evaluated variables for the
provided scope
$evaluatedVariables = (Invoke-RestMethod -UseBasicParsing
"$OctopusURL/api/$spaceId/variables/preview?project=$projectId&environment=$environmentId"
-Headers $header).Variables
After that read the values from the relevant variable set, replace App config file values using the octopus variable set values.
#
Loop each of variable from octopus - begin
foreach($octopusVariable in $evaluatedVariables)
{
#check if the app.config has a key by
name of the variable
$variableName=$octopusVariable.Name;
Write-Host ("Processing variable " + $variableName +"...")
$appConfigEntry = $doc.configuration.appSettings.add
| where {$_.Key -eq $variableName}
#if app config has the key with the
variable name -begin
if(-not ([string]::IsNullOrEmpty($appConfigEntry)))
{
Write-Host ("App Config entry found for variable "
+ $variableName)
# Assign octopus variable value to a
$variableValue
$variableValue=$octopusVariable.Value;
#Check if the variable name starts with
@Microsoft.KeyVault - begin
if($variableValue.startswith('@Microsoft.KeyVault'))
{
Write-Host ("Variable need to be obtained from KV")
if ($notLoggedOntoAz)
{
Write-Host ("Log on to Azure")
$notLoggedOntoAz = $false;
az login --username $azureAccoutUser --password $azureAccoutUserPwd
az account set --subscription $azureSubscriptionId
Write-Host ("Log on to Azure sucess.")
}
$splitSections=$variableValue.split(";");
$splitSecretName=$splitSections[1].split("=");
$secretName=$splitSecretName[1];
$keyVaultName = $splitSections[0].Replace("@Microsoft.KeyVault(VaultName=","");
$secretVersion=$splitSections[2].Replace("SecretVersion=","").Replace(")","");
#read
the variable value from KV and assign to $variableValue
$variableValue = (az keyvault
secret show -n $secretName --vault-name $keyVaultName --version $secretVersion | ConvertFrom-Json).value
Write-Host ("Obtained value from KV for varaible "
+ $variableName)
}
#Check if the variable name starts with
@Microsoft.KeyVault - end
#Update app .config entry with
$variableValue
$appConfigEntry.value = $variableValue
Write-Host ("Updated app config entry.")
}#if app config has the key with the
variable name -end
Write-Host ("Processed variable " + $variableName +".")
}# Loop each of variable from octopus -
end
Write-Host ("Saving config file " + $appConfigFilePath)
#save the app.config
$doc.Save($appConfigFilePath)
Write-Host ("Done.")
The full script can be downloaded from here (https://gist.github.com/PushpaH/5e748ee4b905208cc69b384713a87dfa)
You can use the script with PowerShell task in Azure pipelines as follows.
No comments:
Post a Comment