Octopus.Script exported 2024-10-23 by twerthi belongs to ‘Azure’ category.
Deploys a container to an Azure Container App Environment
Parameters
When steps based on the template are included in a project’s deployment process, the parameters below can be set.
Azure Resource Group Name
Template.Azure.ResourceGroup.Name =
Provide the resource group name to create the environment in.
Azure Account Subscription Id
Template.Azure.Account.SubscriptionId =
The subscription ID of the Azure account to use. This value can be retrieved from an Azure Account variable type. Add an Azure Account to your project , then assign the SubscriptionNumber
property to for this entry. Leave blank to use the Managed Identity.
For example, if your Azure Account variable is called MyAccount, the value for this input would be #{MyAccount.SubscriptionNumber}
Azure Account Client Id
Template.Azure.Account.ClientId =
The subscription ID of the Azure account to use. This value can be retrieved from an Azure Account variable type. Add an Azure Account to your project , then assign the Client
property to for this entry. Leave blank to use the Managed Identity.
For example, if your Azure Account variable is called MyAccount, the value for this input would be #{MyAccount.Client}
Azure Account Tenant Id
Template.Azure.Account.TenantId =
The subscription ID of the Azure account to use. This value can be retrieved from an Azure Account variable type. Add an Azure Account to your project , then assign the TenantId
property to for this entry. If blank, it will use the Managed Identity tenant.
For example, if your Azure Account variable is called MyAccount, the value for this input would be #{MyAccount.TenantId}
Azure Account Password
Template.Azure.Account.Password =
The subscription ID of the Azure account to use. This value can be retrieved from an Azure Account variable type. Add an Azure Account to your project , then assign the Password
property to for this entry. Leave blank to use the Managed Identity.
For example, if your Azure Account variable is called MyAccount, the value for this input would be #{MyAccount.Password}
Container App Environment Name
Template.ContainerApp.Environment.Name =
The name or ID of the container app environment to deploy to.
Azure Location
Template.Azure.Location.Name =
The location in which to create the container app environment.
Container Name
Template.Azure.Container.Name =
The name of the container to create/update. If you want to use the image name, specify #{Octopus.Action.Package[Template.Azure.Container.Image].PackageId}
Container Image
Template.Azure.Container.Image =
Select the container image to deploy.
Environment variables
Template.Azure.Container.Variables =
JSON formatted key/value pair of environment variables to pass to the container. This supports use of OctoStache.
[
{
"name": "ConnectionStrings__CatalogConnection",
"value": "Server=#{Project.SQL.DNS},1433;Integrated Security=true;Initial Catalog=#{Project.Catalog.Database.Name};User Id=#{Project.SQL.Admin.Username};Password=#{Project.SQL.Admin.Password};Trusted_Connection=false;Trust Server Certificate=True;"
},
{
"name": "MyPasswordFromSecret",
"secretref": "Name of my secret"
},
...
]
Secrets
Template.Azure.Container.Secrets =
JSON formatted key/value pair of secrets to create/update. This supports use of OctoStache.
Note: The name of the secret must be lowercase.
[
{
"name": "mysecret",
"value": "#{Project.SQL.Admin.Password}"
},
...
]
Resource CPU
Template.Azure.Container.Cpu =
The amount of CPU to allocate to the container app.
Example: 0.5
Resource Memory
Template.Azure.Container.Memory =
The amount of memory to allocate to the container app.
Examples: 250Mb or 4.0Gi
Container Ingress Port
Template.Azure.Container.Ingress.Port =
The port to allow traffic to the container.
External Ingress
Template.Azure.Container.ExternalIngress = False
Whether the ingress is externally accessible or not.
Script body
Steps based on this template will execute the following PowerShell script.
# Define functions
function Get-ModuleInstalled
{
# Define parameters
param(
$PowerShellModuleName
)
# Check to see if the module is installed
if ($null -ne (Get-Module -ListAvailable -Name $PowerShellModuleName))
{
# It is installed
return $true
}
else
{
# Module not installed
return $false
}
}
function Get-NugetPackageProviderNotInstalled
{
# See if the nuget package provider has been installed
return ($null -eq (Get-PackageProvider -ListAvailable -Name Nuget -ErrorAction SilentlyContinue))
}
function Install-PowerShellModule
{
# Define parameters
param(
$PowerShellModuleName,
$LocalModulesPath
)
# Check to see if the package provider has been installed
if ((Get-NugetPackageProviderNotInstalled) -ne $false)
{
# Display that we need the nuget package provider
Write-Host "Nuget package provider not found, installing ..."
# Install Nuget package provider
Install-PackageProvider -Name Nuget -Force
}
# Save the module in the temporary location
Write-Host "Saving module $PowerShellModuleName to temporary folder ..."
Save-Module -Name $PowerShellModuleName -Path $LocalModulesPath -Force
Write-Host "Save successful!"
}
# Check to see if $IsWindows is available
if ($null -eq $IsWindows)
{
Write-Host "Determining Operating System..."
$IsWindows = ([System.Environment]::OSVersion.Platform -eq "Win32NT")
$IsLinux = ([System.Environment]::OSVersion.Platform -eq "Unix")
}
# Check to see if it's running on Windows
if ($IsWindows)
{
# Disable the progress bar so downloading files via Invoke-WebRequest are faster
$ProgressPreference = 'SilentlyContinue'
}
if ($PSEdition -eq "Core") {
$PSStyle.OutputRendering = "PlainText"
}
# Define PowerShell Modules path
$LocalModules = (New-Item "$PWD/modules" -ItemType Directory -Force).FullName
$env:PSModulePath = "$LocalModules$([IO.Path]::PathSeparator)$env:PSModulePath"
$azureModule = "Az.App"
# Get variables
$templateAzureAccountClient = $OctopusParameters['Template.Azure.Account.ClientId']
$templateAzureAccountPassword = $OctopusParameters['Template.Azure.Account.Password']
$templateAzureAccountTenantId = $OctopusParameters['Template.Azure.Account.TenantId']
$templateAzureResourceGroup = $OctopusParameters['Template.Azure.ResourceGroup.Name']
$templateAzureSubscriptionId = $OctopusParameters['Template.Azure.Account.SubscriptionId']
$templateEnvironmentName = $OctopusParameters['Template.ContainerApp.Environment.Name']
$templateAzureLocation = $OctopusParameters['Template.Azure.Location.Name']
$templateAzureContainer = $OctopusParameters['Template.Azure.Container.Image']
$templateAzureContainerIngressPort = $OctopusParameters['Template.Azure.Container.Ingress.Port']
$templateAzureContainerIngressExternal = $OctopusParameters['Template.Azure.Container.ExternalIngress']
$vmMetaData = $null
$secretRef = @()
$templateAzureContainerSecrets = $null
if (![string]::IsNullOrWhitespace($OctopusParameters['Template.Azure.Container.Variables']))
{
$templateAzureContainerEnvVars = ($OctopusParameters['Template.Azure.Container.Variables'] | ConvertFrom-JSON)
}
else
{
$templateAzureContainerEnvVars = $null
}
if (![string]::IsNullOrWhitespace($OctopusParameters['Template.Azure.Container.Secrets']))
{
$templateAzureContainerSecrets = ($OctopusParameters['Template.Azure.Container.Secrets'] | ConvertFrom-JSON)
}
else
{
$templateAzureContainerSecrets = $null
}
$templateAzureContainerCPU = $OctopusParameters['Template.Azure.Container.Cpu']
$templateAzureContainerMemory = $OctopusParameters['Template.Azure.Container.Memory']
# Check for required PowerShell module
Write-Host "Checking for module $azureModule ..."
if ((Get-ModuleInstalled -PowerShellModuleName $azureModule) -eq $false)
{
# Install the module
Install-PowerShellModule -PowerShellModuleName $azureModule -LocalModulesPath $LocalModules
}
# Import the necessary module
Write-Host "Importing module $azureModule ..."
Import-Module $azureModule
# Check to see if the account was specified
if (![string]::IsNullOrWhitespace($templateAzureAccountClient))
{
# Login using the provided account
Write-Host "Logging in as specified account ..."
# Create credential object for az module
$securePassword = ConvertTo-SecureString $templateAzureAccountPassword -AsPlainText -Force
$azureCredentials = New-Object System.Management.Automation.PSCredential ($templateAzureAccountClient, $securePassword)
Connect-AzAccount -Credential $azureCredentials -ServicePrincipal -Tenant $templateAzureAccountTenantId | Out-Null
Write-Host "Login successful!"
}
else
{
Write-Host "Using machine Managed Identity ..."
$vmMetaData = Invoke-RestMethod -Headers @{"Metadata"="true"} -Method GET -Uri "http://169.254.169.254/metadata/instance?api-version=2021-02-01"
Connect-AzAccount -Identity
# Get Identity context
$identityContext = Get-AzContext
# Set variables
$templateAzureSubscriptionId = $vmMetaData.compute.subscriptionId
if ([string]::IsNullOrWhitespace($templateAzureAccountTenantId))
{
$templateAzureAccountTenantId = $identityContext.Tenant
}
Set-AzContext -Tenant $templateAzureAccountTenantId | Out-Null
Write-Host "Successfully set context for Managed Identity!"
}
# Check to see if the environment name is a / in it
if ($templateEnvironmentName.Contains("/") -ne $true)
{
# Lookup environment id by name
Write-Host "Looking up Managed Environment by Name ..."
$templateEnvironmentName = (Get-AzContainerAppManagedEnv -ResourceGroupName $templateAzureResourceGroup -EnvName $templateEnvironmentName -SubscriptionId $templateAzureSubscriptionId).Id
}
# Build parameter list to pass to New-AzContainerAppTemplateObject
$PSBoundParameters.Add("Image", $OctopusParameters["Octopus.Action.Package[Template.Azure.Container.Image].Image"])
$PSBoundParameters.Add("Name", $OctopusParameters["Template.Azure.Container.Name"])
if (![string]::IsNullOrWhitespace($templateAzureContainerCPU))
{
$PSBoundParameters.Add("ResourceCpu", "$templateAzureContainerCPU")
}
if (![string]::IsNullOrWhitespace($templateAzureContainerMemory))
{
$PSBoundParameters.Add("ResourceMemory", "$templateAzureContainerMemory")
}
if ($null -ne $templateAzureContainerEnvVars)
{
# Loop through list
$envVars = @()
foreach ($envVar in $templateAzureContainerEnvVars)
{
$envEntry = @{}
$envEntry.Add("Name", $envVar.Name)
# Check for specific property
if ($envVar.SecretRef)
{
$envEntry.Add("SecretRef", $envVar.SecretRef)
}
else
{
$envEntry.Add("Value", $envVar.Value)
}
# Add to collection
$envVars += $envEntry
}
$PSBoundParameters.Add("Env", $envVars)
}
if ($null -ne $templateAzureContainerSecrets)
{
# Loop through list
foreach ($secret in $templateAzureContainerSecrets)
{
# Create new secret object and add to array
$secretRef += New-AzContainerAppSecretObject -Name $secret.Name -Value $secret.Value
}
}
# Create new container app
$containerDefinition = New-AzContainerAppTemplateObject @PSBoundParameters
$PSBoundParameters.Clear()
# Define ingress components
if (![string]::IsNullOrWhitespace($templateAzureContainerIngressPort))
{
$PSBoundParameters.Add("IngressExternal", [System.Convert]::ToBoolean($templateAzureContainerIngressExternal))
$PSBoundParameters.Add("IngressTargetPort", $templateAzureContainerIngressPort)
}
# Check the image
if ($OctopusParameters["Octopus.Action.Package[Template.Azure.Container.Image].Image"].Contains("azurecr.io"))
{
# Define local parameters
$registryCredentials = @{}
$registrySecret = @{}
# Accessing an ACR repository, configure credentials
if (![string]::IsNullOrWhitespace($templateAzureAccountClient))
{
# Use configured client, name must be lower case
$registryCredentials.Add("Username", $templateAzureAccountClient)
$registryCredentials.Add("PasswordSecretRef", "clientpassword")
$secretRef += New-AzContainerAppSecretObject -Name "clientpassword" -Value $templateAzureAccountPassword
}
else
{
# Using Managed Identity
$registryCredentials.Add("Identity", "system")
}
$registryServer = $OctopusParameters["Octopus.Action.Package[Template.Azure.Container.Image].Image"]
$registryServer = $registryServer.Substring(0, $registryServer.IndexOf("/"))
$registryCredentials.Add("Server", $registryServer)
# Add credentials
$PSBoundParameters.Add("Registry", $registryCredentials)
}
# Define secrets component
if ($secretRef.Count -gt 0)
{
# Add to parameters
$PSBoundParameters.Add("Secret", $secretRef)
}
# Create new configuration object
Write-Host "Creating new Configuration Object ..."
$configurationObject = New-AzContainerAppConfigurationObject @PSBoundParameters
$PSBoundParameters.Clear()
# Define parameters
$PSBoundParameters.Add("Name", $OctopusParameters["Template.Azure.Container.Name"])
$PSBoundParameters.Add("TemplateContainer", $containerDefinition)
$PSBoundParameters.Add("ResourceGroupName", $templateAzureResourceGroup)
$PSBoundParameters.Add("Configuration", $configurationObject)
# Check to see if the container app already exists
$containerApps = Get-AzContainerApp -ResourceGroupName $templateAzureResourceGroup
if ($null -eq $containerApps)
{
$containerApp = $null
}
else
{
$containerApp = ($containerApps | Where-Object {$_.Name -eq $OctopusParameters["Template.Azure.Container.Name"]})
}
if ($null -eq $containerApp)
{
# Add parameters required for creating container app
$PSBoundParameters.Add("EnvironmentId", $templateEnvironmentName)
$PSBoundParameters.Add("Location", $templateAzureLocation)
# Deploy container
Write-Host "Creating new container app ..."
New-AzContainerApp @PSBoundParameters
}
else
{
Write-Host "Updating existing container app ..."
Update-AzContainerApp @PSBoundParameters
}
Provided under the Apache License version 2.0.
To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.
{
"Id": "db701b9a-5dbe-477e-b820-07f9e354f634",
"Name": "Azure - Deploy Container App",
"Description": "Deploys a container to an Azure Container App Environment",
"Version": 6,
"ExportedAt": "2024-10-23T22:07:49.069Z",
"ActionType": "Octopus.Script",
"Author": "twerthi",
"Packages": [
{
"Id": "636b2191-09f6-4f86-a59c-97e1891475db",
"Name": "Template.Azure.Container.Image",
"PackageId": null,
"FeedId": null,
"AcquisitionLocation": "NotAcquired",
"Properties": {
"Extract": "False",
"SelectionMode": "deferred",
"PackageParameterName": "Template.Azure.Container.Image",
"Purpose": ""
}
}
],
"Parameters": [
{
"Id": "a1ae1b6c-99d0-4ee5-9c3c-08c345966842",
"Name": "Template.Azure.ResourceGroup.Name",
"Label": "Azure Resource Group Name",
"HelpText": "Provide the resource group name to create the environment in.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "fb92b5d7-5e48-485d-9222-dc2c97b58535",
"Name": "Template.Azure.Account.SubscriptionId",
"Label": "Azure Account Subscription Id",
"HelpText": "The subscription ID of the Azure account to use. This value can be retrieved from an Azure Account variable type. Add an Azure Account to your project , then assign the `SubscriptionNumber` property to for this entry. Leave blank to use the Managed Identity.\n\nFor example, if your Azure Account variable is called MyAccount, the value for this input would be `#{MyAccount.SubscriptionNumber}`",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "e1ce647f-956e-48d1-8002-44d958f1c8a4",
"Name": "Template.Azure.Account.ClientId",
"Label": "Azure Account Client Id",
"HelpText": "The subscription ID of the Azure account to use. This value can be retrieved from an Azure Account variable type. Add an Azure Account to your project , then assign the `Client` property to for this entry. Leave blank to use the Managed Identity.\n\nFor example, if your Azure Account variable is called MyAccount, the value for this input would be `#{MyAccount.Client}`",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "a02e3fd0-9d91-4106-84a4-ff0d68e5de7c",
"Name": "Template.Azure.Account.TenantId",
"Label": "Azure Account Tenant Id",
"HelpText": "The subscription ID of the Azure account to use. This value can be retrieved from an Azure Account variable type. Add an Azure Account to your project , then assign the `TenantId` property to for this entry. If blank, it will use the Managed Identity tenant.\n\nFor example, if your Azure Account variable is called MyAccount, the value for this input would be `#{MyAccount.TenantId}`",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "7bd73320-1889-41eb-a1c0-c8788e5eed9d",
"Name": "Template.Azure.Account.Password",
"Label": "Azure Account Password",
"HelpText": "The subscription ID of the Azure account to use. This value can be retrieved from an Azure Account variable type. Add an Azure Account to your project , then assign the `Password` property to for this entry. Leave blank to use the Managed Identity.\n\nFor example, if your Azure Account variable is called MyAccount, the value for this input would be `#{MyAccount.Password}`",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Sensitive"
}
},
{
"Id": "f7fafc7e-2658-4a6f-ac30-7d9f738b9f52",
"Name": "Template.ContainerApp.Environment.Name",
"Label": "Container App Environment Name",
"HelpText": "The name or ID of the container app environment to deploy to.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "31f02b7e-4822-49de-97dc-ee981b12268c",
"Name": "Template.Azure.Location.Name",
"Label": "Azure Location",
"HelpText": "The location in which to create the container app environment.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "d74123b0-4104-45b9-ae12-b1f808b8b948",
"Name": "Template.Azure.Container.Name",
"Label": "Container Name",
"HelpText": "The name of the container to create/update. If you want to use the image name, specify `#{Octopus.Action.Package[Template.Azure.Container.Image].PackageId}`",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "1bdb6d31-4b97-4eab-aca3-5a60891b3455",
"Name": "Template.Azure.Container.Image",
"Label": "Container Image",
"HelpText": "Select the container image to deploy.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "Package"
}
},
{
"Id": "9e7aa5cf-9bab-4303-a851-1b8757f2f486",
"Name": "Template.Azure.Container.Variables",
"Label": "Environment variables",
"HelpText": "JSON formatted key/value pair of environment variables to pass to the container. This supports use of OctoStache.\n\n```\n[\n {\n \"name\": \"ConnectionStrings__CatalogConnection\",\n \"value\": \"Server=#{Project.SQL.DNS},1433;Integrated Security=true;Initial Catalog=#{Project.Catalog.Database.Name};User Id=#{Project.SQL.Admin.Username};Password=#{Project.SQL.Admin.Password};Trusted_Connection=false;Trust Server Certificate=True;\"\n },\n {\n \"name\": \"MyPasswordFromSecret\",\n \"secretref\": \"Name of my secret\"\n },\n ...\n]\n```",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "MultiLineText"
}
},
{
"Id": "498f308d-a94c-4364-b0be-8d739ac63f4e",
"Name": "Template.Azure.Container.Secrets",
"Label": "Secrets",
"HelpText": "JSON formatted key/value pair of secrets to create/update. This supports use of OctoStache.\n\n**Note:** The name of the secret must be lowercase.\n\n```\n[\n {\n \"name\": \"mysecret\",\n \"value\": \"#{Project.SQL.Admin.Password}\"\n },\n ...\n]\n```",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "MultiLineText"
}
},
{
"Id": "20e3e428-62b9-4eef-9cdc-780a0eedee79",
"Name": "Template.Azure.Container.Cpu",
"Label": "Resource CPU",
"HelpText": "The amount of CPU to allocate to the container app.\n\nExample: 0.5",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "d804f749-625e-4ca5-9bef-13fc2c2a463c",
"Name": "Template.Azure.Container.Memory",
"Label": "Resource Memory",
"HelpText": "The amount of memory to allocate to the container app.\n\nExamples: 250Mb or 4.0Gi",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "a506b328-4e10-49fe-947b-6623d4d392c1",
"Name": "Template.Azure.Container.Ingress.Port",
"Label": "Container Ingress Port",
"HelpText": "The port to allow traffic to the container.",
"DefaultValue": "",
"DisplaySettings": {
"Octopus.ControlType": "SingleLineText"
}
},
{
"Id": "682d68a4-f1eb-469c-9557-9577ed9f1505",
"Name": "Template.Azure.Container.ExternalIngress",
"Label": "External Ingress",
"HelpText": "Whether the ingress is externally accessible or not.",
"DefaultValue": "False",
"DisplaySettings": {
"Octopus.ControlType": "Checkbox"
}
}
],
"Properties": {
"Octopus.Action.Script.ScriptSource": "Inline",
"Octopus.Action.Script.Syntax": "PowerShell",
"Octopus.Action.Script.ScriptBody": "# Define functions\nfunction Get-ModuleInstalled\n{\n # Define parameters\n param(\n $PowerShellModuleName\n )\n\n # Check to see if the module is installed\n if ($null -ne (Get-Module -ListAvailable -Name $PowerShellModuleName))\n {\n # It is installed\n return $true\n }\n else\n {\n # Module not installed\n return $false\n }\n}\n\nfunction Get-NugetPackageProviderNotInstalled\n{\n\t# See if the nuget package provider has been installed\n return ($null -eq (Get-PackageProvider -ListAvailable -Name Nuget -ErrorAction SilentlyContinue))\n}\n\nfunction Install-PowerShellModule\n{\n # Define parameters\n param(\n $PowerShellModuleName,\n $LocalModulesPath\n )\n\n\t# Check to see if the package provider has been installed\n if ((Get-NugetPackageProviderNotInstalled) -ne $false)\n {\n \t# Display that we need the nuget package provider\n Write-Host \"Nuget package provider not found, installing ...\"\n \n # Install Nuget package provider\n Install-PackageProvider -Name Nuget -Force\n }\n\n\t# Save the module in the temporary location\n Write-Host \"Saving module $PowerShellModuleName to temporary folder ...\"\n Save-Module -Name $PowerShellModuleName -Path $LocalModulesPath -Force\n Write-Host \"Save successful!\"\n}\n\n# Check to see if $IsWindows is available\nif ($null -eq $IsWindows)\n{\n Write-Host \"Determining Operating System...\"\n $IsWindows = ([System.Environment]::OSVersion.Platform -eq \"Win32NT\")\n $IsLinux = ([System.Environment]::OSVersion.Platform -eq \"Unix\")\n}\n\n# Check to see if it's running on Windows\nif ($IsWindows)\n{\n\t# Disable the progress bar so downloading files via Invoke-WebRequest are faster\n $ProgressPreference = 'SilentlyContinue'\n}\n\nif ($PSEdition -eq \"Core\") {\n $PSStyle.OutputRendering = \"PlainText\"\n}\n\n# Define PowerShell Modules path\n$LocalModules = (New-Item \"$PWD/modules\" -ItemType Directory -Force).FullName\n$env:PSModulePath = \"$LocalModules$([IO.Path]::PathSeparator)$env:PSModulePath\"\n$azureModule = \"Az.App\"\n\n# Get variables\n$templateAzureAccountClient = $OctopusParameters['Template.Azure.Account.ClientId']\n$templateAzureAccountPassword = $OctopusParameters['Template.Azure.Account.Password']\n$templateAzureAccountTenantId = $OctopusParameters['Template.Azure.Account.TenantId']\n$templateAzureResourceGroup = $OctopusParameters['Template.Azure.ResourceGroup.Name']\n$templateAzureSubscriptionId = $OctopusParameters['Template.Azure.Account.SubscriptionId']\n$templateEnvironmentName = $OctopusParameters['Template.ContainerApp.Environment.Name']\n$templateAzureLocation = $OctopusParameters['Template.Azure.Location.Name']\n$templateAzureContainer = $OctopusParameters['Template.Azure.Container.Image']\n$templateAzureContainerIngressPort = $OctopusParameters['Template.Azure.Container.Ingress.Port']\n$templateAzureContainerIngressExternal = $OctopusParameters['Template.Azure.Container.ExternalIngress']\n$vmMetaData = $null\n$secretRef = @()\n$templateAzureContainerSecrets = $null\n\nif (![string]::IsNullOrWhitespace($OctopusParameters['Template.Azure.Container.Variables']))\n{\n $templateAzureContainerEnvVars = ($OctopusParameters['Template.Azure.Container.Variables'] | ConvertFrom-JSON)\n}\nelse\n{\n\t$templateAzureContainerEnvVars = $null\n}\n\nif (![string]::IsNullOrWhitespace($OctopusParameters['Template.Azure.Container.Secrets']))\n{\n $templateAzureContainerSecrets = ($OctopusParameters['Template.Azure.Container.Secrets'] | ConvertFrom-JSON)\n}\nelse\n{\n\t$templateAzureContainerSecrets = $null\n}\n\n$templateAzureContainerCPU = $OctopusParameters['Template.Azure.Container.Cpu']\n$templateAzureContainerMemory = $OctopusParameters['Template.Azure.Container.Memory']\n\n# Check for required PowerShell module\nWrite-Host \"Checking for module $azureModule ...\"\n\nif ((Get-ModuleInstalled -PowerShellModuleName $azureModule) -eq $false)\n{\n\t# Install the module\n Install-PowerShellModule -PowerShellModuleName $azureModule -LocalModulesPath $LocalModules\n}\n\n# Import the necessary module\nWrite-Host \"Importing module $azureModule ...\"\nImport-Module $azureModule\n\n# Check to see if the account was specified\nif (![string]::IsNullOrWhitespace($templateAzureAccountClient))\n{\n\t# Login using the provided account\n Write-Host \"Logging in as specified account ...\"\n \n\t# Create credential object for az module\n\t$securePassword = ConvertTo-SecureString $templateAzureAccountPassword -AsPlainText -Force\n\t$azureCredentials = New-Object System.Management.Automation.PSCredential ($templateAzureAccountClient, $securePassword) \n\n Connect-AzAccount -Credential $azureCredentials -ServicePrincipal -Tenant $templateAzureAccountTenantId | Out-Null\n \n Write-Host \"Login successful!\"\n}\nelse\n{\n\tWrite-Host \"Using machine Managed Identity ...\"\n $vmMetaData = Invoke-RestMethod -Headers @{\"Metadata\"=\"true\"} -Method GET -Uri \"http://169.254.169.254/metadata/instance?api-version=2021-02-01\"\n \n Connect-AzAccount -Identity\n \n # Get Identity context\n $identityContext = Get-AzContext\n \n # Set variables\n $templateAzureSubscriptionId = $vmMetaData.compute.subscriptionId\n \n if ([string]::IsNullOrWhitespace($templateAzureAccountTenantId))\n {\n \t$templateAzureAccountTenantId = $identityContext.Tenant\n }\n \n Set-AzContext -Tenant $templateAzureAccountTenantId | Out-Null\n\tWrite-Host \"Successfully set context for Managed Identity!\"\n}\n\n# Check to see if the environment name is a / in it\nif ($templateEnvironmentName.Contains(\"/\") -ne $true)\n{\n\t# Lookup environment id by name\n Write-Host \"Looking up Managed Environment by Name ...\"\n $templateEnvironmentName = (Get-AzContainerAppManagedEnv -ResourceGroupName $templateAzureResourceGroup -EnvName $templateEnvironmentName -SubscriptionId $templateAzureSubscriptionId).Id\n}\n\n# Build parameter list to pass to New-AzContainerAppTemplateObject\n$PSBoundParameters.Add(\"Image\", $OctopusParameters[\"Octopus.Action.Package[Template.Azure.Container.Image].Image\"])\n$PSBoundParameters.Add(\"Name\", $OctopusParameters[\"Template.Azure.Container.Name\"])\n\nif (![string]::IsNullOrWhitespace($templateAzureContainerCPU))\n{\n $PSBoundParameters.Add(\"ResourceCpu\", \"$templateAzureContainerCPU\")\n}\n\nif (![string]::IsNullOrWhitespace($templateAzureContainerMemory))\n{\n $PSBoundParameters.Add(\"ResourceMemory\", \"$templateAzureContainerMemory\")\n}\n\nif ($null -ne $templateAzureContainerEnvVars)\n{\n # Loop through list\n $envVars = @()\n foreach ($envVar in $templateAzureContainerEnvVars)\n {\n \t$envEntry = @{}\n $envEntry.Add(\"Name\", $envVar.Name)\n \n # Check for specific property\n if ($envVar.SecretRef)\n {\n \t$envEntry.Add(\"SecretRef\", $envVar.SecretRef)\n }\n else\n {\n \t$envEntry.Add(\"Value\", $envVar.Value)\n }\n \n # Add to collection\n $envVars += $envEntry\n }\n \n $PSBoundParameters.Add(\"Env\", $envVars)\n}\n\nif ($null -ne $templateAzureContainerSecrets)\n{\n\t# Loop through list\n foreach ($secret in $templateAzureContainerSecrets)\n {\n # Create new secret object and add to array\n $secretRef += New-AzContainerAppSecretObject -Name $secret.Name -Value $secret.Value\n }\n}\n\n# Create new container app\n$containerDefinition = New-AzContainerAppTemplateObject @PSBoundParameters\n$PSBoundParameters.Clear()\n\n# Define ingress components\nif (![string]::IsNullOrWhitespace($templateAzureContainerIngressPort))\n{\n\t$PSBoundParameters.Add(\"IngressExternal\", [System.Convert]::ToBoolean($templateAzureContainerIngressExternal))\n $PSBoundParameters.Add(\"IngressTargetPort\", $templateAzureContainerIngressPort)\n}\n\n# Check the image\nif ($OctopusParameters[\"Octopus.Action.Package[Template.Azure.Container.Image].Image\"].Contains(\"azurecr.io\"))\n{\n\t# Define local parameters\n $registryCredentials = @{}\n $registrySecret = @{}\n \n # Accessing an ACR repository, configure credentials\n if (![string]::IsNullOrWhitespace($templateAzureAccountClient))\n {\n\n\t\t# Use configured client, name must be lower case\n $registryCredentials.Add(\"Username\", $templateAzureAccountClient)\n $registryCredentials.Add(\"PasswordSecretRef\", \"clientpassword\")\n\n\t\t$secretRef += New-AzContainerAppSecretObject -Name \"clientpassword\" -Value $templateAzureAccountPassword\n }\n else\n {\n \t# Using Managed Identity\n $registryCredentials.Add(\"Identity\", \"system\")\n \n }\n \n $registryServer = $OctopusParameters[\"Octopus.Action.Package[Template.Azure.Container.Image].Image\"]\n $registryServer = $registryServer.Substring(0, $registryServer.IndexOf(\"/\"))\n $registryCredentials.Add(\"Server\", $registryServer)\n \n # Add credentials\n $PSBoundParameters.Add(\"Registry\", $registryCredentials)\n}\n\n# Define secrets component\nif ($secretRef.Count -gt 0)\n{\n\t# Add to parameters\n $PSBoundParameters.Add(\"Secret\", $secretRef)\n}\n\n# Create new configuration object\nWrite-Host \"Creating new Configuration Object ...\"\n$configurationObject = New-AzContainerAppConfigurationObject @PSBoundParameters\n$PSBoundParameters.Clear()\n\n# Define parameters\n$PSBoundParameters.Add(\"Name\", $OctopusParameters[\"Template.Azure.Container.Name\"])\n$PSBoundParameters.Add(\"TemplateContainer\", $containerDefinition)\n$PSBoundParameters.Add(\"ResourceGroupName\", $templateAzureResourceGroup)\n$PSBoundParameters.Add(\"Configuration\", $configurationObject)\n\n\n# Check to see if the container app already exists\n$containerApps = Get-AzContainerApp -ResourceGroupName $templateAzureResourceGroup\n\nif ($null -eq $containerApps)\n{\n $containerApp = $null\n}\nelse\n{\n $containerApp = ($containerApps | Where-Object {$_.Name -eq $OctopusParameters[\"Template.Azure.Container.Name\"]})\n}\n\nif ($null -eq $containerApp)\n{\n\t# Add parameters required for creating container app\n\t$PSBoundParameters.Add(\"EnvironmentId\", $templateEnvironmentName)\n\t$PSBoundParameters.Add(\"Location\", $templateAzureLocation)\n\t\n\t# Deploy container\n Write-Host \"Creating new container app ...\"\n\tNew-AzContainerApp @PSBoundParameters\n}\nelse\n{\n\tWrite-Host \"Updating existing container app ...\"\n Update-AzContainerApp @PSBoundParameters\n}\n"
},
"Category": "Azure",
"HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/azure-deploy-containerapp.json",
"Website": "/step-templates/db701b9a-5dbe-477e-b820-07f9e354f634",
"Logo": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAADNQTFRF////AHjXf7vrv931QJrh7/f8EIDaIIncMJHfYKvmz+b3n8zw3+76j8Ttr9XycLPpUKLkkKvYFAAABGZJREFUeNrsnNmCqjoQRc1MEiD8/9cer7Yt2KBJZQC8ez07sKlKTQlcLgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzoUSnt8YxXlFuGHSbIaxvj+fip4btkLn1blkWLaF5v03yLhLOYlVuGYfMOMZzNGxCOzhjTJqFkXnjq3Dr1yyvPI3hGl3Ih3zzHHNKudRstRhX5O58vIcShY67Gq6EPIESlzUWvazaGAOGbvU7ArDu/g8M4o8opDZWvbvPzlL/MMBE8jT9T9W7PbAJlHPTBFRf9yVTEcs63msXz2UHLSgf650G/d5t+wjbxxB2UCMqGrk8/LFSD7uJMeNt5bcJCyQZyAe5Fo9KYfWS2flQrr4b4tpuzaeWjYs49rt9LHf9uZD7+VbyVi9EBNrjYjuq2sxQOrl+p+HuBVu45qvqfq691ttYFQ5KyKbyJgaIY/NGxrlWZwlwGvmvu1oY3PuAv0niTq6tZ78jk//9uc1r1r4lQki7y7sp2Tu4V1y2iLoqFTqi1lIGcpFiebrZNZ1dOkF0cCIlO8jQ47nCkam9Lilz9GhDF1I6XGLzfnhwDIIZVfI7+8SSgfHsijqXENOGJF5QorG4EcW0OrScqX/dDrXpr70Ut/BII+1OfECPuYz/NWxYmgrCsUskxPvyhgmrw+WGZ6lGTuOlIyCYWTFyWjpM5KIZRUIOwjRNYRQ6tZF9BXtk8hWAHPtLNJ727Fq0JSkC1FDRRF0Jalj0d5qVh2KEpM2TuSsCYTCT6ZkdmFYI9LrYp5QayWbo6NXlZwcRD/61pth5Fq5EX423QQxNjhqWvvklkljOLkYjrmphXPZOJOk6Pg7HKMsrtQKcowzZoK3rx1ZUelGMdQA/HaKkjAt2RgqpZeYqbNbH7Hp2ct4nqfSPOfe0ftiSTZJydOV6rG5bQbyLK+nRuCC0343PzDgiOXyQA5c14BTZi98uR/5KJ1SnatLdoO50WWBQZPTq0VgsklU3h932actuo17ayrHrb/3ykiegd3KbqF2wbV6RrlsJ07yLcpsWFTul9RyK6ZScr+tk7oNrFj0o7HQUlj4EiEvJ6rPLKSmlMZCrksl1OnLaRkxc+/HB1naMhNtT/6yM2bDs6azCRHrM3aVPN7aW8irD/10B8njpAMcsl8okXcdKrl4sPsLmQVy/Sj90ucPRc/d/Bxxj+dXSpCayen32D+hLi16MsIV8gfCXrYp6ySsiJKRUF0XXiLpVbFU+fNv4r7mOwhFsX4ZdwpSi1DYs2jb6ebZ9788cblTzMrYhu7sf/17IFdtuviJ2ioHA6pMHkoH4CLUeMBU7iGkxuM/YgcdderF9ibRdc7O982F1HpYhjfWUe+x5a6pjop9iNLfoePvlsdZdTSMwfxSmTY20Q0eHnUNzga1edeNmmqbg18aMVR1L9vwSXHF9TfIWBxpKLs2hj3eQeBC0USvp2HHF3eIkRdhFOd6ER8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/I/4J8AAo/80BciBec4AAAAASUVORK5CYII=",
"$Meta": {
"Type": "ActionTemplate"
}
}
Page updated on Wednesday, October 23, 2024