AzureDataFactoryV2/ARM_RemoveParametersWithDefaults.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
#Requires -Version 3
[CmdletBinding()]
Param(
    [Parameter(Mandatory=$true,Position=1)] [string] $TemplatePathIn,
    [Parameter(Mandatory=$false,Position=2)] [string] $TemplatePathOut = $TemplatePathIn.Replace('.json', '_out.json'),
    [Parameter(Mandatory=$false,Position=3)] [string[]] $ParametersToKeep = @('factoryName')
)

# halt on first error
$ErrorActionPreference = 'Stop'
# print Information stream
$InformationPreference = 'Continue'
# print Verbose stream
$VerbosePreference = 'Continue'

# for local tests only!!
if ($false) { 
    $rootPath = Split-Path -Parent $psise.CurrentFile.FullPath
    $TemplatePathIn = "$rootPath\arm_template\arm_template.json"
    $TemplatePathOut = "$rootPath\arm_template\arm_template_out.json"
    $ParametersToKeep = @('factoryName')
}
function CheckFor-DefaultValue([PSObject]$object, [string[]]$parametersToKeep)
{
    Write-Verbose "Checking for default value of parameter '$($object.Name)' ..."
    if($object.Name -in $parametersToKeep)
    {
        $return = $false
    }
    else
    {
        $return = -not ($object.Value.defaultValue -eq $null)
    }
    
    Write-Verbose " Default value found: $return"
    return $return
}
function Replace-Parameter([string]$originalText, [hashtable]$parameterDefaultValues)
{
    foreach($key in $parameterDefaultValues.Keys)
    {
        $parameterName = $key
        $parameterDefaultValue = $parameterDefaultValues[$key]
        
        # in case the expression only contains the the parameter
        $searchText = "[parameters('$parameterName')]"
        Write-Verbose "Replacing '$searchText' with '$parameterDefaultValue"
        $originalText = $originalText.Replace($searchText, $parameterDefaultValue.Trim().Trim('"'))
        
        # if the parameter is used in a more complex expression, we need to change the defaultl-value accordingly
        # replace surrounding " with ' as default values for strings are defined as "..." but when used in code the need to be '...'
        if($parameterDefaultValue -like '"*"')
        {
            $parameterDefaultValue = $parameterDefaultValue.Trim().Trim('"')
            # a default value may also contain a function and/or a reference to another parameter so we check for common patterns of functions/references
            if($parameterDefaultValue -like "*('*" -or $parameterDefaultValue -like "*().*")
            {
                $parameterDefaultValue = "[" + $parameterDefaultValue + "]"
            }
            else # a regular fixed text -> we add single brackets
            {
                $parameterDefaultValue = "'" + $parameterDefaultValue + "'"
            }
        }
        
        $searchText = "parameters('$parameterName')"
        Write-Verbose "Replacing '$searchText' with '$parameterDefaultValue"
        $originalText = $originalText.Replace($searchText, $parameterDefaultValue)
    }
    
    return $originalText
}

function ReplaceIn-ARMProperty([string]$propertyName, $propertyValue, $parameterDefaultValues)
{
    Write-Verbose "Replacing parameters in '$propertyName' ..."
    if($propertyValue)
    {
        $armPropertyNew = $propertyValue | ConvertTo-Json -Depth 100 | ForEach-Object { [System.Text.RegularExpressions.Regex]::Unescape($_) }
        $armPropertyNew = Replace-Parameter -originalText $armPropertyNew -parameterDefaultValues $parameterDefaultValues
        Write-Verbose "Add $propertyName to new ARM template ..."
        return ' "' + $propertyName + '": ' + $armPropertyNew  + ", `n"
    }
}

$armTemplate = Get-Content -Path $TemplatePathIn | ConvertFrom-Json

$armParameters = $armTemplate.parameters

# get the defaultValues for all parameters
$armParametersWithDefault = $armParameters.PSObject.Properties | Where-Object { CheckFor-DefaultValue -object $_ -parametersToKeep $ParametersToKeep } 
$parameterDefaultValues = @{}
$armParametersWithDefault | ForEach-Object { $parameterDefaultValues[$_.name] = $_.Value.defaultValue | ConvertTo-Json -Depth 100 | ForEach-Object { [System.Text.RegularExpressions.Regex]::Unescape($_) } }

$armTemplateNew = '{
"$schema": "'
 + $armTemplate.'$schema' + '",
"contentVersion": "'
 + $armTemplate.contentVersion + '",
'


# process parameters without a defaultvalue
[PSObject]$armParametersNew = New-Object -TypeName PSObject
$armParameters.PSObject.Properties | Where-Object { -not (CheckFor-DefaultValue -object $_ -parametersToKeep $ParametersToKeep) } | ForEach-Object { $armParametersNew | Add-Member -MemberType NoteProperty -Name $_.Name -Value $_.Value }
$armParametersNew = $armParametersNew | ConvertTo-Json -Depth 100 | ForEach-Object { [System.Text.RegularExpressions.Regex]::Unescape($_) }

Write-Verbose 'Add parameters to new ARM template ...'
$armTemplateNew += ' "parameters": ' + $armParametersNew  + ", `n"

# process remaining properties in ARM template
foreach($jsonProperty in @('variables', 'resources', 'outputs'))
{
    Write-Verbose "Replacing parameters in '$jsonProperty' ..."
    if($armTemplate.PSObject.Properties[$jsonProperty])
    {
        $armPropertyNew = $armTemplate.PSObject.Properties[$jsonProperty].Value | ConvertTo-Json -Depth 100 | ForEach-Object { [System.Text.RegularExpressions.Regex]::Unescape($_) }
        $armPropertyNew = Replace-Parameter -originalText $armPropertyNew -parameterDefaultValues $parameterDefaultValues
        Write-Verbose "Add $jsonProperty to new ARM template ..."
        $armTemplateNew += ' "' + $jsonProperty + '": ' + $armPropertyNew  + ", `n"
    }
}

$armTemplateNew += ReplaceIn-ARMProperty -propertyName "variables" -propertyValue $armTemplate.variables -parameterDefaultValues $parameterDefaultValues
$armTemplateNew += ReplaceIn-ARMProperty -propertyName "resources" -propertyValue $armTemplate.resources -parameterDefaultValues $parameterDefaultValues
$armTemplateNew += ReplaceIn-ARMProperty -propertyName "outputs" -propertyValue $armTemplate.outputs -parameterDefaultValues $parameterDefaultValues


$armTemplateNew = $armTemplateNew.Trim().Trim(',') + "`n}"


$armTemplateNew | Out-File -FilePath $TemplatePathOut -Encoding utf8