Convert-REAzureRmToAz.ps1


<#PSScriptInfo
 
.VERSION 1.1.1
 
.GUID c0c725c3-36be-4fe7-b526-88c549e3f47a
 
.AUTHOR Karl Wallenius, Tobias Keitsch
 
.COMPANYNAME Redeploy AB
 
.COPYRIGHT (c) 2018 Redeploy AB. All rights reserved.
 
.TAGS Azure AzureRm Az Convert Update
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
* 1.0.0
    * Initial version.
* 1.0.1
    * Fixed matching so that *-Azure, as in *-AzureStorage is matched and replaced.
* 1.1.0
    * Handles Import-Module AzureRm to Az, and using module AzureRm to Az.
    * Renamed internal function to FindReplaceLine.
    * Checks if object is a directory or a file, skips if it's a directory.
    * Handles multiple calls in same line.
* 1.1.1
    * Added additional Verbs from AzureRM module that
    * Added Case Insensitive matching
    * Adjusted *-Azure* match to only match *-AzureStorage* to avoid breaking old code.
    * Added *-Azure* matching to include *-AzureKeyVault*
    * Added Get-Module, Find-Module, Get-InstalledModule to matches.
 
.PRIVATEDATA
 
#>


<#
 
.DESCRIPTION
 Script to convert *-AzureRm*-cmdlets to *-Az*-cmdlets. Dot source the script: . <path-to-script>\Convert-REAzureRmToAz.ps1 to get access to the function 'Convert-REAzureRmToAz'.
 
#>
 

<#
.SYNOPSIS
Takes provded System.IO.FileInfo object(s) or path(s) to a PowerShell script file and
converts "-AzureRm" to "-Az" in function/cmdlet calls.
 
.DESCRIPTION
Takes provded System.IO.FileInfo object(s) or path(s) to a PowerShell script file and
converts "-AzureRm" to "-Az" in function/cmdlet calls.
 
The function will only convert commands that are structured in the PowerShell Verb-Noun
syntax. It will replace the content of the specified file if not -OutputPath is used.
 
.PARAMETER InputObject
A System.IO.FileInfo object, or path to a file.
 
.PARAMETER OutputPath
Output directory of the resulting file (Optional). If used a resulting file with the same name as
the input file will be placed in this path.
 
.EXAMPLE
To replace "-AzureRm" from cmdlet/function calls in provided scripts:
 
# Assuming Path contains a couple of scripts:
$files = Get-ChildItem -Path C:\Scripts
Convert-REAzureRmToAZ -InputObject $files
 
.EXAMPLE
To replace "-AzureRm" from cmdlet/function calls in provided scripts and create new files in specified directory:
 
# Assuming Path contains a couple of scripts:
$files = Get-ChildItem -Path C:\Scripts
Convert-REAzureRmToAz -InputObject $files -OutputPath C:\Scripts2
 
.EXAMPLE
To replace "-AzureRm" from cmdlet/function calls in provided scripts:
 
# Assuming Path contains a couple of scripts:
$files = Get-ChildItem -Path C:\Scripts
$files | Convert-REAzureRmToAz
 
.EXAMPLE
To replace "-AzureRm" from cmdlet/function calls in script C:\Scripts\somescript.ps1 (if it contains such calls):
 
Convert-REAzureRmToAz -InputObject C:\Scripts\somescript.ps1
 
.EXAMPLE
To replace "-AzureRm" from cmdlet/function calls in script C:\Scripts\somescript.ps1 and C:\Scripts\somescript2.ps1 (if they contains such calls):
 
Convert-REAzureRmToAz -InputObject C:\Scripts\somescript.ps1,C:\Scripts\somescript2.ps1
 
.NOTES
Written by Karl Wallenius, Redeploy AB.
Contibutions by Tobias Keitsch, Redeploy AB.
#>

function Convert-REAzureRmToAz {
    [CmdletBinding()]
    [OutputType([PSCustomObject])]
    param(
        [Parameter(
            Mandatory = $true,
            Position = 0,
            ValueFromPipeline = $true, 
            ValueFromPipelineByPropertyName = $true)]
        [ValidateNotNull()]
        [ValidateNotNullOrEmpty()]
        [Object[]]
        $InputObject,
        [Parameter(
            Mandatory = $false,
            Position = 1)]
        [AllowNull()]
        [AllowEmptyString()]
        [String]
        $OutputPath
    )

    Begin {
        function FindReplaceLine {
            param($Line, $Verbs)
        
            $modified = $false
            $newLine = $Line

            if ($newLine -match "Import-Module|using module|Get-Module|Get-InstalledModule|Find-Module|Install-Module") {
                $newLine = $line -replace "AzureRm|Azure", "Az"
                $modified = $true
            } else {
                $pattern = "(?i)(" + ($verbs -join "|") + ")(\-AzureRm|\-AzureStorage|\-AzureKeyVault)"
                $match = [Regex]::Matches($Line, $pattern)

                foreach ($m in $match) {
                    $verb = $m.Groups[1].Value
                    if ($verb -in $Verbs) {
                        if($m.Groups[2].Value -like '*AzureStorage*'){
                            $newLine = $newLine -replace "$verb\-(AzureStorage)", "$verb-AzStorage"
                            $modified = $true  
                        }elseif($m.Groups[2].Value -like '*AzureKeyVault*'){
                            $newLine = $newLine -replace "$verb\-(AzureKeyVault)", "$verb-AzureKeyVault"
                            $modified = $true  
                        }else{
                            $newLine = $newLine -replace "$verb\-(AzureRm)", "$verb-Az"
                            $modified = $true                     
                        }
                    }
                }
            }

            $modified
            $newLine
        }

        $oPath = $null

        if (!([string]::IsNullOrEmpty($OutputPath))) {

            if (!(Test-Path -Path $OutputPath)) {
                [void](New-Item -ItemType Directory -Path $OutputPath)
            }

            $oPath = (Resolve-Path -Path $OutputPath).Path

            if (!(Test-Path -Path $oPath)) {
                [void](New-Item -ItemType Directory -Path $oPath)
            }
        }

        $verbs = (Get-Verb).Verb
        $additionalVerbs = @("List", "Login", "Logout", "Reactivate", "Swap", "Validate")
        $verbs += $additionalVerbs
        
        $resultObject = [PSCustomObject]@{
            Files = [System.Collections.ArrayList]::new()
            ModifiedFiles = [System.Collections.ArrayList]::new()
            SkippedFiles = [System.Collections.ArrayList]::new()
        }
    }

    Process {
        foreach ($object in $InputObject) {
            
            if ($object.GetType().Name -eq "String") {
                $object = Get-Item -Path (Resolve-Path -Path $object).Path
            }

            [void]($resultObject.Files.Add($object.FullName))

            # Skip if it's a directory.
            if (!($object -is [System.IO.DirectoryInfo])) {
                $content = Get-Content -Path $object.FullName
            
                $modded = [System.Collections.ArrayList]::new()
    
                $newContent = $content | ForEach-Object {
                    $mod, $line = FindReplaceLine -Line $_ -Verbs $verbs
                    [void]($modded.Add($mod))
                    $line
                }
    
                if ($true -in $modded) {
                    if ($null -ne $oPath) {
                        $newContent | Out-File -Path (Join-Path -Path $oPath -ChildPath $object.Name)
                    } else {
                        $newContent | Set-Content -Path $($object.FullName)
                    }
                    [void]($resultObject.ModifiedFiles.Add($object.FullName))
                } else {
                    [void]($resultObject.SkippedFiles.Add($object.FullName))
                }
            }
        }
    }

    End {
        $resultObject
    }
}