This message was deleted.
# getting-started
s
This message was deleted.
b
Hi Mark, I orchestrate with PowerShell so stacks get updated and destroyed in order. If a change is made through the portal you will need to run "pulumi refresh" to resolve differences.
Copy code
function run-infra{
    Param(
        [Alias("a")]
        [parameter(Mandatory = $true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$True, HelpMessage="Pulumi action to run.")]
        [ValidateSet("up","destroy","refresh")]
        [string] $action,

        [Alias("e")]
        [parameter(Mandatory = $true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$True, HelpMessage="Environment variable used in resource names. Default value = dev")]
        [string] $env,

        [Alias("t")]
        [parameter(Mandatory = $true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$True, HelpMessage="Path to local transcripts folder.")]
        [string] $transcriptsDir,

        [Alias("p")]
        [parameter(Mandatory = $true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$True, HelpMessage="Path to local folder that contains Pulumi projects.")]
        [string] $projectsRoot,

        [Alias("s")]
        [parameter(Mandatory = $false, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$True, HelpMessage="Steps to skip as. Example 1,3,4,5 only applies step 2")]
        [string[]] $skip = @()
    )


$null = New-Item -Path $transcriptsDir  -ItemType Directory -ErrorAction Ignore
Start-Transcript -Path "$transcriptsDir\$(((get-date).ToUniversalTime()).ToString("yyyyMMddTHHmmssZ")))_Transcript.txt"

Get-Date 

function Deploy {
    param (
        $stack
    )
    switch($stack)
    {
        1 {
            write-host "az_hub ($($env)Test10) > pulumi $action "
            set-location "$projectsRoot\az_hub"
            if ($env -ieq "dev") {
                pulumi stack select devTest10
                pulumi $action -y -f
                pulumi stack select devTest172
                pulumi $action -y -f
            }elseif ($env -ieq "sys") {
                pulumi stack select sysTest10
                pulumi $action -y
                pulumi stack select sysTest172
                pulumi $action -y
            }
            Break
        } 2 {
            write-host "az_hub_panfw ($($env)Test10) > pulumi $action "
            # Depends On: az_hub-devTest10
            if ($action -ieq "up"){
            az vm image accept-terms --urn "paloaltonetworks:vmseries-flex:byol:10.2.3"
            }

            set-location "$projectsRoot\az_hub_panfw"
            if ($env -ieq "dev") {
                pulumi stack select devTest10
                pulumi $action -y -f
                pulumi stack select devTest172
                pulumi $action -y -f
            }elseif ($env -ieq "sys") {
                pulumi stack select sysTest10
                pulumi $action -y
                pulumi stack select sysTest172
                pulumi $action -y
            }
            Break
        } 3 {
            write-host "az_panfw_lb ($($env)Test10) > pulumi $action "
            # Depends On: az_hub-devTest10
            set-location "$projectsRoot\az_panfw_lb"
            if ($env -ieq "dev") {
                pulumi stack select devTest10
                pulumi $action -y -f
                pulumi stack select devTest172
                pulumi $action -y -f
            }elseif ($env -ieq "sys") {
                pulumi stack select sysTest10
                pulumi $action -y
                pulumi stack select sysTest172
                pulumi $action -y
            }
            Break
        } 4 {
            write-host "az_hub_spoke (pano-devTest) > pulumi $action "
            # Depends On: az_hub-devTest10
            Set-Location "$projectsRoot\az_hub_spoke"
            if ($env -ieq "dev") {
                pulumi stack select pano-devTest
                pulumi $action -y -f
            }elseif ($env -ieq "sys") {
                pulumi stack select pano-sysTest
                pulumi $action -y
            }
            Break
        } 5 {
            write-host "az_spoke_panorama (devTest) > pulumi $action "
            # Depends On: az_hub_spoke-pano-devTest
            set-location "$projectsRoot\az_spoke_panorama"
            if ($env -ieq "dev") {
                pulumi stack select devTest
                pulumi $action -y -f
            }elseif ($env -ieq "sys") {
                pulumi stack select devTest
                pulumi $action -y
            }
        }
    }
}

if ( ($action -ieq "up") -or ($action -ieq "refresh") )
{
    1..5 | % { if($skip.Contains($_) -eq $false){ Deploy -stack $_} }
}elseif ( $action -ieq "destroy" ) {
    5..1 | % { if($skip.Contains($_) -eq $false) { Deploy -stack $_ }}
}

Get-Date 
Stop-Transcript

}

# Run-Infra -action "up" -env "dev" -t 'D:\_Repos\Infrastructure\Transcripts' -projectsRoot 'D:\_Repos\Infrastructure'
The script above and related projects create a hub and spoke network and use stack references to build dependencies.
b
Thank you for the response, I wish there was a native way to protect against doing this accidentally but a script to run them will also work.
b
I wrote logic that checks target subscription and stack reference. Basically in every stack I define the target subscription because I would hate to update production with a dev config.
Copy code
config:
  cfg:stackRefOrg: dmanson
  cfg:stackRefProject: az_hub
  cfg:stackRefEnv: devTest10
  cfg:targetSubscriptionId: 44444444-0000-0000-0000-111111111111
Then in the stack something like this is called. You can prevent the stacks from running out of sequence easily. Your logic would siply need to know its dependencies, its stack Ref(s), but also everything that depends on it for destroy, not as easy.
Copy code
_hubStack = new StackReference($"{_config.Require("stackRefOrg")}/{_config.Require("stackRefProject")}/{_config.Require("stackRefEnv")}");
        this.StackRef = _hubStack.Name;

        var currentConfig = (Pulumi.AzureNative.Authorization.GetClientConfigResult) Pulumi.AzureNative.Authorization.GetClientConfig.InvokeAsync().GetAwaiter().GetResult();
        var targetSubscriptionId = _config.Require("targetSubscriptionId");
        if(currentConfig.SubscriptionId != targetSubscriptionId)
        {
            Pulumi.Log.Error($"The target subscription {targetSubscriptionId} is not the current subscription. Use `az account set --subscription {targetSubscriptionId}` to select the expected subscription");
        }
        this.PanFwSubscriptionId = Output.Create(currentConfig.SubscriptionId);
Something to think about.
b
I suppose over time that the destroy becomes less important because im unlikely ever to want to destroy shared infrastructure (at least not all in one go), only individual apps that will be in their own stacks. Im using destroy quite heavily right now just while testing things out. StackReference with RequireOutput(C#) has been great for catching out running updates/creations in the wrong order.