https://pulumi.com logo
Title
m

melodic-rain-98270

03/27/2023, 12:55 PM
Slight off topic, but also sort of on topic. I was tasked with rewriting some ARM templates to Pulumi. I now have several Pulumi scripts working individually. They are originally based on the previous ARM templates, where the launch conditions depends on the users launch input in a powershell script. I am looking at the ps1 file and I am not sure which relevant Pulumi commands I can use to make the launch of the Pulumi scripts depend on the users input. I will include the full ps1 underneath, but mostly I am wondering the best practice for converting a ps1 script to a logical pulumi script where the user can trigger it from a pipeline cli. I.e. Commands such as
Get-AzWebApp
seems to have a Pulumi Azure native command described here: https://www.pulumi.com/registry/packages/azure-native/api-docs/web/getwebapp/ However, is there any way to make this accessible from a user CLI, in a "best practice" kind of way? Full example of a
deployAppService.ps1
script (only for reference to get a better understanding of what kind of logic I am trying to achieve):
Param(
[string]$namePrefix,
[string]$name,
[string]$VirtualDirectory,
[string]$appPlanName,
[string]$appInsightsKey,
[string]$SubscriptionID,
[string]$ResourceGroup,
[bool]$useCosmos = $false
)

Set-Location $PSScriptRoot
$firstimeDeployment = $false
$deploymentTime = (Get-Date).ToUniversalTime().ToString("yyyyMMddHHmmss")
$VirtualDirectory = $VirtualDirectory.Trim("/")
$paths = $VirtualDirectory -split '/'

$gatewaysubnetId = "/subscriptions/$SubscriptionID/resourceGroups/$ResourceGroup/providers/Microsoft.Network/virtualNetworks/$namePrefix-vnet/subnets/$namePrefix-gwsubnet"
$serverFarmId = "/subscriptions/$SubscriptionID/resourceGroups/$ResourceGroup/providers/Microsoft.Web/serverFarms/$namePrefix-$appPlanName"

$webapp = Get-AzWebApp -ResourceGroupName "$ResourceGroup" -Name "$namePrefix-$name" -ErrorAction SilentlyContinue
if(-not $webapp)
{
    write-host "web app does not exist, creating both app and slot"
    $firstimeDeployment = $true
}

$params = @{namePrefix = "$namePrefix"; name = "$name"; gatewaysubnetId = $gatewaysubnetId; serverFarmId = $serverFarmId; isFirsttimeDeployment = $firstimeDeployment; appInsightsKey = $appInsightsKey; EnableIdentity = $useCosmos}

if($VirtualDirectory -eq "")
{
    write-host "Virtual directory is empty, deploying root only template"
    $outputs = New-AzResourceGroupDeployment -name "$($name).$($deploymentTime)"  -ResourceGroupName "$ResourceGroup" -TemplateFile "..\RootOnly-ssl.json" -TemplateParameterObject $params
    $outputs
}
elseif($paths.count -eq 1)
{
    write-host "deploying standard template"
    $params.Add("VirtualDirectory","$VirtualDirectory")
    $outputs = New-AzResourceGroupDeployment -name "$($name).$($deploymentTime)" -ResourceGroupName "$ResourceGroup" -TemplateFile "..\standard-ssl.json" -TemplateParameterObject $params
    $outputs
}
elseif($paths.count -eq 2)
{
    write-host "Virtual directory contains folder, deploying: DirectoryandPath template"
    $params.Add("VirtualDirectory","$VirtualDirectory")
    $outputs = New-AzResourceGroupDeployment -name "$($name).$($deploymentTime)" -ResourceGroupName "$ResourceGroup" -TemplateFile "..\DirectoryandPath-ssl.json" -TemplateParameterObject $params
    $outputs
}
else
{
    Write-Error "Virtual directory is not valid. Virtualdirectory: [$VirtualDirectory]"
}


if($useCosmos)
{
    if(-not $outputs.Outputs["identity"].value -or -not $outputs.Outputs["developIdentity"].value){
        throw "template deployment outputs does not contain required identities"
    }
    write-host "cosmos enabled, giving permission to key vault"

    write-host "Variables: VaultName: $namePrefix-keyVault-cosmos. ResourceGroup: $ResourceGroup, identity: $($outputs.Outputs['identity'].value). developIdentity: $($outputs.Outputs['developIdentity'].value)"
    Set-AzKeyVaultAccessPolicy -VaultName "$namePrefix-keyVault-cosmos" -ResourceGroupName "$ResourceGroup" -ObjectId "$($outputs.Outputs['identity'].value)" -PermissionsToSecrets Get,List -BypassObjectIdValidation

    Set-AzKeyVaultAccessPolicy -VaultName "$namePrefix-keyVault-cosmos" -ResourceGroupName "$ResourceGroup" -ObjectId "$($outputs.Outputs['developIdentity'].value)" -PermissionsToSecrets Get,List -BypassObjectIdValidation
}
s

salmon-account-74572

03/27/2023, 2:17 PM
If I’m understanding correctly (in that you want to be able to run
pulumi up
and have the results be dependent on user input), you have two options: 1. Write your code to pull environment variables and then use environment variables on the command line (i.e.,
VARIABLE=value pulumi up
). 2. Switch to using configuration values and have users supply the values they want to use via
pulumi config set
. Then each user can deploy their own stack with their own configuration values. The second is probably a “better” way of handling it but it is slightly different than the current way (again, if I’m understanding correctly).
m

melodic-rain-98270

03/28/2023, 12:24 PM
Thank you for the reply and sorry for the delayed response. I tried finding documentation for the second option, but I am very much out of my depth when it comes to both Pulumi and PowerShell. I will keep searching and testing and see if I can find something that works. Thank you for the push in the right direction.
s

salmon-account-74572

03/28/2023, 2:59 PM
What language are you using? I can most likely find (or write) sample code that might illustrate the second approach.
m

melodic-rain-98270

03/28/2023, 3:03 PM
I am writing the Pulumi scripts in TypeScript. Thank you so much for your time!
s

salmon-account-74572

03/28/2023, 3:14 PM
Of course, I am happy to help! Here’s a public example of how to pull a value from project configuration: https://github.com/pulumi/zephyr-infra/blob/main/index.ts#L4-L6 AIUI, in your case you’d want to take all those
Params
from the top of your PowerShell script and set them as configuration values. In TypeScript, the
|| <value>
syntax is a way of saying “If no other value was supplied, then use this value` (set a default, in other words). I don’t know if any of the parameters in your PowerShell script could have default values, but if you want/need to use defaults that’s how. Let me (or anyone else here) know if you have further questions.
m

melodic-rain-98270

03/29/2023, 7:33 AM
If this were to be launched in a pipeline (they are using Azure classic pipelines today), would it be best to re-use the existing ps1 scripts and use the existing variables to inject Pulumi config into a pipeline-provided Pulumi environment from the scripts themselves, or would it be better to do everything config related in the pipeline in a "hard config way"? I would like there to be as little manual config for them to do in the end, where they only input the arguments they actually need for their specific resource (which, from my understanding, is how they are running it today, just without Pulumi). Essentially I think what I am asking is: Is rewriting the ps1 files for Pulumi config and letting them keep using that as an entry point for their infra a good way to also configure the Pulimi envs?
s

salmon-account-74572

03/29/2023, 5:38 PM
I would say that if updating the
.ps1
scripts to set Pulumi configuration values and run a Pulumi deployment works for you and your team, then go for it. I’m sure someone somewhere will say it’s not “correct” or the “most effective” way to do it, but if it works for you all, then it seems to me to be a perfectly reasonable starting point.