dsc/Start-OsMofUpload.ps1
function Start-OsMofUpload { [cmdletbinding()] Param ( [Parameter(Mandatory = $true)] [validatepattern('\A\w\d\Z')] [String] $Environment, [String] $role, [String] $Prefix = "SPZE2", [String] $Location = "eastus2", [String] $Project, [string] $GlobalRG, [String] $StorageAccountName, [switch] $KeepMof, [switch] $WhatIf, [string] $ProjectDirectory = (Get-Location | Select-Object -ExpandProperty Path) ) try { $GlobalParameters = Get-Content "$ProjectDirectory\global.parameters.json" -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop $EnvironmentParameters = Get-Content "$ProjectDirectory\env\$Location\$Environment\environment.parameters.json" -Raw -ErrorAction Stop | ConvertFrom-Json -ErrorAction Stop $EnvironmentParameters.parameters.Global.value | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name | ForEach-Object { $GlobalParameters.parameters.Global.value | Add-Member -MemberType NoteProperty -Name $_ -Value $EnvironmentParameters.parameters.Global.value.$_ -Force } } catch { throw "Could not generate a valid parameters template and/or import the Project's gobal.parameters.json file! Please check the location!`n$_" } if (-not $Project) { if ($GlobalParameters.parameters.Global.value.AppName) { $Project = $GlobalParameters.parameters.Global.value.AppName } else { throw "Could not find the Project's name in global.parameters.json!" } } if (-not $GlobalRG) { if ($GlobalParameters.parameters.Global.value.GlobalRG) { $GlobalRG = $GlobalParameters.parameters.Global.value.GlobalRG } else { throw "Could not find the GlobalRG parameter in global.parameters.json!" } } if ($StorageAccountName -eq "") { if ($GlobalParameters.parameters.Global.value.globalStorageAccount) { $StorageAccountName = $GlobalParameters.parameters.Global.value.globalStorageAccount if (-not $StorageAccountName) { throw "Could not find storage account $StorageAccountName in the currently selected Azure subscription!" } } else { throw "Could not find a value for globalStorageAccount in the global.parameters.json for $Project!`nPlease provide a Storage Account name." } } if ($project -eq 'atmos' -and $Environment -eq 's1') { $ResourceGroupName = 'SPZE2-ATMOS-SBX-S1' } else { $ResourceGroupName = ($Prefix + '-' + $Project + '-' + $Environment).toUpper() } $AAName = ($Prefix + $Project + $Environment + "OMSAutomation") $ConfigurationFile = "$ProjectDirectory\dsc\roles\$role\role.ps1" # Retrieves username and password from keyvault for DSC resources that need a domain account to run. $StorageAccountKeySource = Get-AzStorageAccountKey -Name $StorageAccountName -ResourceGroupName $GlobalRG | Select-Object -first 1 | ForEach-Object value $StorageCred = [PSCredential]::new($StorageAccountName, (ConvertTo-SecureString -String $StorageAccountKeySource -AsPlainText -Force -ErrorAction stop)) $DomainCred = [PSCredential]::new((Get-AzKeyVaultSecret -VaultName $GlobalParameters.parameters.Global.value.globalKeyvault -Name 'dscaccount' | Select-Object -ExpandProperty SecretValueText), (Get-AzKeyVaultSecret -VaultName $GlobalParameters.parameters.Global.value.globalKeyvault -Name 'dscpassword' | Select-Object -ExpandProperty SecretValue)) $CertCred = [PSCredential]::new('CertCred', (Get-AzKeyVaultSecret -VaultName $GlobalParameters.parameters.Global.value.globalKeyvault -Name 'certPassword' | Select-Object -ExpandProperty SecretValue)) Write-Output "Automation Account: $AAName" Write-Output "Resource Group: $ResourceGroupName" Write-Output "Storage Account: $StorageAccountName" Write-Verbose "Role: $role" Write-Verbose "Project: $Project" Write-Verbose "DomainCred: $DomainCred" Write-Verbose "StorageCred: $StorageCred" # Import role ConfigData to build the mof file. Environment specific ConfigData will override default role settings on a per environment basis. if (Test-Path "$ProjectDirectory\dsc\roles\$role\role.psd1") { $RoleCD = Import-PowerShellDataFile -Path "$ProjectDirectory\dsc\roles\$role\role.psd1" if (Test-Path "$ProjectDirectory\env\$Location\$Environment\dsc\$role\role.psd1") { $EnvRoleCD = Import-PowerShellDataFile -Path "$ProjectDirectory\env\$Location\$Environment\dsc\$role\role.psd1" foreach ($key in $EnvRoleCD.AllNodes[0].Keys) { $RoleCD.AllNodes[0].$key = $EnvRoleCD.AllNodes[0].$key } } $RoleCD | ConvertTo-Json -Depth 100 | Out-File "$ProjectDirectory\temp\$role-ConfigData.json" } else { throw "Missing metadata.json or role.psd1 file for DSC role $role! Please create one!`nFile Path: $ProjectDirectory\dsc\roles\$role\" } # This sets the configuration name to VMSS for the scalesets. if ($role -match 'ssapi|sssf|sssps') { $ConfigurationName = 'VMSS' } else { $ConfigurationName = $ResourceGroupName } # Dot sources the DSC configuration, runs it with the specified ConfigData and generates the Mof file. $ConfigurationParams = @{ StorageAccountName = $StorageAccountName ConfigurationData = $RoleCD ConfigData = $RoleCD.AllNodes StorageCred = $StorageCred DomainCred = $DomainCred CertCred = $CertCred GlobalParameters = $GlobalParameters Environment = $Environment OutputPath = "$ProjectDirectory\temp\" Verbose = $true } . $ConfigurationFile & $role @ConfigurationParams $AutomationParams = @{ AutomationAccountName = $AAName ResourceGroupName = $ResourceGroupName ConfigurationName = $ConfigurationName Path = "$ProjectDirectory\temp\$role.mof" Force = $true Verbose = $true } if (-not $WhatIf) { try { Import-AzAutomationDscNodeConfiguration @AutomationParams } catch { Write-Error "Failed to upload module to Azure Automation account $AAName!`n$_" } } else { $KeepMof = $true } if ($KeepMof) { Write-Warning "$ProjectDirectory\temp\$role.mof file was NOT deleted! Please delete immediately if it contains sensitive information!" } else { Remove-Item "$ProjectDirectory\temp\*.mof" -Force if (Test-Path "$ProjectDirectory\temp\*.mof") { Remove-Item "$ProjectDirectory\temp\*.mof" -Force throw "WARNING! Could not delete generated $ConfigurationName MOF file! Delete immediately! Could contain sensitive information!`nFile Path: $ProjectDirectory\temp\$role.mof" } } } New-Alias -Name DSCDeploy -Value Start-OsMofUpload -Force Register-ArgumentCompleter -CommandName Start-OsMofUpload -ParameterName role -ScriptBlock { param($commandName, $parameterName, $wordToComplete) $foldernames = @() $foldernames += Get-ChildItem ((Get-Location | Select-Object -ExpandProperty Path) + "\dsc\roles") -Directory | Select-Object -ExpandProperty Name $foldernames | Select-Object -Unique | Sort-Object | Where-Object { $_ -like "$wordToComplete*" } | ForEach-Object { "$_" } } |