diff --git a/eng/common/TestResources/AzurePowerShellV4/Utility.ps1 b/eng/common/TestResources/AzurePowerShellV4/Utility.ps1 new file mode 100644 index 000000000..0bac797fb --- /dev/null +++ b/eng/common/TestResources/AzurePowerShellV4/Utility.ps1 @@ -0,0 +1,153 @@ +# Copied from https://github.com/microsoft/azure-pipelines-tasks/blob/a1502bbe67561f5bec8402f32c997406f798a019/Tasks/AzurePowerShellV4/Utility.ps1 + +function Get-SavedModulePath { + [CmdletBinding()] + param([string] $azurePowerShellVersion) + $savedModulePath = $($env:SystemDrive + "\Modules\az_" + $azurePowerShellVersion) + Write-Verbose "The value of the module path is: $savedModulePath" + return $savedModulePath +} + +function Get-SavedModulePathLinux { + [CmdletBinding()] + param([string] $azurePowerShellVersion) + $savedModulePath = $("/usr/share/az_" + $azurePowerShellVersion) + Write-Verbose "The value of the module path is: $savedModulePath" + return $savedModulePath +} + +function Update-PSModulePathForHostedAgent { + [CmdletBinding()] + param([string] $targetAzurePs) + try { + if ($targetAzurePs) { + $hostedAgentAzModulePath = Get-SavedModulePath -azurePowerShellVersion $targetAzurePs + } + else { + $hostedAgentAzModulePath = Get-LatestModule -patternToMatch "^az_[0-9]+\.[0-9]+\.[0-9]+$" -patternToExtract "[0-9]+\.[0-9]+\.[0-9]+$" + } + $env:PSModulePath = $hostedAgentAzModulePath + ";" + $env:PSModulePath + $env:PSModulePath = $env:PSModulePath.TrimStart(';') + } finally { + Write-Verbose "The updated value of the PSModulePath is: $($env:PSModulePath)" + } +} + +function Update-PSModulePathForHostedAgentLinux { + [CmdletBinding()] + param([string] $targetAzurePs) + try { + if ($targetAzurePs) { + $hostedAgentAzModulePath = Get-SavedModulePathLinux -azurePowerShellVersion $targetAzurePs + if(!(Test-Path $hostedAgentAzModulePath)) { + Write-Verbose "No module path found with this name" + throw ("Could not find the module path with given version.") + } + } + else { + $hostedAgentAzModulePath = Get-LatestModuleLinux -patternToMatch "^az_[0-9]+\.[0-9]+\.[0-9]+$" -patternToExtract "[0-9]+\.[0-9]+\.[0-9]+$" + } + $env:PSModulePath = $hostedAgentAzModulePath + ":" + $env:PSModulePath + $env:PSModulePath = $env:PSModulePath.TrimStart(':') + } finally { + Write-Verbose "The updated value of the PSModulePath is: $($env:PSModulePath)" + } +} + +function Get-LatestModule { + [CmdletBinding()] + param([string] $patternToMatch, + [string] $patternToExtract) + + $resultFolder = "" + $regexToMatch = New-Object -TypeName System.Text.RegularExpressions.Regex -ArgumentList $patternToMatch + $regexToExtract = New-Object -TypeName System.Text.RegularExpressions.Regex -ArgumentList $patternToExtract + $maxVersion = [version] "0.0.0" + $modulePath = $env:SystemDrive + "\Modules"; + + try { + if (-not (Test-Path -Path $modulePath)) { + return $resultFolder + } + + $moduleFolders = Get-ChildItem -Directory -Path $modulePath | Where-Object { $regexToMatch.IsMatch($_.Name) } + foreach ($moduleFolder in $moduleFolders) { + $moduleVersion = [version] $($regexToExtract.Match($moduleFolder.Name).Groups[0].Value) + if($moduleVersion -gt $maxVersion) { + $modulePath = [System.IO.Path]::Combine($moduleFolder.FullName,"Az\$moduleVersion\Az.psm1") + + if(Test-Path -LiteralPath $modulePath -PathType Leaf) { + $maxVersion = $moduleVersion + $resultFolder = $moduleFolder.FullName + } else { + Write-Verbose "A folder matching the module folder pattern was found at $($moduleFolder.FullName) but didn't contain a valid module file" + } + } + } + } + catch { + Write-Verbose "Attempting to find the Latest Module Folder failed with the error: $($_.Exception.Message)" + $resultFolder = "" + } + Write-Verbose "Latest module folder detected: $resultFolder" + return $resultFolder +} + +function Get-LatestModuleLinux { + [CmdletBinding()] + param([string] $patternToMatch, + [string] $patternToExtract) + + $resultFolder = "" + $regexToMatch = New-Object -TypeName System.Text.RegularExpressions.Regex -ArgumentList $patternToMatch + $regexToExtract = New-Object -TypeName System.Text.RegularExpressions.Regex -ArgumentList $patternToExtract + $maxVersion = [version] "0.0.0" + + try { + $moduleFolders = Get-ChildItem -Directory -Path $("/usr/share") | Where-Object { $regexToMatch.IsMatch($_.Name) } + foreach ($moduleFolder in $moduleFolders) { + $moduleVersion = [version] $($regexToExtract.Match($moduleFolder.Name).Groups[0].Value) + if($moduleVersion -gt $maxVersion) { + $modulePath = [System.IO.Path]::Combine($moduleFolder.FullName,"Az/$moduleVersion/Az.psm1") + + if(Test-Path -LiteralPath $modulePath -PathType Leaf) { + $maxVersion = $moduleVersion + $resultFolder = $moduleFolder.FullName + } else { + Write-Verbose "A folder matching the module folder pattern was found at $($moduleFolder.FullName) but didn't contain a valid module file" + } + } + } + } + catch { + Write-Verbose "Attempting to find the Latest Module Folder failed with the error: $($_.Exception.Message)" + $resultFolder = "" + } + Write-Verbose "Latest module folder detected: $resultFolder" + return $resultFolder +} + +function CleanUp-PSModulePathForHostedAgent { + # Clean up PSModulePath for hosted agent + $azureRMModulePath = "C:\Modules\azurerm_2.1.0" + $azureModulePath = "C:\Modules\azure_2.1.0" + $azPSModulePath = $env:PSModulePath + + if ($azPSModulePath.split(";") -contains $azureRMModulePath) { + $azPSModulePath = (($azPSModulePath).Split(";") | ? { $_ -ne $azureRMModulePath }) -join ";" + write-verbose "$azureRMModulePath removed. Restart the prompt for the changes to take effect." + } + else { + write-verbose "$azureRMModulePath is not present in $azPSModulePath" + } + + if ($azPSModulePath.split(";") -contains $azureModulePath) { + $azPSModulePath = (($azPSModulePath).Split(";") | ? { $_ -ne $azureModulePath }) -join ";" + write-verbose "$azureModulePath removed. Restart the prompt for the changes to take effect." + } + else { + write-verbose "$azureModulePath is not present in $azPSModulePath" + } + + $env:PSModulePath = $azPSModulePath +} diff --git a/eng/common/TestResources/Import-AzModules.ps1 b/eng/common/TestResources/Import-AzModules.ps1 new file mode 100644 index 000000000..3cd7b3124 --- /dev/null +++ b/eng/common/TestResources/Import-AzModules.ps1 @@ -0,0 +1,11 @@ +. "$PSScriptRoot/AzurePowerShellV4/Utility.ps1" + +if ($IsWindows) { + # Copied from https://github.com/microsoft/azure-pipelines-tasks/blob/9cc8e1b3ee37dc023c81290de1dd522b77faccf7/Tasks/AzurePowerShellV4/AzurePowerShell.ps1#L57-L58 + CleanUp-PSModulePathForHostedAgent + Update-PSModulePathForHostedAgent +} +else { + # Copied from https://github.com/microsoft/azure-pipelines-tasks/blob/9cc8e1b3ee37dc023c81290de1dd522b77faccf7/Tasks/AzurePowerShellV4/InitializeAz.ps1#L16 + Update-PSModulePathForHostedAgentLinux +} diff --git a/eng/common/TestResources/deploy-test-resources.yml b/eng/common/TestResources/deploy-test-resources.yml index 7f6b6daac..6f0db25d6 100644 --- a/eng/common/TestResources/deploy-test-resources.yml +++ b/eng/common/TestResources/deploy-test-resources.yml @@ -21,6 +21,8 @@ steps: - template: /eng/common/TestResources/setup-az-modules.yml - pwsh: | + eng/common/TestResources/Import-AzModules.ps1 + $subscriptionConfiguration = @" ${{ parameters.SubscriptionConfiguration }} "@ | ConvertFrom-Json -AsHashtable; diff --git a/eng/common/TestResources/remove-test-resources.yml b/eng/common/TestResources/remove-test-resources.yml index 01e9f64d5..a0871a2ff 100644 --- a/eng/common/TestResources/remove-test-resources.yml +++ b/eng/common/TestResources/remove-test-resources.yml @@ -21,6 +21,8 @@ parameters: steps: - pwsh: | + eng/common/TestResources/Import-AzModules.ps1 + $subscriptionConfiguration = @" ${{ parameters.SubscriptionConfiguration }} "@ | ConvertFrom-Json -AsHashtable; diff --git a/eng/common/TestResources/setup-az-modules.yml b/eng/common/TestResources/setup-az-modules.yml index 9329ddf58..b5369f433 100644 --- a/eng/common/TestResources/setup-az-modules.yml +++ b/eng/common/TestResources/setup-az-modules.yml @@ -20,16 +20,14 @@ steps: displayName: (MacOS) Grant access to ~/.Azure condition: contains(variables['OSVmImage'], 'mac') - # New-TestResources command requires Az module - - pwsh: Install-Module -Name Az -Scope CurrentUser -AllowClobber -Force -Verbose - displayName: Install Azure PowerShell module - - task: Powershell@2 inputs: displayName: Register Dogfood environment targetType: inline pwsh: true script: | + eng/common/TestResources/Import-AzModules.ps1 + $environmentSpec = @" $(env-config-dogfood) "@ | ConvertFrom-Json -AsHashtable;