Variables - Substitute in Files

Octopus.Script exported 2024-02-05 by twerthi belongs to ‘Octopus’ category.

This step template attempts to replace Octopus variable placeholders in one or more file(s) with their values from the $OctopusParameters Dictionary.


Version 18+:

Version 18 and higher pins the version of Octostache and Sprache (an Octostache dependency) to the following versions:

This is to resolve issues when running the step template on Windows, where the .NET 4.0 (net40) version is no longer present in newer versions of these libraries.

As a result, no new functionality available in Octostache, such as new commands/functions, will be present

If you need later functionality, use the built-in Octopus variable substitution feature.

Breaking Change - version 15+:

Previous versions of this step template would attempt to find the Octostache library bundled with Calamari as part of a deployment or runbook. Due to compatibility issues running the netstandard version of Octostache bundled with newer versions of Calamari on Windows PowerShell, this functionality has now been removed.

As a result, version 15 and higher of this step template now look for Octostache on the deployment target or worker in the NuGet cache. If it’s not found, it will attempt to download two required binaries:

  1. Octostache from nuget.org
  2. Sprache (an Octostache dependency) from nuget.org

If access to nuget.org is restricted on your deployment target or worker, this step template may fail to execute successfully.

In that case, it’s recommended to use the built-in Octopus variable substitution feature.


Notes:

  • Tested on Windows PowerShell only running Octopus 2023.2.4954.

Parameters

When steps based on the template are included in a project’s deployment process, the parameters below can be set.

Path

Path =

Specifies a path to one or more locations. Wildcards are permitted. The default location is the current directory (.).

Filter

Filter = *.config

Specifies, as a string array, a filter for an item or items that are included in the operation. Wildcards are permitted.

Include

Include

Specifies, as a string array, an item or items that are included in the operation. Enter a path element or pattern, such as *.txt. Wildcards are permitted. Leave this empty if you have specified a Filter.

Exclude

Exclude

Specifies, as a string array, an item or items that are excluded in the operation. Enter a path element or pattern, such as *.txt. Wildcards are permitted. Leave this empty if you have specified a Filter.

Recurse

Recurse

Search the specified locations and in all sub-directories of those locations.

Octostache library location

Variables.SubstituteInFiles.OctostacheLocation =

Optional - Provide the location that contains both of the required Octostache.dll and Sprache.dll libraries.

  • If this value is not provided, the libraries will be searched for on the target or worker, and if not found will be downloaded from nuget.org.
  • If more than one matching file is found, the first one will be used.

Script body

Steps based on this template will execute the following PowerShell script.

$ErrorActionPreference = "Stop";
function Get-Exceptions {
    param ($ExceptionObject)
    
    if ($null -ne $ExceptionObject.InnerException) {
        Get-Exceptions -ExceptionObject $ExceptionObject.InnerException
    }
    
    Write-Warning "Exception is: $($ExceptionObject.Message)"
}

function Resolve-OctopusVariablesInTemplate {
    <#
.SYNOPSIS
	Resolves Octopus variables in files with their values from a OctopusParameters

.DESCRIPTION
	Looks for files using Get-ChildItem and in each of the files replaces ${Variable} with the value from $OctopusParameters.
	Files are written back using UTF-8.
	Requires PowerShell 3.0 or higher.

.PARAMETER Path
	Passed to Get-ChildItem to find the files you want to process

.PARAMETER Filter
	Passed to Get-ChildItem to find the files you want to process

.PARAMETER Include
	Passed to Get-ChildItem to find the files you want to process

.PARAMETER Exclude
	Passed to Get-ChildItem to find the files you want to process
	
.PARAMETER Recurse
	Passed to Get-ChildItem to find the files you want to process

#>
    Param(
        [string]$Path,
        [string]$Filter = "*.config",
        [string[]]$Include,
        [string[]]$Exclude,
        [switch]$Recurse,
        [string]$OctostacheLocation
    )
	
    if (-not $OctopusParameters) { throw "No OctopusParameters found" }
	
    Write-Output "Tentacle Version: $env:TentacleVersion"
    Write-Output "PowerShell version..."
    Write-Output $PSVersionTable
    Write-Output "Path = $Path"
	
    Write-Output "Getting target files..."
    $TargetFiles = Get-ChildItem -File -Path $Path -Filter $Filter -Include $Include -Exclude $Exclude -Recurse:$Recurse
    if ($TargetFiles.Count -eq 0) {
        Write-Warning "`tDid not find any files to process!"
        return
    }
    else {
        Write-Output "`tFound $($TargetFiles.Count) file(s)"
    }
	
    Import-Octostache -OctostacheLocation $OctostacheLocation

    foreach ($File in $TargetFiles) {
        Resolve-VariablesUsingOctostache $File.FullName
    }        
}


function Import-Octostache {
    Param(
        [string]$OctostacheLocation
    )
    
    $OctostachePath = $null
    $SprachePath = $null
    
    Write-Output "Searching for installed version of Octostache."
    if (-not [string]::IsNullOrWhiteSpace($OctostacheLocation)) {
        if (-not (Test-Path $OctostacheLocation)) {
            Write-Error "Octostache path: $OctostacheLocation doesnt exist."
            Exit 1
        }
        Write-Verbose "Searching in $OctostacheLocation for Octostache.dll"
        $OctostacheLibraryLocations = Get-ChildItem -File -Path $OctostacheLocation -Filter "OctoStache.dll" -Recurse
        $OctostachePath = ($OctostacheLibraryLocations | Select-Object -First 1).FullName
        Write-Verbose "Searching in $OctostacheLocation for Sprache.dll"
        $SpracheLibraryLocations = Get-ChildItem -File -Path $OctostacheLocation -Filter "Sprache.dll" -Recurse
        $SprachePath = ($SpracheLibraryLocations | Select-Object -First 1).FullName
    }
    else {
        try {
            $OctostachePackage = (Get-Package Octostache -ErrorAction Stop) | Select-Object -First 1
        } 
        catch {
            $OctostachePackage = $null
        }

        if ($null -eq $OctostachePackage) {
            Write-Output "Downloading Octostache (v3.2.1) from nuget.org."
            Install-Package Octostache -MaximumVersion "3.2.1" -source https://www.nuget.org/api/v2 -Force -SkipDependencies
            $OctostachePackage = (Get-Package Octostache) | Select-Object -First 1
        }
    
        $OctostachePath = Join-Path (Get-Item $OctostachePackage.source).Directory.FullName "lib/net40/Octostache.dll"

        try {
            $SprachePackage = (Get-Package Sprache -ErrorAction Stop) | Select-Object -First 1
        } 
        catch {
            $SprachePackage = $null
        }

        if ($null -eq $SprachePackage) {
            Write-Output "Downloading Sprache (v2.3.1) from nuget.org."
            Install-Package Sprache -MaximumVersion "2.3.1" -source https://www.nuget.org/api/v2 -Force -SkipDependencies
            $SprachePackage = @(Get-Package Sprache) | Select-Object -First 1
        }

        $SprachePath = Join-Path (Get-Item $SprachePackage.source).Directory.FullName "lib/net40/Sprache.dll"
    }

    Write-Verbose "Octostache path: $OctostachePath"
    Write-Verbose "Sprache path: $SprachePath"

    if ([string]::IsNullOrWhiteSpace($OctostachePath) -or [string]::IsNullOrWhiteSpace($SprachePath)) {
        Write-Error "Couldnt locate either the Octostache or Sprache library."
        Exit 1
    }

    Write-Output "Adding type $SprachePath"
    Add-Type -Path $SprachePath

    Write-Output "Adding type $OctostachePath"
    Add-Type -Path $OctostachePath
}

function Resolve-VariablesUsingOctostache {
    Param(
        [string]$TemplateFile
    )
		
    Write-Output "Loading template file $TemplateFile..."
    $TemplateContent = Get-Content -Raw $TemplateFile
    Write-Output "`tRead $($TemplateContent.Length) bytes"
	
    $Dictionary = New-Object -TypeName Octostache.VariableDictionary
	
    # Load the hastable into the dictionary
    Write-Output "Loading `$OctopusParameters..."
    foreach ($Variable in $OctopusParameters.GetEnumerator()) {
        Write-Verbose "#{$($Variable.Key)} = $($Variable.Value)"
        $Dictionary.Set($Variable.Key, $Variable.Value)
    }
	
    Write-Output "Resolving variables..."
    
    try {
        $EvaluatedTemplate = $Dictionary.Evaluate($TemplateContent)
    }
    catch {
        Get-Exceptions -ExceptionObject $Error.Exception
        throw
    }
	
    Write-Output "Writing the resolved template to $($TemplateFile) (UTF8 encoding)"
    #$EvaluatedTemplate | Out-File $TemplateFile -Force	-Encoding UTF8
    $EvaluatedTemplate -join "rn" | Set-Content $TemplateFile -NoNewLine -Encoding UTF8 -Force
    Write-Output "Done!"
}

$FunctionParameters = @{}

if ($null -ne $OctopusParameters['Path']) { $FunctionParameters.Add('Path', $OctopusParameters['Path']) }
if ($null -ne $OctopusParameters['Filter']) { $FunctionParameters.Add('Filter', $OctopusParameters['Filter']) }
if ($null -ne $OctopusParameters['Include']) { $FunctionParameters.Add('Include', $($OctopusParameters['Include'] -split "`n")) }
if ($null -ne $OctopusParameters['Exclude']) { $FunctionParameters.Add('Exclude', $($OctopusParameters['Exclude'] -split "`n")) }
if ($null -ne $OctopusParameters['Recurse']) { $FunctionParameters.Add('Recurse', [System.Convert]::ToBoolean($OctopusParameters['Recurse'])) }
if (-not [string]::IsNullOrWhiteSpace($OctopusParameters['Variables.SubstituteInFiles.OctostacheLocation'])) { $FunctionParameters.Add('OctostacheLocation', $OctopusParameters['Variables.SubstituteInFiles.OctostacheLocation']) }

Resolve-OctopusVariablesInTemplate @FunctionParameters

Provided under the Apache License version 2.0.

Report an issue

To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.

{
  "Id": "a3078bc0-0615-4220-84e8-bb1f271a90f9",
  "Name": "Variables - Substitute in Files",
  "Description": "This step template attempts to replace Octopus variable placeholders in one or more file(s) with their values from the `$OctopusParameters` Dictionary.\n\n---\n\n### Version 18+:\n\nVersion 18 and higher pins the version of Octostache and Sprache (an Octostache dependency) to the following versions:\n- Octostache: [version 3.2.1](https://www.nuget.org/packages/Octostache/3.2.1)\n- Sprache: [version 2.3.1](https://www.nuget.org/packages/Sprache/2.3.1)\n\nThis is to resolve issues when running the step template on Windows, where the .NET 4.0 (`net40`) version is no longer present in newer versions of these libraries.\n\n**As a result, no new functionality available in Octostache, such as new commands/functions, will be present**\n\nIf you need later functionality, use the built-in Octopus [variable substitution feature](https://octopus.com/docs/projects/variables/variable-substitutions).\n\n### Breaking Change - version 15+:\n\nPrevious versions of this step template would attempt to find the Octostache library bundled with [Calamari](https://github.com/OctopusDeploy/Calamari) as part of a deployment or runbook. Due to compatibility issues running the `netstandard` version of Octostache bundled with newer versions of Calamari on Windows PowerShell, **this functionality has now been removed**.\n\nAs a result, **version 15** and higher of this step template now look for Octostache on the deployment target or worker in the NuGet cache. If it's not found, it will attempt to download two required binaries:\n\n1. Octostache from [nuget.org](https://www.nuget.org/packages/Octostache)\n1. Sprache (an Octostache dependency) from [nuget.org](https://www.nuget.org/packages/Sprache)\n\nIf access to [nuget.org](https://www.nuget.org) is restricted on your deployment target or worker, this step template may fail to execute successfully.\n\nIn that case, it's recommended to use the built-in Octopus [variable substitution feature](https://octopus.com/docs/projects/variables/variable-substitutions).\n\n---\n\n### Notes:\n\n- Tested on Windows PowerShell only running Octopus **2023.2.4954**.\n",
  "Version": 19,
  "ExportedAt": "2024-02-05T21:47:52.063Z",
  "ActionType": "Octopus.Script",
  "Author": "twerthi",
  "Packages": [],
  "Parameters": [
    {
      "Name": "Path",
      "Label": "Path",
      "HelpText": "Specifies a path to one or more locations. Wildcards are permitted. The default location is the current directory (.).",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Name": "Filter",
      "Label": "Filter",
      "HelpText": "Specifies, as a string array, a filter for an item or items that are included in the operation. Wildcards are permitted.",
      "DefaultValue": "*.config",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Name": "Include",
      "Label": "Include",
      "HelpText": "Specifies, as a string array, an item or items that are included in the operation. Enter a path element or pattern, such as *.txt. Wildcards are permitted. Leave this empty if you have specified a Filter.",
      "DefaultValue": null,
      "DisplaySettings": {
        "Octopus.ControlType": "MultiLineText"
      }
    },
    {
      "Name": "Exclude",
      "Label": "Exclude",
      "HelpText": "Specifies, as a string array, an item or items that are excluded in the operation. Enter a path element or pattern, such as *.txt. Wildcards are permitted. Leave this empty if you have specified a Filter.",
      "DefaultValue": null,
      "DisplaySettings": {
        "Octopus.ControlType": "MultiLineText"
      }
    },
    {
      "Name": "Recurse",
      "Label": "Recurse",
      "HelpText": "Search the specified locations and in all sub-directories of those locations.",
      "DefaultValue": null,
      "DisplaySettings": {
        "Octopus.ControlType": "Checkbox"
      }
    },
    {
      "Name": "Variables.SubstituteInFiles.OctostacheLocation",
      "Label": "Octostache library location",
      "HelpText": "*Optional* - Provide the location that contains both of the required  `Octostache.dll` and `Sprache.dll` libraries. \n\n- *If this value is not provided, the libraries will be searched for on the target or worker, and if not found will be downloaded from [nuget.org](https://www.nuget.org).*\n- If more than one matching file is found, the first one will be used.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    }
  ],
  "Properties": {
    "Octopus.Action.Script.ScriptBody": "$ErrorActionPreference = \"Stop\";\nfunction Get-Exceptions {\n    param ($ExceptionObject)\n    \n    if ($null -ne $ExceptionObject.InnerException) {\n        Get-Exceptions -ExceptionObject $ExceptionObject.InnerException\n    }\n    \n    Write-Warning \"Exception is: $($ExceptionObject.Message)\"\n}\n\nfunction Resolve-OctopusVariablesInTemplate {\n    <#\n.SYNOPSIS\n\tResolves Octopus variables in files with their values from a OctopusParameters\n\n.DESCRIPTION\n\tLooks for files using Get-ChildItem and in each of the files replaces ${Variable} with the value from $OctopusParameters.\n\tFiles are written back using UTF-8.\n\tRequires PowerShell 3.0 or higher.\n\n.PARAMETER Path\n\tPassed to Get-ChildItem to find the files you want to process\n\n.PARAMETER Filter\n\tPassed to Get-ChildItem to find the files you want to process\n\n.PARAMETER Include\n\tPassed to Get-ChildItem to find the files you want to process\n\n.PARAMETER Exclude\n\tPassed to Get-ChildItem to find the files you want to process\n\t\n.PARAMETER Recurse\n\tPassed to Get-ChildItem to find the files you want to process\n\n#>\n    Param(\n        [string]$Path,\n        [string]$Filter = \"*.config\",\n        [string[]]$Include,\n        [string[]]$Exclude,\n        [switch]$Recurse,\n        [string]$OctostacheLocation\n    )\n\t\n    if (-not $OctopusParameters) { throw \"No OctopusParameters found\" }\n\t\n    Write-Output \"Tentacle Version: $env:TentacleVersion\"\n    Write-Output \"PowerShell version...\"\n    Write-Output $PSVersionTable\n    Write-Output \"Path = $Path\"\n\t\n    Write-Output \"Getting target files...\"\n    $TargetFiles = Get-ChildItem -File -Path $Path -Filter $Filter -Include $Include -Exclude $Exclude -Recurse:$Recurse\n    if ($TargetFiles.Count -eq 0) {\n        Write-Warning \"`tDid not find any files to process!\"\n        return\n    }\n    else {\n        Write-Output \"`tFound $($TargetFiles.Count) file(s)\"\n    }\n\t\n    Import-Octostache -OctostacheLocation $OctostacheLocation\n\n    foreach ($File in $TargetFiles) {\n        Resolve-VariablesUsingOctostache $File.FullName\n    }        \n}\n\n\nfunction Import-Octostache {\n    Param(\n        [string]$OctostacheLocation\n    )\n    \n    $OctostachePath = $null\n    $SprachePath = $null\n    \n    Write-Output \"Searching for installed version of Octostache.\"\n    if (-not [string]::IsNullOrWhiteSpace($OctostacheLocation)) {\n        if (-not (Test-Path $OctostacheLocation)) {\n            Write-Error \"Octostache path: $OctostacheLocation doesnt exist.\"\n            Exit 1\n        }\n        Write-Verbose \"Searching in $OctostacheLocation for Octostache.dll\"\n        $OctostacheLibraryLocations = Get-ChildItem -File -Path $OctostacheLocation -Filter \"OctoStache.dll\" -Recurse\n        $OctostachePath = ($OctostacheLibraryLocations | Select-Object -First 1).FullName\n        Write-Verbose \"Searching in $OctostacheLocation for Sprache.dll\"\n        $SpracheLibraryLocations = Get-ChildItem -File -Path $OctostacheLocation -Filter \"Sprache.dll\" -Recurse\n        $SprachePath = ($SpracheLibraryLocations | Select-Object -First 1).FullName\n    }\n    else {\n        try {\n            $OctostachePackage = (Get-Package Octostache -ErrorAction Stop) | Select-Object -First 1\n        } \n        catch {\n            $OctostachePackage = $null\n        }\n\n        if ($null -eq $OctostachePackage) {\n            Write-Output \"Downloading Octostache (v3.2.1) from nuget.org.\"\n            Install-Package Octostache -MaximumVersion \"3.2.1\" -source https://www.nuget.org/api/v2 -Force -SkipDependencies\n            $OctostachePackage = (Get-Package Octostache) | Select-Object -First 1\n        }\n    \n        $OctostachePath = Join-Path (Get-Item $OctostachePackage.source).Directory.FullName \"lib/net40/Octostache.dll\"\n\n        try {\n            $SprachePackage = (Get-Package Sprache -ErrorAction Stop) | Select-Object -First 1\n        } \n        catch {\n            $SprachePackage = $null\n        }\n\n        if ($null -eq $SprachePackage) {\n            Write-Output \"Downloading Sprache (v2.3.1) from nuget.org.\"\n            Install-Package Sprache -MaximumVersion \"2.3.1\" -source https://www.nuget.org/api/v2 -Force -SkipDependencies\n            $SprachePackage = @(Get-Package Sprache) | Select-Object -First 1\n        }\n\n        $SprachePath = Join-Path (Get-Item $SprachePackage.source).Directory.FullName \"lib/net40/Sprache.dll\"\n    }\n\n    Write-Verbose \"Octostache path: $OctostachePath\"\n    Write-Verbose \"Sprache path: $SprachePath\"\n\n    if ([string]::IsNullOrWhiteSpace($OctostachePath) -or [string]::IsNullOrWhiteSpace($SprachePath)) {\n        Write-Error \"Couldnt locate either the Octostache or Sprache library.\"\n        Exit 1\n    }\n\n    Write-Output \"Adding type $SprachePath\"\n    Add-Type -Path $SprachePath\n\n    Write-Output \"Adding type $OctostachePath\"\n    Add-Type -Path $OctostachePath\n}\n\nfunction Resolve-VariablesUsingOctostache {\n    Param(\n        [string]$TemplateFile\n    )\n\t\t\n    Write-Output \"Loading template file $TemplateFile...\"\n    $TemplateContent = Get-Content -Raw $TemplateFile\n    Write-Output \"`tRead $($TemplateContent.Length) bytes\"\n\t\n    $Dictionary = New-Object -TypeName Octostache.VariableDictionary\n\t\n    # Load the hastable into the dictionary\n    Write-Output \"Loading `$OctopusParameters...\"\n    foreach ($Variable in $OctopusParameters.GetEnumerator()) {\n        Write-Verbose \"#{$($Variable.Key)} = $($Variable.Value)\"\n        $Dictionary.Set($Variable.Key, $Variable.Value)\n    }\n\t\n    Write-Output \"Resolving variables...\"\n    \n    try {\n        $EvaluatedTemplate = $Dictionary.Evaluate($TemplateContent)\n    }\n    catch {\n        Get-Exceptions -ExceptionObject $Error.Exception\n        throw\n    }\n\t\n    Write-Output \"Writing the resolved template to $($TemplateFile) (UTF8 encoding)\"\n    #$EvaluatedTemplate | Out-File $TemplateFile -Force\t-Encoding UTF8\n    $EvaluatedTemplate -join \"rn\" | Set-Content $TemplateFile -NoNewLine -Encoding UTF8 -Force\n    Write-Output \"Done!\"\n}\n\n$FunctionParameters = @{}\n\nif ($null -ne $OctopusParameters['Path']) { $FunctionParameters.Add('Path', $OctopusParameters['Path']) }\nif ($null -ne $OctopusParameters['Filter']) { $FunctionParameters.Add('Filter', $OctopusParameters['Filter']) }\nif ($null -ne $OctopusParameters['Include']) { $FunctionParameters.Add('Include', $($OctopusParameters['Include'] -split \"`n\")) }\nif ($null -ne $OctopusParameters['Exclude']) { $FunctionParameters.Add('Exclude', $($OctopusParameters['Exclude'] -split \"`n\")) }\nif ($null -ne $OctopusParameters['Recurse']) { $FunctionParameters.Add('Recurse', [System.Convert]::ToBoolean($OctopusParameters['Recurse'])) }\nif (-not [string]::IsNullOrWhiteSpace($OctopusParameters['Variables.SubstituteInFiles.OctostacheLocation'])) { $FunctionParameters.Add('OctostacheLocation', $OctopusParameters['Variables.SubstituteInFiles.OctostacheLocation']) }\n\nResolve-OctopusVariablesInTemplate @FunctionParameters",
    "Octopus.Action.Script.Syntax": "PowerShell",
    "Octopus.Action.Script.ScriptSource": "Inline"
  },
  "Category": "Octopus",
  "HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/variables-substitute-in-files.json",
  "Website": "/step-templates/a3078bc0-0615-4220-84e8-bb1f271a90f9",
  "Logo": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAMAAACahl6sAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAC1QTFRFT6Tl////L5Pg8vj9Y67omsvwPJrisdfzfbzs5fL7y+T32Ov5isLucLXqvt31CJPHWwAABMJJREFUeNrs3deW4jAMAFDF3U75/89dlp0ZhiU4blJEjvQ8hYubLJsA00UCBCIQgQhEIAIRiEAEIhCBCEQgAhGIQAQiEIEIhD8kJm+t+QprfdKfB9HbYpx6CWfspj8HMi+gMgHL/AmQA8W3JTKH+ALFvzCeL0RbpyoCPE9IJeNOSQwh5Z3qd6yRGWQ2qi2cZQWxqj1WzQYSjeoJmJlAklOd4VlArOqPhQEkqBERToeMcfRJBkC0Uep8CfBpjz4JsHJ0zF3dkEWNje0kiB/sUC6eApndaIiCMyAa1PiwJ0AWhRGJHJJQHG2dC7h1rNbO1QOxSA7lNCkkKrQIpJCAB1GREILYIC1NAiwbpKFJgGWDNExcwGstfExcZBCHC6nOglshHtmhViLIig1RNBCN7qjtW8C0Z1UvJcC1Z9XmwMBzzvobmgAyEzgq91dtEEsBsQSQQAFZCSBAATEEEApHZbrVBIkkEIUPSVeB+KtALA0kXQUSrwKZBCIQBnk8Y4i5CsReBeKvkqLM+BCSDWJlrZFvGk9SRTHshkgjZCGAaArIxm3H3grhVzFlW2msfl1ca79UJ1bofYvsDHHlNdTZnlh5MghuPd5NdBDUNZHyCkfktIh03XzALGRPlBDPac7qgWjHZzWcmF5zmmkhidMQ6boKiDXcDTUEaylZqCGJ0Vjvu/fLJtHqhSANEvqb2OYqkOUqEHuVMbJcZdZCGiPhKhC4yjqiIjEE7XThMp8fAWII3mY3kUIQD+AMKQTzPiBhgQ63HlT/KSvgtoi0dq5mCPah1UIE0eh3sT0NhOByvKeAkFzi8PgQomumFhsyOxpIzZN4gLOj5plVwNpR0b2AuePWKBEHQu24pSsJA+LVCeHHQxZ1SiyDIdqok8IOhSSnTottHEQTdyt4ettAj4KkzA4dMikk2Dht2S5ptm1vswnPDxn0YyDZ5oDM3iToo2T5voWaYe+Q+vdjH80QyAzZhCgcDtLMI1Tmtz9w++XHgziHQHJJu/OZ3bs9Xn8gQ72NcP3dKqEfkp10F51xhoIi2I91R+LurXV/5q7pH+wx061CzO16oSQleMyr8fXvwMA0Pro8432DPD/ySx8XrHfSuDAM8n6UhnjQabaiXf5Bq/lREHvEeNtn1rJ08+C/uXkQZHeguxAPC3UvtcJYUogLzZX5hhZZvS6onG5lxXtzWGaygwb79vT/IXhdlNibwlKYOR6T8xjI7W8n+xV7T+GH4tMzWwR+lZhRkJYSsC0thpmCYqyngOz3rN2FLBZ2wZflBCggUHF0Vnp88JKienzIXLSEZCZqU7IKr/gQW9yx3pzV7Y9kvWZWTRRIqDmTtRUnU7b2lLcTYmoqHqnmiO1poER0SPkAeZMAZxaJx0Y3TCdAclsIqDz03ALcyxfTCZBsthoGXWmigGyVhWPLFJJfuuKQWycoEFdXbH4dJJoJxNR1eD/kshz6yn48cF8yW8sFoitflB1w6Q8n+/15Za7oA17/pYNmYgP5fmWm8L1NOHPWgK8kuFew1/JXtOA0yJCv7ah7X8ObUuT5kObU30+fDZm8+zqP+HTIpK0xQ796b5Kv2hSIQAQiEIEIRCACEYhABCIQgQhEIAIRiEAEIpBf8UeAAQAEjtYmlDTcCgAAAABJRU5ErkJggg==",
  "$Meta": {
    "Type": "ActionTemplate"
  }
}

History

Page updated on Monday, February 5, 2024