generated from arcus-azure/arcus.github.template
-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathInject-ArmContent.ps1
123 lines (89 loc) · 4.41 KB
/
Inject-ArmContent.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
<#
Possible injection instructions in ARM templates or recursively referenced files:
${ fileToInject.xml }
${ FileToInject=file.xml }
${ FileToInject = ".\Parent Directory\file.xml" }
${ FileToInject = ".\Parent Directory\file.xml", EscapeJson, ReplaceSpecialChars }
${ FileToInject = '.\Parent Directory\file.json', InjectAsJsonObject }
#>
param (
[string] $Path = $PSScriptRoot
)
function InjectFile {
param(
[string] $filePath
)
Write-Host "Checking file $filePath"
$replaceContentDelegate = {
param($match)
$completeInjectionInstruction = $match.Groups[1].Value;
$instructionParts = @($completeInjectionInstruction -split "," | foreach { $_.Trim() } )
$filePart = $instructionParts[0];
# Regex uses non-capturing group for 'FileToInject' part,
# afterwards character classes and backreferencing to select the optional single or double quotes
$fileToInjectPathRegex = [regex] "^(?:FileToInject\s*=\s*)?([`"`']?)(?<File>.*?)\1?$";
$fileMatch = $fileToInjectPathRegex.Match($filePart)
if ($fileMatch.Success -ne $True){
throw "The file part '$filePart' of the injection instruction could not be parsed correctly"
}
$relativePathOfFileToInject = $fileMatch.Groups["File"];
$fullPathOfFileToInject = Join-Path (Split-Path $filePath -Parent) $relativePathOfFileToInject
$fileToInjectIsFound = Test-Path -Path $fullPathOfFileToInject -PathType Leaf
if ($false -eq $fileToInjectIsFound) {
throw "No file can be found at '$fullPathofFileToInject'"
}
# Inject content recursively first
InjectFile($fullPathOfFileToInject)
Write-Host "`t Injecting content of $fullPathOfFileToInject into $filePath"
$newString = Get-Content -Path $fullPathOfFileToInject -Raw
# XML declaration can only appear on the first line of an XML document, so remove when injecting
$newString = $newString -replace '(<\?xml).+(\?>)(\r)?(\n)?', ""
# By default: retain double quotes around content-to-inject, if present
$surroundContentWithDoubleQuotes = $match.Value.StartsWith('"') -and $match.Value.EndsWith('"')
if ($instructionParts.Length -gt 1) {
$optionParts = $instructionParts | select -Skip 1
if ($optionParts.Contains("ReplaceSpecialChars")){
Write-Host "`t Replacing special characters"
# Replace newline characters with literal equivalents
$newString = $newString -replace "`r`n", "\r\n"
# Replace tabs with spaces
$newString = $newString -replace "`t", " "
# Replace " with \"
$newString = $newString -replace """", "\"""
}
if ($optionParts.Contains("EscapeJson")) {
Write-Host "`t JSON-escaping file content"
# Use regex negative lookbehind to replace double quotes not preceded by a backslash with escaped quotes
$newString = $newString -replace '(?<!\\)"', '\"'
}
if ($optionParts.Contains("InjectAsJsonObject")){
try{
# Test if content is valid JSON
ConvertFrom-Json $newString
$surroundContentWithDoubleQuotes = $False
}
catch{
Write-Error "Content to inject cannot be parsed as a JSON object!"
}
}
}
if ($surroundContentWithDoubleQuotes){
Write-Host "`t Surrounding content in double quotes"
$newString = '"' + $newString + '"'
}
return $newString;
}
$rawContents = Get-Content $filePath -Raw
$injectionInstructionRegex = [regex] '"?\${(.+)}\$"?';
$injectionInstructionRegex.Replace($rawContents, $replaceContentDelegate) | Set-Content $filePath -Encoding UTF8
Write-Host "Done checking file $filePath"
}
$psScriptFileName = $MyInvocation.MyCommand.Name
$PathIsFound = Test-Path -Path $Path
if ($false -eq $PathIsFound) {
throw "Passed allong path '$Path' doesn't point to valid file path"
}
Write-Host "Starting $psScriptFileName script on path $Path"
$armTemplates = Get-ChildItem -Path $Path -Recurse -Include *.json
$armTemplates | ForEach-Object { InjectFile($_.FullName) }
Write-Host "Finished script $psScriptFileName"