From 8279e2439699d2ffd7a5b01e9fe877e3bd7444f8 Mon Sep 17 00:00:00 2001 From: Justin Grote Date: Mon, 27 Mar 2023 10:17:46 -0700 Subject: [PATCH 1/2] Fix profile folder casing --- linux/powershell/PSCloudShellStartup.ps1 | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/linux/powershell/PSCloudShellStartup.ps1 b/linux/powershell/PSCloudShellStartup.ps1 index ce665443..48ba1a45 100644 --- a/linux/powershell/PSCloudShellStartup.ps1 +++ b/linux/powershell/PSCloudShellStartup.ps1 @@ -33,8 +33,14 @@ Az.Accounts\Enable-AzureRmAlias # For Pwsh profile, see https://docs.microsoft.com/en-us/powershell/scripting/whats-new/what-s-new-in-powershell-core-60?view=powershell-6#filesystem $script:UserDefaultPath = $HOME -$script:CurrentHostProfilePath = (Microsoft.PowerShell.Management\Join-Path -Path $script:UserDefaultPath -ChildPath '.config/PowerShell/Microsoft.PowerShell_profile.ps1') -$script:AllHostsProfilePath = (Microsoft.PowerShell.Management\Join-Path -Path $script:UserDefaultPath -ChildPath '.config/PowerShell/profile.ps1') +$script:CurrentHostProfilePath = (Microsoft.PowerShell.Management\Join-Path -Path $script:UserDefaultPath -ChildPath '.config/powershell/Microsoft.PowerShell_profile.ps1') +$script:AllHostsProfilePath = (Microsoft.PowerShell.Management\Join-Path -Path $script:UserDefaultPath -ChildPath '.config/powershell/profile.ps1') + +#Added to help migration from a breaking change of fixing incorrectly cased powershell profile paths +$legacyUpperCaseProfilePath = (Microsoft.PowerShell.Management\Join-Path -Path $script:UserDefaultPath -ChildPath '.config/PowerShell') +if (Test-Path $legacyUpperCaseProfilePath) { + Write-Warning "We detected you have a profile folder at $upperProfilePath. Please move these files to .config/powershell instead of .config/PowerShell (case sensitive difference) in your home folder to re-enable your profile files." +} # To ensure that the installed script is immediately usable, we need to add the scope path to the PATH enviroment variable. $scriptPath = Microsoft.PowerShell.Management\Join-Path $env:HOME '.local/share/powershell/Scripts' From 9df63c9272a990609bb66a67ab2127f39373a80e Mon Sep 17 00:00:00 2001 From: Justin Grote Date: Mon, 3 Apr 2023 11:43:16 -0700 Subject: [PATCH 2/2] Add migration logic to script --- linux/powershell/PSCloudShellStartup.ps1 | 81 ++++++++++++++++++------ 1 file changed, 63 insertions(+), 18 deletions(-) diff --git a/linux/powershell/PSCloudShellStartup.ps1 b/linux/powershell/PSCloudShellStartup.ps1 index 48ba1a45..62b3cfbf 100644 --- a/linux/powershell/PSCloudShellStartup.ps1 +++ b/linux/powershell/PSCloudShellStartup.ps1 @@ -1,7 +1,7 @@ # Startupscript for PowerShell Cloud Shell #region Script Variables -$script:Startuptime = [System.DateTime]::Now +$script:Startuptime = [System.DateTime]::Now $script:AzureADModuleName = 'AzureAD.Standard.Preview' # Set SkipAzInstallationChecks to avoid az check for AzInstallationChecks.json @@ -14,8 +14,8 @@ Microsoft.PowerShell.Core\Import-Module -Name PSCloudShellUtility $script:PSCloudShellUtilityModuleInfo = Microsoft.PowerShell.Core\Get-Module PSCloudShellUtility $script:CloudEnvironmentMap = @{ - PROD = 'AzureCloud'; - Fairfax = 'AzureUSGovernment'; + PROD = 'AzureCloud'; + Fairfax = 'AzureUSGovernment'; Mooncake = 'AzureChinaCloud'; BlackForest = 'AzureGermanCloud'; dogfood = 'dogfood' @@ -29,18 +29,15 @@ Microsoft.PowerShell.Core\Import-Module Az.Tools.Predictor -Force Microsoft.PowerShell.Core\Import-Module Az.Accounts Az.Accounts\Enable-AzureRmAlias -# On Linux, we are not loading the profile from the clouddrive since we are already mounted on the Linux OS image: \clouddrive\.cloudconsole\acc_.img +# On Linux, we are not loading the profile from the clouddrive since we are already mounted on the Linux OS image: \clouddrive\.cloudconsole\acc_.img # For Pwsh profile, see https://docs.microsoft.com/en-us/powershell/scripting/whats-new/what-s-new-in-powershell-core-60?view=powershell-6#filesystem - + $script:UserDefaultPath = $HOME $script:CurrentHostProfilePath = (Microsoft.PowerShell.Management\Join-Path -Path $script:UserDefaultPath -ChildPath '.config/powershell/Microsoft.PowerShell_profile.ps1') -$script:AllHostsProfilePath = (Microsoft.PowerShell.Management\Join-Path -Path $script:UserDefaultPath -ChildPath '.config/powershell/profile.ps1') +$script:AllHostsProfilePath = (Microsoft.PowerShell.Management\Join-Path -Path $script:UserDefaultPath -ChildPath '.config/powershell/profile.ps1') + +Complete-UpperCaseProfileFolderMigration -#Added to help migration from a breaking change of fixing incorrectly cased powershell profile paths -$legacyUpperCaseProfilePath = (Microsoft.PowerShell.Management\Join-Path -Path $script:UserDefaultPath -ChildPath '.config/PowerShell') -if (Test-Path $legacyUpperCaseProfilePath) { - Write-Warning "We detected you have a profile folder at $upperProfilePath. Please move these files to .config/powershell instead of .config/PowerShell (case sensitive difference) in your home folder to re-enable your profile files." -} # To ensure that the installed script is immediately usable, we need to add the scope path to the PATH enviroment variable. $scriptPath = Microsoft.PowerShell.Management\Join-Path $env:HOME '.local/share/powershell/Scripts' @@ -54,6 +51,54 @@ if(($existingPath -split ':') -notcontains $scriptPath) #region Utility Functions +# Migrate profile from incorrect uppercase profile location to standard location. Added to help migration from a breaking change of fixing incorrectly cased powershell profile paths +function Complete-UpperCaseProfileFolderMigration { + [CmdletBinding(SupportsShouldProcess,ConfirmImpact='High')] + param() + + $errorActionPreference = 'stop' + + $legacyUpperCaseProfilePath = (Microsoft.PowerShell.Management\Join-Path -Path $script:UserDefaultPath -ChildPath '.config/PowerShell') + $standardProfilePath = Split-Path $script:CurrentHostProfilePath + + if (-not (Test-Path $legacyUpperCaseProfilePath)) { + #Nothing to do + return + } + + $legacyUpperCaseProfilePathItem = Get-Item $legacyUpperCaseProfilePath + if ($legacyUpperCaseProfilePathItem -isnot [IO.DirectoryInfo]) { + #This would be a very rare occurance + Write-Warning "A non-directory item was detected at $legacyUpperCaseProfilePathItem. You should remove this or otherwise transition it to $standardProfilePath" + return + } + if ($legacyUpperCaseProfilePathItem.LinkType -eq 'SymbolicLink') { + if ((Resolve-Path $legacyUpperCaseProfilePathItem.Target -ne $standardProfilePath)) { + Write-Warning "A symbolic link was detected for the legacy profile folder $legacyUpperCaseProfilePathItem, but it points to $($legacyUpperCaseProfilePathItem.Target). You should remove this or otherwise transition it to $standardProfilePath" + return + } else { + #A migration has already completed + return + } + } + + if (Test-Path $standardProfilePath) { + Write-Warning "$legacyUpperCaseProfilePathItem requires migration but a standard profile folder was already detected at $standardProfilePath. If you have completed migration manually, please remove $legacyUpperCaseProfilePathItem and any references to it." + return + } + + #Prerequisites for migration have been met at this point. + Write-Warning "We have detected a legacy profile folder at $legacyUpperCaseProfilePathItem. We are moving this to the standard profile folder $standardProfilePath for you and will link the old location to maintain compatibility." + + if ($PSCmdlet.ShouldProcess("Migrate profile folder from $legacyUpperCaseProfilePathItem to $standardProfilePath")) { + Move-Item -Path $legacyUpperCaseProfilePathItem -Destination $standardProfilePath + } + if ($PSCmdlet.ShouldProcess("Create symbolic link from $legacyUpperCaseProfilePathItem to $standardProfilePath to maintain compatibility")) { + New-Item -ItemType SymbolicLink -Path $legacyUpperCaseProfilePath -Value $standardProfilePath + } +} + + # Helper to do telemetry logging. function Invoke-CloudShellTelemetry { @@ -110,14 +155,14 @@ function Get-SubscriptionIdFromStorageProfile function Connect-AzService { param ( - + [string]$currentSubscriptionId ) # Enable Az Data collection # Else User is prompted when Connect-AzAccount is invoked Set-PSCloudShellTelemetry - + $startTime = [System.DateTime]::Now try @@ -177,7 +222,7 @@ function Connect-AzureAD $startTime = [System.DateTime]::Now try - { + { $envName = $env:ACC_CLOUD if ($CloudEnvironmentMap.ContainsKey($env:ACC_CLOUD)) { @@ -189,7 +234,7 @@ function Connect-AzureAD # This call sets the local process context with the token, account and tenant information & $script:AzureADModuleName\Connect-AzureAD @azureADParameters -ErrorAction SilentlyContinue -ErrorVariable azureADError | Microsoft.PowerShell.Core\Out-Null - + # Log any errors from AzureAD authentication if ($azureADError) { @@ -331,7 +376,7 @@ if($script:SkipMSIAuth -eq $true) { Microsoft.PowerShell.Utility\Write-Debug -Message "Skip authenticating with MSI, instead test scripts will take care of Auth." } -else +else { Microsoft.PowerShell.Utility\Write-Debug -Message "Authenticating with MSI ..." @@ -362,9 +407,9 @@ else # Import AzureAD module so cmdlets are visible, they are not currently being auto-discovered $azureADLoadStartTime = [System.DateTime]::Now -try +try { - Microsoft.PowerShell.Core\Import-Module -Name $script:AzureADModuleName + Microsoft.PowerShell.Core\Import-Module -Name $script:AzureADModuleName } finally {