Skip to content

Commit ea3339e

Browse files
authored
Merge pull request #528 from soma-ms/vekandib/deploymentscript-bugfixes
Big fixes for bool, timezone issues in trigger payload
2 parents a808533 + d66dded commit ea3339e

File tree

1 file changed

+85
-24
lines changed

1 file changed

+85
-24
lines changed

SamplesV2/ContinuousIntegrationAndDelivery/PrePostDeploymentScript.Ver2.ps1

Lines changed: 85 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,9 @@
2727
Expliticly stops the triggers form this list if the trigger is in started state even if the trigger payload not changed
2828
example: "testTrigger", "storageEventsTrigger"
2929
The script is not very comprehensive in detecting the trigger changes, so this parameter can be used to stop triggers explicitly if required
30+
.PARAMETER MaxJsonDepth
31+
Default: 100
32+
The maximum depth the JSON input is allowed to have
3033
#>
3134
param
3235
(
@@ -36,7 +39,8 @@ param
3639
[parameter(Mandatory = $false)] [Bool] $PreDeployment = $true,
3740
[parameter(Mandatory = $false)] [Bool] $DeleteDeployment = $false,
3841
[parameter(Mandatory = $false)] [String] $ArmTemplateParameters = $null,
39-
[parameter(Mandatory = $false)] [String[]] $ExplicitStopTriggerList = @()
42+
[parameter(Mandatory = $false)] [String[]] $ExplicitStopTriggerList = @(),
43+
[parameter(Mandatory = $false)] [int] $MaxJsonDepth = 100
4044
)
4145

4246
function Get-PipelineDependency {
@@ -175,6 +179,7 @@ function Compare-TriggerPayload {
175179
[PSCustomObject]$templateParameters
176180
)
177181
try {
182+
Write-Host "Comparing '$($triggerDeployed.Name)' trigger payload"
178183
# Parse the trigger json from template to deserialize to trigger object
179184
$triggerInTemplate.properties.typeProperties | Get-Member -MemberType NoteProperty | ForEach-Object {
180185
$triggerInTemplate.properties | Add-Member -NotePropertyName $_.Name -NotePropertyValue $triggerInTemplate.properties.typeProperties.$($_.Name) -Force
@@ -183,11 +188,12 @@ function Compare-TriggerPayload {
183188
$addPropDictionary.Add('typeProperties', $triggerInTemplate.properties.typeProperties)
184189
$triggerInTemplate.properties | Add-Member -NotePropertyName 'additionalProperties' -NotePropertyValue $addPropDictionary
185190
$triggerInTemplate.properties.PSObject.Properties.Remove('typeProperties')
186-
$triggerTemplateJson = ConvertTo-Json -InputObject $triggerInTemplate.properties -Depth 10 -EscapeHandling Default
191+
$triggerTemplateJson = ConvertTo-Json -InputObject $triggerInTemplate.properties -Depth $MaxJsonDepth -EscapeHandling Default
187192
$updatedTemplateJson = Update-TriggerTemplate -templateJson $triggerTemplateJson -templateParameters $templateParameters
188193
$serializerOptions = New-Object System.Text.Json.JsonSerializerOptions -Property @{ PropertyNameCaseInsensitive = $True }
189-
$payloadPSObject = $updatedTemplateJson | ConvertFrom-Json -Depth 10
194+
$payloadPSObject = $updatedTemplateJson | ConvertFrom-Json -Depth $MaxJsonDepth
190195
if ($triggerDeployed.Properties.RuntimeState -ne $payloadPSObject.runtimeState) {
196+
Write-Host "Change detected in '$($triggerDeployed.Name)' trigger payload - runtimeState changed"
191197
return $True;
192198
}
193199

@@ -199,7 +205,7 @@ function Compare-TriggerPayload {
199205
if ($payloadPSObject.recurrence.schedule.monthlyOccurrences) {
200206
$payloadPSObject.recurrence.schedule.monthlyOccurrences | ForEach-Object { $_.day = ([System.DayOfWeek]::$($_.day)).value__ }
201207
}
202-
$updatedTemplateJson = ConvertTo-Json -InputObject $payloadPSObject -Depth 10
208+
$updatedTemplateJson = ConvertTo-Json -InputObject $payloadPSObject -Depth $MaxJsonDepth
203209

204210
$triggerPayload = [System.Text.Json.JsonSerializer]::Deserialize($updatedTemplateJson,
205211
[Microsoft.Azure.Management.DataFactory.Models.ScheduleTrigger],
@@ -225,10 +231,11 @@ function Compare-TriggerPayload {
225231
return Compare-CustomEventsTrigger -triggerDeployed $triggerDeployed -triggerPayload $triggerPayload
226232
}
227233

234+
Write-Host "##[warning] Comparison terminated as trigger type '$($triggerDeployed.Properties.GetType().Name)' not match"
228235
return $True
229236
}
230237
catch {
231-
Write-Host "##[warning] Unable to compare payload for '$($triggerDeployed.Name)' trigger, this is not a failure. You can post the issue to https://github.com/Azure/Azure-DataFactory/issues to check if this is user error or limitation."
238+
Write-Host "##[warning] Unable to compare '$($triggerDeployed.Name)' trigger payload, this is not a failure. You can post the issue to https://github.com/Azure/Azure-DataFactory/issues to check if this is user error or limitation."
232239
Write-Host "##[warning] $_ from Line: $($_.InvocationInfo.ScriptLineNumber)"
233240
return $True;
234241
}
@@ -273,16 +280,21 @@ function Compare-ScheduleTrigger {
273280
# Compare to check if there is any change in referenced pipeline
274281
$pipelineRefChanged = Compare-TriggerPipelineReference -tprDeployed $deployedTriggerProps.Pipelines -tprPayload $triggerPayload.Pipelines
275282

283+
# Temporary workaround for Get-AzDataFactoryV2Trigger returning incorrect datetime notation
284+
# https://github.com/Azure/azure-powershell/issues/20474 issue, thanks to gvdmaaden for this workaround
285+
Update-TriggerTimeFormat -deployedAdditionalProps $deployedTriggerProps.AdditionalProperties
286+
276287
# Compare additional properties (unmatched properties stay here)
277-
$additionalPropsChanged = Compare-TriggerAdditionalProperty -deployedAdditionalProps $triggerDeployed.Properties.AdditionalProperties `
288+
$additionalPropsChanged = Compare-TriggerAdditionalProperty -deployedAdditionalProps $deployedTriggerProps.AdditionalProperties `
278289
-payloadAdditionalProps $triggerPayload.AdditionalProperties
279290

280291
if (($null -ne $descriptionChanges) -or ($null -ne $annotationChanges) -or ($null -ne $recurrencechanges) -or `
281292
$scheduleChanged -or $pipelineRefChanged -or $additionalPropsChanged) {
293+
Write-Host "Change detected in '$($triggerDeployed.Name)' trigger payload - descriptionChanges=$($descriptionChanges.Length), annotationChanges=$($annotationChanges.Length), recurrencechanges=$($recurrencechanges.Length), scheduleChanged=$scheduleChanged, pipelineRefChanged=$pipelineRefChanged, additionalPropsChanged=$additionalPropsChanged"
282294
return $True
283295
}
284296

285-
Write-Host "No change in payload for '$($triggerDeployed.Name)' trigger"
297+
Write-Host "No change detected in '$($triggerDeployed.Name)' trigger payload"
286298
return $False;
287299
}
288300

@@ -311,10 +323,11 @@ function Compare-TumblingWindowTrigger {
311323

312324
if (($null -ne $propertyChanges) -or ($null -ne $annotationChanges) -or ($null -ne $retryPolicyChanges) -or `
313325
$pipelineRefChanged -or $additionalPropsChanged) {
326+
Write-Host "Change detected in '$($triggerDeployed.Name)' trigger payload - propertyChanges=$($propertyChanges.Length), annotationChanges=$($annotationChanges.Length), retryPolicyChanges=$($retryPolicyChanges.Length), pipelineRefChanged=$pipelineRefChanged, additionalPropsChanged=$additionalPropsChanged"
314327
return $True
315328
}
316329

317-
Write-Host "No change in payload for '$($triggerDeployed.Name)' trigger"
330+
Write-Host "No change detected in '$($triggerDeployed.Name)' trigger payload"
318331
return $False;
319332
}
320333

@@ -335,10 +348,11 @@ function Compare-BlobEventsTrigger {
335348
-payloadAdditionalProps $triggerPayload.AdditionalProperties
336349

337350
if (($null -ne $propertyChanges) -or ($null -ne $annotationChanges) -or $pipelineRefChanged -or $additionalPropsChanged) {
351+
Write-Host "Change detected in '$($triggerDeployed.Name)' trigger payload - propertyChanges=($propertyChanges.Length), annotationChanges=$($annotationChanges.Length), pipelineRefChanged=$pipelineRefChanged, additionalPropsChanged=$additionalPropsChanged"
338352
return $True
339353
}
340354

341-
Write-Host "No change in payload for '$($triggerDeployed.Name)' trigger"
355+
Write-Host "No change detected in '$($triggerDeployed.Name)' trigger payload"
342356
return $False;
343357
}
344358

@@ -363,10 +377,11 @@ function Compare-CustomEventsTrigger {
363377

364378
if (($null -ne $propertyChanges) -or ($null -ne $eventChanges) -or ($null -ne $annotationChanges) -or `
365379
$pipelineRefChanged -or $additionalPropsChanged) {
380+
Write-Host "Change detected in '$($triggerDeployed.Name)' trigger payload - propertyChanges=$($propertyChanges.Length), eventChanges=$($eventChanges.Length), annotationChanges=$($annotationChanges.Length), pipelineRefChanged=$pipelineRefChanged, additionalPropsChanged=$additionalPropsChanged"
366381
return $True
367382
}
368383

369-
Write-Host "No change in payload for '$($triggerDeployed.Name)' trigger"
384+
Write-Host "No change detected in '$($triggerDeployed.Name)' trigger payload"
370385
return $False;
371386
}
372387

@@ -404,7 +419,19 @@ function Compare-TriggerPipelineReference {
404419
break
405420
}
406421
else {
407-
$paramValueChanges = Compare-Object -ReferenceObject $deployedValue -DifferenceObject $payloadValue
422+
if ($deployedValue.GetType().Name -in @("JObject", "JArray")) {
423+
if (($deployedValue.ToString() | ConvertFrom-Json).type -eq "SecureString") {
424+
$paramsChanged = $True
425+
Write-Host "##[warning] SecureString parameter is always treated as a change"
426+
break
427+
} else {
428+
$paramValueChanges = Compare-Object -ReferenceObject ($deployedValue.ToString() | ConvertFrom-Json) -DifferenceObject ($payloadValue.ToString() | ConvertFrom-Json)
429+
}
430+
} elseif ($deployedValue.GetType().Name -eq "Boolean") {
431+
$paramValueChanges = Compare-Object -ReferenceObject ($deployedValue.ToString().ToLower() | ConvertFrom-Json) -DifferenceObject ($payloadValue.ToString().ToLower() | ConvertFrom-Json)
432+
} else {
433+
$paramValueChanges = Compare-Object -ReferenceObject $deployedValue -DifferenceObject $payloadValue
434+
}
408435
if ($paramValueChanges.Length -gt 0) {
409436
$paramsChanged = $True
410437
break
@@ -458,21 +485,48 @@ function Compare-TriggerAdditionalProperty {
458485
return $additionalPropchanged
459486
}
460487

488+
function Update-TriggerTimeFormat {
489+
param(
490+
[System.Collections.Generic.Dictionary[String, System.Object]]$deployedAdditionalProps
491+
)
492+
foreach ($key in $deployedAdditionalProps.Keys) {
493+
$deployedValue = $null;
494+
if ($deployedAdditionalProps.TryGetValue($key, [ref]$deployedValue) -and $deployedValue["recurrence"]["timeZone"] -ne "UTC")
495+
{
496+
if ($null -ne $deployedValue["recurrence"]["startTime"]) {
497+
$startTimeString = $deployedValue["recurrence"]["startTime"].ToString("yyyy-MM-ddTHH:mm:ss");
498+
$startDateTime = Get-Date -Date $startTimeString;
499+
$deployedValue["recurrence"]["startTime"] = New-Object DateTime 2000, 1, 1, 1, 0, 0, ([DateTimeKind]::Unspecified)
500+
$deployedValue["recurrence"]["startTime"] = New-Object DateTime $startDateTime.Year, $startDateTime.Month, $startDateTime.Day, $startDateTime.Hour, $startDateTime.Minute, $startDateTime.Second, ([DateTimeKind]::Unspecified)
501+
}
502+
503+
if ($null -ne $deployedValue["recurrence"]["endTime"]) {
504+
$endTimeString = $deployedValue["recurrence"]["endTime"].ToString("yyyy-MM-ddTHH:mm:ss");
505+
$endDateTime = Get-Date -Date $endTimeString;
506+
$deployedValue["recurrence"]["endTime"] = New-Object DateTime 2000, 1, 1, 1, 0, 0, ([DateTimeKind]::Unspecified)
507+
$deployedValue["recurrence"]["endTime"] = New-Object DateTime $endDateTime.Year, $endDateTime.Month, $endDateTime.Day, $endDateTime.Hour, $endDateTime.Minute, $endDateTime.Second, ([DateTimeKind]::Unspecified)
508+
}
509+
}
510+
}
511+
}
512+
461513
function Update-TriggerTemplate {
462514
param(
463515
[string]$templateJson,
464516
[PSCustomObject]$templateParameters
465517
)
466518
$parameterMatches = [System.Text.RegularExpressions.Regex]::Matches($templateJson, '\[parameters\([^)]*\)\]')
467519
foreach ($parameterMatch in $parameterMatches) {
468-
$parameterName = $parameterMatch.Value.Substring(13, $parameterMatch.Value.Length - 16)
469-
if ($null -ne $templateParameters.$($parameterName)) {
470-
$parameterType = $templateParameters.$($parameterName).value ? $templateParameters.$($parameterName).value.GetType().Name : $null
471-
if ($parameterType -eq 'Object[]') {
472-
$parameterValue = ConvertTo-Json $templateParameters.$($parameterName).value
520+
[string]$parameterName = $parameterMatch.Value.Substring(13, $parameterMatch.Value.Length - 16)
521+
if ($null -ne $templateParameters.$($parameterName) && ($PreDeployment || $parameterName.EndsWith('runtimeState'))) {
522+
$parameterType = $null -ne $templateParameters.$($parameterName).value ? $templateParameters.$($parameterName).value.GetType().Name : $null
523+
if ($parameterType -eq 'Object[]' -or $parameterType -eq 'PSCustomObject') {
524+
$parameterValue = ConvertTo-Json $templateParameters.$($parameterName).value -Depth $MaxJsonDepth -EscapeHandling Default
473525
$templateJson = $templateJson -replace [System.Text.RegularExpressions.Regex]::Escape("`"$($parameterMatch.Value)`""), $parameterValue
474-
} elseif ($parameterType -eq 'Boolean' -or $parameterType -eq 'Int64') {
526+
} elseif ($parameterType -eq 'Int64') {
475527
$templateJson = $templateJson -replace [System.Text.RegularExpressions.Regex]::Escape("`"$($parameterMatch.Value)`""), $templateParameters.$($parameterName).value
528+
} elseif ($parameterType -eq 'Boolean') {
529+
$templateJson = $templateJson -replace [System.Text.RegularExpressions.Regex]::Escape("`"$($parameterMatch.Value)`""), $templateParameters.$($parameterName).value.ToString().ToLower()
476530
} else {
477531
$templateJson = $templateJson -replace [System.Text.RegularExpressions.Regex]::Escape($parameterMatch.Value), $templateParameters.$($parameterName).value
478532
}
@@ -487,7 +541,7 @@ try {
487541
$PSCompatible = $True
488542
if ($PSVersionTable.PSEdition -ne 'Core' -and ([System.Version]$PSVersionTable.PSVersion -lt [System.Version]"7.0.0")) {
489543
$PSCompatible = $False
490-
Write-Host "##[warning] The script is not compatible with your current PowerShell version $($PSVersionTable.PSVersion). Use either PowerShell Core or at least PS version 7.0, otherwise the script may fail to compare the trigger payload and start the trigger(s)"
544+
Write-Host "##[warning] The script is not compatible with your current PowerShell version $($PSVersionTable.PSVersion). Use either PowerShell Core or at least PS version 7.0, otherwise the script may fail to compare the trigger payload and always stop/start the trigger(s)"
491545
}
492546

493547
$templateJson = Get-Content $ArmTemplate | ConvertFrom-Json
@@ -503,7 +557,7 @@ try {
503557
$templateParametersJson = Get-Content $ArmTemplateParameters | ConvertFrom-Json
504558
$templateParameters = $templateParametersJson.parameters
505559
} else {
506-
Write-Host "##[warning] The script couldn't find the arm-tempalte parameter file in the arm-template file path, the trigger comparision won't work for parameterized properties. Please pass the arm-template parameter file path to ArmTemplateParameters script argument."
560+
Write-Host "##[warning] The script couldn't find the arm-tempalte parameter file in the arm-template file path, the trigger comparison won't work for parameterized properties. Please pass the arm-template parameter file path to ArmTemplateParameters script argument."
507561
}
508562

509563
#Triggers
@@ -674,10 +728,15 @@ try {
674728

675729
$updatedTriggersInTemplate = $triggersInTemplate
676730
if ($PSCompatible) {
677-
$updatedTriggersInTemplate = $triggersInTemplate | ForEach-Object {
678-
$triggerJson = ConvertTo-Json -InputObject $_ -Depth 10 -EscapeHandling Default
679-
Update-TriggerTemplate -templateJson $triggerJson -templateParameters $templateParameters
680-
} | ConvertFrom-Json -Depth 10
731+
try {
732+
$updatedTriggersInTemplate = $triggersInTemplate | ForEach-Object {
733+
$triggerJson = ConvertTo-Json -InputObject $_ -Depth $MaxJsonDepth -EscapeHandling Default
734+
Update-TriggerTemplate -templateJson $triggerJson -templateParameters $templateParameters
735+
} | ConvertFrom-Json -Depth $MaxJsonDepth
736+
} catch {
737+
Write-Host "##[warning] Unable to update the parameterized properties in trigger template. The script may fail to start triggers if using parameterized runtimeState."
738+
$updatedTriggersInTemplate = $triggersInTemplate
739+
}
681740
}
682741

683742
$triggersToStart = $updatedTriggersInTemplate | Where-Object { $_.properties.runtimeState -eq 'Started' -and $_.name.Substring(37, $_.name.Length - 40) -notin $triggersRunning } `
@@ -688,7 +747,9 @@ try {
688747
}
689748
}
690749

691-
Write-Host "Starting $($triggersToStart.Count) triggers"
750+
if ($triggersToStart.Count -gt 0) {
751+
Write-Host "Starting $($triggersToStart.Count) triggers"
752+
}
692753

693754
$triggersToStart | ForEach-Object {
694755
if ($_.TriggerType -eq 'BlobEventsTrigger') {

0 commit comments

Comments
 (0)