Liquibase - Run command

Octopus.Script exported 2024-07-23 by twerthi belongs to ‘Liquibase’ category.

Run Liqbuibase commands against a database. You can include Liquibase in the package itself or choose Download to download it during runtime.

Note:

  • AWS EC2 IAM Authentication requires the AWS CLI to be installed.
  • Windows Authentication has been tested with
    • Microsoft SQL Server
    • PostgreSQL

Once the Liquibase commands have executed, the output is stored in an Octopus output variable called LiquibaseCommandOutput for use in subsequent Octopus deployment or runbook steps.

Parameters

When steps based on the template are included in a project’s deployment process, the parameters below can be set.

Pro license key

liquibaseProLicenseKey =

Enter your Liquibase Pro license key. Request a free 30-day trial. Leave blank to use the Community Edition.

Database type

liquibaseDatabaseType =

Select the database type to deploy to.

Command

liquibaseCommand =

Use the drop down to select the command to execute. Commands with * have partial functionality with Community edition, full functionality with Pro edition.

Commands with ** are Pro only (all Pro only commands require the use of Additional switches).

Commands with *** require Additiona switches.

All commands that end in SQL will automatically add the --outputFile switch and include the generated output as an artifact.

Command style

liquibaseCommandStyle = modern

Select the style of command, Legacy or Modern. Legacy will place the Liquibase command at the end of the call, Modern will place it at the beginning

Legacy: liquibase --switch1 command

Modern: liquibase command --switch1

Command Arguments

liquibaseCommandArguments =

Some commands require additional arguments, e.g. , status --verbose, rollbackOneUpdate --force

Additional switches

liquibaseAdditionalSwitches =

A list of additional switches to include for the command, one per line. (I.e. --logLevel=debug)

Change Log file name

liquibaseChangeLogFileName =

Name of the changelog file in the package.

Changeset package

liquibaseChangeset =

Select the package with the changeset.

Server name

liquibaseServerName =

Name or IP address of the database server.

Server port

liquibaseServerPort =

The port the database server listens on.

Authentication Method

liquibaseAuthenticationMethod = usernamepassword

Method used to authenticate to the database server.

Database name

liquibaseDatabaseName =

Name of the database to deploy to.

  • Service name for Oracle
  • KeySpace for Cassandra

Username

liquibaseUsername =

Username of a user that has permission to make changes to the database.

Password

liquibasePassword =

Password for the user with permissions to make changes to the database.

Connection query string parameters

liquibaseQueryStringParameters =

Add additional parameters to the connection string URL. Example: ?useUnicode=true or ;AuthMech=1

Database driver path

liquibaseClassPath =

Filepath to the location of the .jar driver for the database type.

Executable file path

liquibaseExecutablePath =

File path to the Liquibase executable.

Download Liquibase?

liquibaseDownload =

Use this option to download the software necessary to deploy a Liquibase changeset. This will download Liquibase, java, and the appropriate driver for the selected database type. Using this option overrides the Database driver path and Executable file path inputs.

Liquibase version

liquibaseVersion =

Used with Download Liquibase to specify the version of Liquibase to use.

Script body

Steps based on this template will execute the following PowerShell script.

# Configure template

# Check to see if $IsWindows is available
if ($null -eq $IsWindows) {
    Write-Host "Determining Operating System..."
    $IsWindows = ([System.Environment]::OSVersion.Platform -eq "Win32NT")
    $IsLinux = ([System.Environment]::OSVersion.Platform -eq "Unix")
}

# Fix ANSI Color on PWSH Core issues when displaying objects
if ($PSEdition -eq "Core") {
    $PSStyle.OutputRendering = "PlainText"
}

# Set TLS
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls11 -bor [System.Net.SecurityProtocolType]::Tls12

# Downloads and extracts liquibase to the work folder
Function Get-Liquibase {
    # Define parameters
    param ($Version) 

    $repositoryName = "liquibase/liquibase"

    # Check to see if version wasn't specified
    if ([string]::IsNullOrEmpty($Version)) {
        # Get the latest version download url
        $downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName | Where-Object { $_.EndsWith(".zip") })
    }
    else {
        $downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName -Version $Version | Where-Object { $_.EndsWith(".zip") })
    }

    # Extract the downloaded file
    Expand-DownloadedFile -DownloadUrls $downloadUrl | Out-Null
    
    # Parse downloaded version
    if ($downloadUrl -is [array]) {
        $downloadedFileName = [System.IO.Path]::GetFileName($downloadUrl[0])
    }
    else {
        $downloadedFileName = [System.IO.Path]::GetFileName($downloadUrl)
    }

    # Return the downloaded version
    return $downloadedFileName.SubString($downloadedFileName.IndexOf("-") + 1).Replace(".zip", "")    
}

# Downloads the files
Function Expand-DownloadedFile {
    # Define parameters
    param (
        $DownloadUrls
    )
    
    # Loop through results
    foreach ($url in $DownloadUrls) {
        # Download the zip file
        $folderName = [System.IO.Path]::GetFileName("$PSScriptroot/$($url.Substring($url.LastIndexOf("/")))").Replace(".zip", "")
        $zipFile = "$PSScriptroot/$folderName/$($url.Substring($url.LastIndexOf("/")))"
        Write-Host "Downloading $zipFile from $url ..."
        
        if ((Test-Path -Path "$PSScriptroot/$folderName") -eq $false) {
            # Create folder
            New-Item -Path "$PSScriptroot/$folderName/" -ItemType Directory
        }

        # Download the zip file
        Invoke-WebRequest -Uri $url -OutFile $zipFile -UseBasicParsing | Out-Null

        # Extract package
        Write-Host "Extracting $zipFile ..."
        Expand-Archive -Path $zipFile -DestinationPath "$PSSCriptRoot/$folderName" | Out-Null
    }
}


# Downloads and extracts Java to the work folder, then adds the location of java.exe to the $env:PATH variabble so it can be called
Function Get-Java {
    # Check to see if a folder needs to be created
    if ((Test-Path -Path "$PSScriptRoot/jdk") -eq $false) {
        # Create new folder
        New-Item -ItemType Directory -Path "$PSSCriptRoot/jdk"
    }

    # Download java
    Write-Output "Downloading Java ... "
    
    # Determine OS
    if ($IsWindows) {
        Invoke-WebRequest -Uri "https://download.java.net/java/GA/jdk14.0.2/205943a0976c4ed48cb16f1043c5c647/12/GPL/openjdk-14.0.2_windows-x64_bin.zip" -OutFile "$PSScriptroot/jdk/openjdk-14.0.2_windows-x64_bin.zip" -UseBasicParsing

        # Extract
        Write-Output "Extracting Java ... "
        Expand-Archive -Path "$PSScriptroot\jdk\openjdk-14.0.2_windows-x64_bin.zip" -DestinationPath "$PSSCriptRoot/jdk"

        # Get Java executable
        $javaExecutable = Get-ChildItem -Path "$PSScriptRoot\jdk" -Recurse | Where-Object { $_.Name -eq "java.exe" }
    }
    
    if ($IsLinux) {
        Invoke-WebRequest -Uri "https://download.java.net/openjdk/jdk14/ri/openjdk-14+36_linux-x64_bin.tar.gz" -OutFile "$PSScriptroot/jdk/openjdk-14+36_linux-x64_bin.tar.gz" -UseBasicParsing

        # Extract
        Write-Output "Extracting Java ... "
        tar -xvzf "$PSScriptroot/jdk/openjdk-14+36_linux-x64_bin.tar.gz" --directory "$PSScriptRoot/jdk"

        # Get Java executable
        $javaExecutable = Get-ChildItem -Path "$PSScriptRoot/jdk" -Recurse | Where-Object { $_.Name -eq "java" }   
    }
    
    # Add path to current session as first entry to bypass other versions of Java that may be installed.
    $env:PATH = "$($javaExecutable.Directory)$([IO.Path]::PathSeparator)" + $env:PATH
    
}

Function Get-DriverAssets {
    # Define parameters
    param (
        $DownloadInfo
    )

    # Declare working variables
    $assetFilePath = ""

    # Check to see if there are multiple assets to download
    if ($DownloadInfo -is [array]) {
        # Declare local variables
        $assetFiles = @()

        # Loop through array
        foreach ($url in $DownloadInfo) {
            # Download the asset
            Write-Host "Downloading asset from $url..."
            $assetPath = "$PSScriptroot/$($url.Substring($url.LastIndexOf("/")))"
            
            # Skip test assets
            if ($assetPath.EndsWith("tests.jar")) {
                Write-Host "Asset is for testing, skipping ..."
                continue
            }
            
            Invoke-WebRequest -Uri $url -Outfile $assetPath -UseBasicParsing
            $assetFiles += $assetPath
        }

        # Assign paths
        $assetFilePath = $assetFiles -join "$([IO.Path]::PathSeparator)"
    }
    else {
        # Download asset
        Write-Host "Downloading asset from $DownloadInfo ..."
        $assetFilePath = "$PSScriptroot/$($DownloadInfo.Substring($DownloadInfo.LastIndexOf("/")))"
        Invoke-WebRequest -Uri $DownloadInfo -Outfile $assetFilePath -UseBasicParsing
    }

    # Return path
    return $assetFilePath
}

# Gets download url of latest release with an asset
Function Get-LatestVersionDownloadUrl {
    # Define parameters
    param(
        $Repository,
        $Version
    )
    
    # Define local variables
    $releases = "https://api.github.com/repos/$Repository/releases"
    
    # Get latest version
    Write-Host "Determining latest release of $Repository ..."
    
    $tags = (Invoke-WebRequest $releases -UseBasicParsing | ConvertFrom-Json)
    
    if ($null -ne $Version) {
        # Get specific version
        $tags = ($tags | Where-Object { $_.name.EndsWith($Version) })

        # Check to see if nothing was returned
        if ($null -eq $tags) {
            # Not found
            Write-Host "No release found matching version $Version, getting highest version using Major.Minor syntax..."

            # Get the tags
            $tags = (Invoke-WebRequest $releases -UseBasicParsing | ConvertFrom-Json)

            # Parse the version number into a version object
            $parsedVersion = [System.Version]::Parse($Version)
            $partialVersion = "$($parsedVersion.Major).$($parsedVersion.Minor)"
            
            # Filter tags to ones matching only Major.Minor of version specified
            $tags = ($tags | Where-Object { $_.name.Contains("$partialVersion.") -and $_.draft -eq $false })
            
            # Grab the latest
            if ($null -eq $tags)
            {
            	# decrement minor version
                $minorVersion = [int]$parsedVersion.Minor
                $minorVersion --
                
                # return the urls
                return (Get-LatestVersionDownloadUrl -Repository $Repository -Version "$($parsedVersion.Major).$($minorVersion)")
            }
        }
    }

    # Find the latest version with a downloadable asset
    foreach ($tag in $tags) {
        if ($tag.assets.Count -gt 0) {
            return $tag.assets.browser_download_url
        }
    }

    # Return the version
    return $null
}

# Finds the specified changelog file
Function Get-ChangeLog {
    # Define parameters
    param ($FileName)
    
    # Find file
    $fileReference = (Get-ChildItem -Path $OctopusParameters["Octopus.Action.Package[liquibaseChangeSet].ExtractedPath"] -Recurse | Where-Object { $_.Name -eq $FileName })

    # Check to see if something weas returned
    if ($null -eq $fileReference) {
        # Not found
        Write-Error "$FileName was not found in $PSScriptRoot or subfolders."
    }

    # Return the reference
    return $fileReference
}

# Downloads the appropriate JDBC driver
Function Get-DatabaseJar {
    # Define parameters
    param ($DatabaseType)

    # Declare local variables
    $driverPath = ""

    # Check to see if a folder needs to be created
    if ((Test-Path -Path "$PSScriptRoot/DatabaseDriver") -eq $false) {
        # Create new folder
        New-Item -ItemType Directory -Path "$PSSCriptRoot/DatabaseDriver" | Out-Null
    }

    # Download the driver for the selected type
    switch ($DatabaseType) {
        "Cassandra" {

			# Get the release download
            Write-Host "Downloading Cassandra JDBC driver bundle ..."
			$downloadUrl = Get-LatestVersionDownloadUrl -Repository "ing-bank/cassandra-jdbc-wrapper"
           
            # Find driver
            $driverPath = (Get-DriverAssets -DownloadInfo $downloadUrl)

            # Set repo name
            $repositoryName = "liquibase/liquibase-cassandra"
            
            if ([string]::IsNullOrEmpty($liquibaseVersion)) {
                # Get the latest version for the extension
                $downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName | Where-Object { $_.EndsWith(".jar") })
           	}
            else {
                # Download version matching extension
                $downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName -Version $liquibaseVersion | Where-Object { $_.EndsWith(".jar") })
            }           

            $extensionPath = Get-DriverAssets -DownloadInfo $downloadUrl
            
            # Make driver path null
            $driverPath = "$driverPath$([IO.Path]::PathSeparator)$extensionPath"

            break
        }
        "CosmosDB"
        {
			# Download the (long) list of dependencies
            $driverPaths = @()

			# Set repo name
            $repositoryName = "liquibase/liquibase-cosmosdb"

			if ([string]::IsNullOrEmpty($liquibaseVersion))
            {
            	# Get the latest version for the extension
            	$downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName | Where-Object {$_.EndsWith(".jar")})
           	}
            else
            {
            	# Download version matching extension
                $downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName -Version $liquibaseVersion | Where-Object {$_.EndsWith(".jar")})
            }    
            
            $extensionPath = Get-DriverAssets -DownloadInfo $downloadUrl
                     
			# Add to driver path
            $driverPaths += $extensionPath
            
            Write-Host "Downloading azure-cosmos driver ..."
            $driverVersion = "4.28.0"
            $filePath = "$PSScriptroot/DatabaseDriver/azure-cosmos-$driverVersion.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/com/azure/azure-cosmos/$driverVersion/azure-cosmos-$driverVersion.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            
            # Add to driver path
            $driverPaths += $filePath
            
            Write-Host "Downloading azure-core driver ..."
            $driverVersion = "1.27.0"
            $filePath = "$PSScriptroot/DatabaseDriver/azure-core-$driverVersion.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/com/azure/azure-core/$driverVersion/azure-core-$driverVersion.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            $files = Get-ChildItem -Path "$PSScriptRoot/DatabaseDriver"
            
            Write-Host "There are these $files"


            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading jackson core driver ..."
            $driverVersion = "2.13.2"
            $filePath = "$PSScriptroot/DatabaseDriver/jackson-core-$driverVersion.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/$driverVersion/jackson-core-$driverVersion.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            
            
            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading slf4j core driver ..."
            $driverVersion = "1.7.36"
            $filePath = "$PSScriptroot/DatabaseDriver/slf4j-api-$driverVersion.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/org/slf4j/slf4j-api/$driverVersion/slf4j-api-$driverVersion.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            
            
            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty buffer driver ..."
            $driverVersion = "4.1.75"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-buffer-$driverVersion.final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-buffer/$driverVersion.Final/netty-buffer-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            
            
            # Add to driver path
            $driverPaths += $filePath
			
            Write-Host "Downloading reactor-core driver ..."
            $driverVersion = "3.4.16"
            $filePath = "$PSScriptroot/DatabaseDriver/reactor-core-$driverVersion.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/projectreactor/reactor-core/$driverVersion/reactor-core-$driverVersion.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            
            
            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading reactor-netty-core driver ..."
            $driverVersion = "1.0.17"
            $filePath = "$PSScriptroot/DatabaseDriver/reactor-core-$driverVersion.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/projectreactor/netty/reactor-netty-core/$driverVersion/reactor-netty-core-$driverVersion.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            
            
            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading reactor-netty-core driver ..."
            $driverVersion = "1.0.17"
            $filePath = "$PSScriptroot/DatabaseDriver/reactor-netty-http-$driverVersion.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/projectreactor/netty/reactor-netty-http/$driverVersion/reactor-netty-http-$driverVersion.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            
            
            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty-resolver driver ..."
            $driverVersion = "4.1.75"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-resolver-$driverVersion.Final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-resolver/$driverVersion.Final/netty-resolver-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing  | Out-Null
            
            
            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty-transport driver ..."
            $driverVersion = "4.1.75"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-transport-$driverVersion.Final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-transport/$driverVersion.Final/netty-transport-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing  | Out-Null
            
            
            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading reactivestreams driver ..."
            $driverVersion = "1.0.3"
            $filePath = "$PSScriptroot/DatabaseDriver/reactive-streams-$driverVersion.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/org/reactivestreams/reactive-streams/$driverVersion/reactive-streams-$driverVersion.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading jackson-databind driver ..."
            $driverVersion = "2.13.2.1"
            $filePath = "$PSScriptroot/DatabaseDriver/jackson-databind-$driverVersion.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/$driverVersion/jackson-databind-$driverVersion.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading jackson-annotations driver ..."
            $driverVersion = "2.13.2"
            $filePath = "$PSScriptroot/DatabaseDriver/jackson-annotations-$driverVersion.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/$driverVersion/jackson-annotations-$driverVersion.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath
            
            Write-Host "Downloading jackson-module-afterburner driver ..."
            $driverVersion = "2.13.2"
            $filePath = "$PSScriptroot/DatabaseDriver/jackson-module-afterburner-$driverVersion.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/com/fasterxml/jackson/module/jackson-module-afterburner/$driverVersion/jackson-module-afterburner-$driverVersion.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading reactor-netty driver ..."
            $driverVersion = "1.0.17"
            $filePath = "$PSScriptroot/DatabaseDriver/reactor-netty-$driverVersion.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/projectreactor/netty/reactor-netty/$driverVersion/reactor-netty-$driverVersion.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty-transport-native-unix-common driver ..."
            $driverVersion = "4.1.75"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-transport-native-unix-common-$driverVersion.Final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-transport-native-unix-common/$driverVersion.Final/netty-transport-native-unix-common-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty-transport-native-epoll driver ..."
            $driverVersion = "4.1.75"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-transport-native-epoll-$driverVersion.Final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-transport-native-epoll/$driverVersion.Final/netty-transport-native-epoll-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty-tcnative-boringssl-static driver ..."
            $driverVersion = "2.0.51"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-tcnative-boringssl-static-$driverVersion.Final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-tcnative-boringssl-static/$driverVersion.Final/netty-tcnative-boringssl-static-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty-resolver-dns driver ..."
            $driverVersion = "4.1.75"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-resolver-dns-$driverVersion.Final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-resolver-dns/$driverVersion.Final/netty-resolver-dns-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty-handler-proxy driver ..."
            $driverVersion = "4.1.75"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-handler-proxy-$driverVersion.Final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-handler-proxy/$driverVersion.Final/netty-handler-proxy-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty-handler driver ..."
            $driverVersion = "4.1.75"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-handler-$driverVersion.Final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-handler/$driverVersion.Final/netty-handler-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty-common driver ..."
            $driverVersion = "4.1.75"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-common-$driverVersion.Final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-common/$driverVersion.Final/netty-common-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty-codec-socks driver ..."
            $driverVersion = "4.1.75"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-codec-socks-$driverVersion.Final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-codec-socks/$driverVersion.Final/netty-codec-socks-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty-codec-http driver ..."
            $driverVersion = "4.1.75"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-codec-http-$driverVersion.Final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-codec-http/$driverVersion.Final/netty-codec-http-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty-codec-http2 driver ..."
            $driverVersion = "4.1.75"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-codec-http2-$driverVersion.Final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-codec-http2/$driverVersion.Final/netty-codec-http2-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty-codec-dns driver ..."
            $driverVersion = "4.1.75"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-codec-dns-$driverVersion.Final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-codec-dns/$driverVersion.Final/netty-codec-dns-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty-codec driver ..."
            $driverVersion = "4.1.75"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-codec-$driverVersion.Final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-codec/$driverVersion.Final/netty-codec-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading micrometer-core driver ..."
            $driverVersion = "1.8.4"
            $filePath = "$PSScriptroot/DatabaseDriver/micrometer-core-$driverVersion.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/micrometer/micrometer-core/$driverVersion/micrometer-core-$driverVersion.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading metrics-core driver ..."
            $driverVersion = "4.2.9"
            $filePath = "$PSScriptroot/DatabaseDriver/metrics-core-$driverVersion.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/dropwizard/metrics/metrics-core/$driverVersion/metrics-core-$driverVersion.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading LatencyUtils driver ..."
            $driverVersion = "2.0.3"
            $filePath = "$PSScriptroot/DatabaseDriver/LatencyUtils-$driverVersion.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/org/latencyutils/LatencyUtils/$driverVersion/LatencyUtils-$driverVersion.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading jackson-datatype-jsr310 driver ..."
            $driverVersion = "2.12.5"
            $filePath = "$PSScriptroot/DatabaseDriver/jackson-datatype-jsr310-$driverVersion.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/$driverVersion/jackson-datatype-jsr310-$driverVersion.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty-tcnative-classes driver ..."
            $driverVersion = "2.0.51"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-tcnative-classes-$driverVersion.Final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-tcnative-classes/$driverVersion.Final/netty-tcnative-classes-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty-transport-classes-kqueue driver ..."
            $driverVersion = "4.1.73"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-transport-classes-kqueue-$driverVersion.Final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-transport-classes-kqueue/$driverVersion.Final/netty-transport-classes-kqueue-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading slf4j-simple driver ..."
            $driverVersion = "1.7.36"
            $filePath = "$PSScriptroot/DatabaseDriver/slf4j-simple-$driverVersion.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/org/slf4j/slf4j-simple/$driverVersion/slf4j-simple-$driverVersion.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty-transport-classes-epoll driver ..."
            $driverVersion = "4.1.75"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-transport-classes-epoll-$driverVersion.Final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-transport-classes-epoll/$driverVersion.Final/netty-transport-classes-epoll-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

            Write-Host "Downloading netty-transport-native-kqueue driver ..."
            $driverVersion = "4.1.75"
            $filePath = "$PSScriptroot/DatabaseDriver/netty-transport-native-kqueue-$driverVersion.Final.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/io/netty/netty-transport-native-kqueue/$driverVersion.Final/netty-transport-native-kqueue-$driverVersion.Final.jar" -Outfile $filePath -UseBasicParsing | Out-Null
            

            # Add to driver path
            $driverPaths += $filePath

			# Return driver list separated by system specific PathSeparator
            $driverPath = ($driverPaths -join [IO.Path]::PathSeparator)
            
            $files = Get-ChildItem -Path "$PSScriptRoot/DatabaseDriver"
            
            #Write-Host "There are these $files"
            
       		break
        }        
        "DB2" {
            # Use built-in driver
            $driverPath = $null
            break
        }
        "MariaDB" {
            # Download MariaDB driver
            Write-Host "Downloading MariaDB driver ..."
            $driverPath = "$PSScriptroot/DatabaseDriver/mariadb-java-client-2.6.2.jar"
            Invoke-WebRequest -Uri "https://downloads.mariadb.com/Connectors/java/connector-java-2.6.2/mariadb-java-client-2.6.2.jar" -OutFile $driverPath -UseBasicParsing
             
            break
        }
        "MongoDB" {
            # Download MongoDB driver
            Write-Host "Downloading Maven MongoDB driver ..."
            $driverPath = "$PSScriptroot/DatabaseDriver/mongo-java-driver-3.12.7.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/org/mongodb/mongo-java-driver/3.12.7/mongo-java-driver-3.12.7.jar" -Outfile $driverPath -UseBasicParsing
            
            # Check to see if they are using a licenced version
            if (![string]::IsNullOrWhitespace($liquibaseProLicenseKey)) {
                # Set the paid version url
                $mongoVersions = Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/org/liquibase/ext/liquibase-commercial-mongodb" -UseBasicParsing
                
                # Loop through links, look for ones that evaluate to version
                $versions = @()
                foreach ($link in $mongoVersions.Links) {
                    Write-Verbose "Evaluating: $link"
                    if (![string]::IsNullOrWhitespace($link.title)) {
                        # Get the inner text
                        $versionNumber = $link.title.Replace("/", "")

                        # Check to see if $versionNumber can be parsed as a versionNumber
                        $versionOut = $null
                        if ([System.Version]::TryParse($versionNumber, [ref]$versionOut)) {
                            $versions += $versionOut
                        }
                    }
                }

                # Get the highest version number
                $info = ($versions | Measure-Object -Maximum)

                $downloadUrl = "https://repo1.maven.org/maven2/org/liquibase/ext/liquibase-commercial-mongodb/$($info.Maximum)/liquibase-commercial-mongodb-$($info.Maximum).jar"                
            }
            else {
                # Set repo name
                $repositoryName = "liquibase/liquibase-mongodb"            
                
                # Download latest OSS version
                $downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName | Where-Object { $_.EndsWith(".jar") })
            }
                        
            $extensionPath = Get-DriverAssets -DownloadInfo $downloadUrl
            
            # Make driver path null
            $driverPath = "$driverPath$([IO.Path]::PathSeparator)$extensionPath"
            
            break
        }
        "MySQL" {
            # Download MariaDB driver
            Write-Host "Downloading MySQL driver ..."
            Invoke-WebRequest -Uri "https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.28.zip" -OutFile "$PSScriptroot/DatabaseDriver/mysql-connector-java-8.0.28.zip" -UseBasicParsing -UserAgent "curl/7.8.3.1"

            # Extract package
            Write-Host "Extracting MySQL driver ..."
            Expand-Archive -Path "$PSScriptroot/DatabaseDriver/mysql-connector-java-8.0.28.zip" -DestinationPath "$PSSCriptRoot/DatabaseDriver"

            # Find driver
            $driverPath = (Get-ChildItem -Path "$PSScriptRoot/DatabaseDriver" -Recurse | Where-Object { $_.Name -eq "mysql-connector-java-8.0.28.jar" }).FullName

            break
        }
        "Oracle" {
            # Download Oracle driver
            Write-Host "Downloading Oracle driver ..."
            $driverPath = "$PSScriptroot/DatabaseDriver/ojdbc10.jar"
            Invoke-WebRequest -Uri "https://download.oracle.com/otn-pub/otn_software/jdbc/211/ojdbc11.jar" -OutFile $driverPath -UseBasicParsing

            break
        }
        "SqlServer" {
            # Download Microsoft driver
            Write-Host "Downloading Sql Server driver ..."
            Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/?linkid=2186163" -OutFile "$PSScriptroot/DatabaseDriver/sqljdbc_10.2.0.0_enu.zip" -UseBasicParsing

            # Extract package
            Write-Host "Extracting SqlServer driver ..."
            Expand-Archive -Path "$PSScriptroot/DatabaseDriver/sqljdbc_10.2.0.0_enu.zip" -DestinationPath "$PSSCriptRoot/DatabaseDriver"

            # Find driver
            $driverPath = (Get-ChildItem -Path "$PSSCriptRoot/DatabaseDriver" -Recurse | Where-Object { $_.Name -eq "mssql-jdbc-10.2.0.jre11.jar" }).FullName
            
            # Determine architecture
            if ([System.Environment]::Is64BitOperatingSystem) {
                # Locate auth dll
                $authDll = Get-ChildItem -Path "$PSScriptRoot/DatabaseDriver" -Recurse | Where-Object { $_.Name -eq "mssql-jdbc_auth-10.2.0.x64.dll" }
            }
            else {
                $authDll = Get-ChildItem -Path "$PSScriptRoot/DatabaseDriver" -Recurse | Where-Object { $_.Name -eq "mssql-jdbc_auth-10.2.0.x86.dll" }
            }
            
            # Add the dll to the path so it can find it.
            $env:PATH += "$([IO.Path]::PathSeparator)$($authDll.Directory)"
            
            break
        }
        "PostgreSQL" {
            # Download PostgreSQL driver
            Write-Host "Downloading PostgreSQL driver ..."
            $driverPath = "$PSScriptroot/DatabaseDriver/postgresql-42.2.12.jar"
            Invoke-WebRequest -Uri "https://jdbc.postgresql.org/download/postgresql-42.2.12.jar" -OutFile $driverPath -UseBasicParsing
            
            # Download the WAFFLE jna driver for Windows Authentication
            $repositoryName = "waffle/waffle"
            
            # Latest version of Waffle (2.3.0) doesn't seem to work, can't find sspi method, specify version 1.9.0
            $downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName -Version "1.9.0" | Where-Object { $_.EndsWith(".zip") })
            Expand-DownloadedFile -DownloadUrls $downloadUrl | Out-Null
            
            # Get all waffle jars
            $waffleFolder = (Get-ChildItem -Path "$PSScriptroot" -Recurse | Where-Object { $_.PSIsContainer -and $_.Name -like "Waffle*" })           
            $waffleJars = (Get-ChildItem -Path $waffleFolder.FullName -Recurse | Where-Object { $_.Extension -eq ".jar" })
            
            foreach ($jar in $waffleJars) {
                $driverPath += "$([IO.Path]::PathSeparator)$($jar.FullName)"
            }

            break
        }
        "Snowflake" {
            # Set repo name
            $repositoryName = "liquibase/liquibase-snowflake"

            # Download Snowflake driver
            Write-Host "Downloading Snowflake driver ..."
            $driverPath = "$PSScriptroot/DatabaseDriver/snowflake-jdbc-3.9.2.jar"
            Invoke-WebRequest -Uri "https://repo1.maven.org/maven2/net/snowflake/snowflake-jdbc/3.9.2/snowflake-jdbc-3.9.2.jar" -OutFile $driverPath -UseBasicParsing

            if ([string]::IsNullOrEmpty($liquibaseVersion)) {
                # Get the latest version for the extension
                $downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName | Where-Object { $_.EndsWith(".jar") })
           	}
            else {
                # Download version matching extension
                $downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName -Version $liquibaseVersion | Where-Object { $_.EndsWith(".jar") })
            }
                        
            $extensionPath = Get-DriverAssets -DownloadInfo $downloadUrl
            
            # Make driver path null
            $driverPath = "$driverPath$([IO.Path]::PathSeparator)$extensionPath"


            break
        }
        default {
            # Display error
            Write-Error "Unknown database type: $DatabaseType."
        }
    }

    # Return the driver location
    return $driverPath
}

# Returns the connection string formatted for the database type
Function Get-ConnectionUrl {
    # Define parameters
    param ($DatabaseType, 
        $ServerPort, 
        $ServerName, 
        $DatabaseName, 
        $QueryStringParameters)

    # Define local variables
    $connectionUrl = ""

    # Download the driver for the selected type
    switch ($DatabaseType) {
        "Cassandra" {
            #$connectionUrl = "jdbc:cassandra://{0}:{1};DefaultKeyspace={2}"
            $connectionUrl = "jdbc:cassandra://{0}:{1}/{2}"
            break
        }
        "CosmosDB"
        {
            $connectionUrl = "cosmosdb://{0}:$($liquibasePassword)@{0}:{1}/{2}" 
            break
        }        
        "DB2" {
            $connectionUrl = "jdbc:db2://{0}:{1}/{2}"
            break
        }
        "MariaDB" {
            $connectionUrl = "jdbc:mariadb://{0}:{1}/{2}"
            
            # Check for Windows Authentication type
            if ($liquibaseAuthenticationMethod -eq "windowsauthentication") {
                # Add querysting parameter
                $connectionUrl += "?integratedSecurity=true"
            }
            
            break
        }
        "MongoDB" {        
            $connectionUrl = "mongodb://{0}:{1}/{2}"            
            break
        }
        "MySQL" {
        
            $connectionUrl = "jdbc:mysql://{0}:{1}/{2}"
            
            # Check for Windows Authentication type
            if ($liquibaseAuthenticationMethod -eq "windowsauthentication") {
                # Add querysting parameter
                $connectionUrl += "?integratedSecurity=true"
            }
            
            break
        }
        "Oracle" {
            $connectionUrl = "jdbc:oracle:thin:@{0}:{1}/{2}"
            break
        }
        "SqlServer" {
            $connectionUrl = "jdbc:sqlserver://{0}:{1};database={2};"
            
            switch ($liquibaseAuthenticationMethod) {
                "azuremanagedidentity" {
                    # Add querystring parameter
                    $connectionUrl += "Authentication=ActiveDirectoryMSI;"
                    break
                }
                "windowsauthentication" {
                    # Add querysting parameter
                    $connectionUrl += "integratedSecurity=true;"
                	
                    break
                }
            }
            
            break
        }
        "PostgreSQL" {
            $connectionUrl = "jdbc:postgresql://{0}:{1}/{2}"
            
            # Check for Windows Authentication type
            if ($liquibaseAuthenticationMethod -eq "windowsauthentication") {
                # Add querysting parameter
                $connectionUrl += "?gsslib=sspi"
            }
            
            break
        }
        "Snowflake" {
            $connectionUrl = "jdbc:snowflake://{0}.snowflakecomputing.com?db={2}"
            break
        }
        default {
            # Display error
            Write-Error "Unkonwn database type: $DatabaseType."
        }
    }

    if (![string]::IsNullOrWhitespace($QueryStringParameters)) {       	
        if ($connectionUrl.Contains("?")) {
           	# Replace the ? with & in connection string parameters
            $QueryStringParameters = $QueryStringParameters.Replace("?", "&")
        }
        
        # Appen connecion string
        $connectionUrl += "$QueryStringParameters"
    }

    # Return the url
    return ($connectionUrl -f $ServerName, $ServerPort, $DatabaseName)
}

# Create array for arguments
$liquibaseArguments = @()

# Check to see if it's running on Windows
if ($IsWindows) {
    # Disable the progress bar so downloading files via Invoke-WebRequest are faster
    $ProgressPreference = 'SilentlyContinue'
}

# Check for license key
if (![string]::IsNullOrWhitespace($liquibaseProLicenseKey)) {
    # Add key to arguments
    $liquibaseArguments += "--liquibaseProLicenseKey=$liquibaseProLicenseKey"
}

# Find Change log
$changeLogFile = (Get-ChangeLog -FileName $liquibaseChangeLogFileName)
$liquibaseArguments += "--changeLogFile=$($changeLogFile.Name)"

# Set the location to where the file is
Set-Location -Path $changeLogFile.Directory

# Check to see if it needs to be downloaed to machine
if ($liquibaseDownload -eq $true) {
    # Download and extract liquibase - get the version for extensions that are version specific
    $liquibaseVersion = Get-Liquibase -Version $liquibaseVersion -DownloadFolder $workingFolder

    # Download and extract java and add it to PATH environment variable
    Get-Java

    # Get the driver
    $driverPath = Get-DatabaseJar -DatabaseType $liquibaseDatabaseType

    # Check to see if it's null
    if ($null -ne $driverPath) {
        # Create folder to hold jar files to override
        New-Item -Path "$PWD/liquibase_libs/" -ItemType Directory    

        # Copy contents into liquibase_libs folder
        $driverPaths = $driverPath.Split([IO.Path]::PathSeparator)

        foreach ($driver in $driverPaths) {
            # Copy the items
            $files = Get-ChildItem -Path $driver

            foreach ($file in $files) {
                Write-Host "Copying $($file.FullName) to $PWD/liquibase_libs/$($file.Name)"
                Copy-Item -Path $file.FullName -Destination "$PWD/liquibase_libs/$($file.Name)"
            }
        }
    }
}
else {
    if (![string]::IsNullOrEmpty($liquibaseClassPath)) {
        $liquibaseArguments += "--classpath=$liquibaseClassPath"
    }
}

# Check to see if liquibase path has been defined
if ([string]::IsNullOrWhitespace($liquibaseExecutablePath)) {

	if ($env:IsContainer)
    {
    	$liquibaseExecutablePath = "/"	
    }
    else
    {
    	# Assign root
    	$liquibaseExecutablePath = $PSSCriptRoot
    }
}

# Get the executable location
if ($IsWindows) {
    $liquibaseExecutable = Get-ChildItem -Path $liquibaseExecutablePath -Recurse | Where-Object { $_.Name -eq "liquibase.bat" }
}

if ($IsLinux) {
    $liquibaseExecutable = Get-ChildItem -Path $liquibaseExecutablePath -Recurse | Where-Object { $_.Name -eq "liquibase" }
}

# Add path to current session
$env:PATH += "$([IO.Path]::PathSeparator)$($liquibaseExecutable.Directory)"

# Check to make sure it was found
if ([string]::IsNullOrEmpty($liquibaseExecutable)) {
    # Could not find the executable
    Write-Error "Unable to find liquibase.bat in $PSScriptRoot or subfolders."
}

# Get connection Url
$connectionUrl = Get-ConnectionUrl -DatabaseType $liquibaseDatabaseType -ServerPort $liquibaseServerPort -ServerName $liquibaseServerName -DatabaseName $liquibaseDatabaseName -QueryStringParameters $liquibaseQueryStringParameters

# Add username
$liquibaseArguments += "--username=$liquibaseUsername"

# Determine authentication method
switch ($liquibaseAuthenticationMethod) {
    "azuremanagedidentity" {
        # SQL Server driver doesn't assign password
        if ($liquibaseDatabaseType -ne "SqlServer") {
            # Get login token
            Write-Host "Generating Azure Managed Identity token ..."
            $token = Invoke-RestMethod -Method GET -Uri "http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://ossrdbms-aad.database.windows.net" -Headers @{"MetaData" = "true" } -UseBasicParsing

            $liquibasePassword = $token.access_token
            $liquibaseArguments += "--password=`"$liquibasePassword`""
        }
    }
    "awsiam" {
        # Region is part of the RDS endpoint, extract
        $region = ($liquibaseServerName.Split("."))[2]

        Write-Host "Generating AWS IAM token ..."
        $liquibasePassword = (aws rds generate-db-auth-token --hostname $liquibaseServerName --region $region --port $liquibaseServerPort --username $liquibaseUsername)
        $liquibaseArguments += "--password=`"$liquibasePassword`""

        break
    }
    "gcpserviceaccount" {
        # Define header
        $header = @{ "Metadata-Flavor" = "Google" }

        # Retrieve service accounts
        $serviceAccounts = Invoke-RestMethod -Method Get -Uri "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/" -Headers $header -UseBasicParsing

        # Results returned in plain text format, get into array and remove empty entries
        $serviceAccounts = $serviceAccounts.Split([Environment]::NewLine, [StringSplitOptions]::RemoveEmptyEntries)

        # Retreive the specific service account assigned to the VM
        $serviceAccount = $serviceAccounts | Where-Object { $_.Contains("iam.gserviceaccount.com") }

        Write-Host "Generating GCP IAM token ..."
        # Retrieve token for account
        $token = Invoke-RestMethod -Method Get -Uri "http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/$serviceAccount/token" -Headers $header -UseBasicParsing
        
        $liquibasePassword = $token.access_token
        $liquibaseArguments += "--password=`"$liquibasePassword`""
    }
    "usernamepassword" {
        # Add password
        $liquibaseArguments += "--password=`"$liquibasePassword`""
        
        break
    }
}

# Add connection url
$liquibaseArguments += "--url=`"$connectionUrl`""

# Determine if the output variable needs to be set
if ($liquibaseCommand.EndsWith("SQL")) {
    # Add the output variable as the command name
    $liquibaseArguments += "--outputFile=`"$PSScriptRoot/artifacts/$($liquibaseCommand).sql`""
    
    # Create the folder
    if ((Test-Path -Path "$PSScriptRoot/artifacts") -eq $false) {
        New-Item -Path "$PSScriptRoot/artifacts" -ItemType "Directory"
    }
}


# Add the additional switches
foreach ($liquibaseSwitch in $liquibaseAdditionalSwitches) {
    $liquibaseArguments += $liquibaseSwitch
}

switch ($liquibaseCommandStyle) {
    "legacy" {
        # Add the command to execute
        $liquibaseArguments += $liquibaseCommand
    }
    "modern" {
        # Insert the command at the beginning
        $liquibaseArguments = @($liquibaseCommand) + $liquibaseArguments
    }
}

# Add command arguments
$liquibaseArguments += $liquibaseCommandArguments

# Display what's going to be run
if (![string]::IsNullOrWhitespace($liquibasePassword)) {
    $liquibaseDisplayArguments = $liquibaseArguments.PSObject.Copy()
    for ($i = 0; $i -lt $liquibaseDisplayArguments.Count; $i++) {
        if ($null -ne $liquibaseDisplayArguments[$i]) {
            if ($liquibaseDisplayArguments[$i].Contains($liquibasePassword)) {
                $liquibaseDisplayArguments[$i] = $liquibaseDisplayArguments[$i].Replace($liquibasePassword, "****")
            }
        }
    }
    
    Write-Host "Executing the following command: $($liquibaseExecutable.FullName) $liquibaseDisplayArguments"
}
else {
    Write-Host "Executing the following command: $($liquibaseExecutable.FullName) $liquibaseArguments"
}


# Check to see if it's running in a container (this variable is provided by the build of the container itself)
if ($env:IsContainer)
{
	# Download any additional drivers based on the database technology being deployed to
    $driverPath = Get-DatabaseJar -DatabaseType $liquibaseDatabaseType

    # Check to see if it's null
    if ($null -ne $driverPath) {
        # Create folder to hold jar files to override
        New-Item -Path "$PWD/liquibase_libs/" -ItemType Directory    

        # Copy contents into liquibase_libs folder
        $driverPaths = $driverPath.Split([IO.Path]::PathSeparator)

        foreach ($driver in $driverPaths) {
            # Copy the items
            $files = Get-ChildItem -Path $driver

            foreach ($file in $files) {
                Write-Host "Copying $($file.FullName) to $PWD/liquibase_libs/$($file.Name)"
                Copy-Item -Path $file.FullName -Destination "$PWD/liquibase_libs/$($file.Name)"
            }
        }
    }
}



# Declare variable to hold output from Tee-Object
$liquibaseCommandOutput;

# Redirection of stderr to stdout is done different on Windows versus Linux
if ($IsWindows) {
    $liquibaseArguments += "2>&1"
    # Execute Liquibase
    & $liquibaseExecutable.FullName $liquibaseArguments | Tee-Object -Variable liquibaseCommandOutput
}

if ($IsLinux) {
    # Execute Liquibase
    & $liquibaseExecutable.FullName $liquibaseArguments 2>&1 | Tee-Object -Variable liquibaseCommandOutput
}

Set-OctopusVariable -name "LiquibaseCommandOutput" -value $liquibaseCommandOutput

# Check exit code
if ($lastExitCode -ne 0) {
    # Fail the step
    Write-Error "Execution of Liquibase failed!"
}

# Check to see if there were any files output
if ((Test-Path -Path "$PSScriptRoot/artifacts") -eq $true) {
    # Loop through items
    foreach ($item in (Get-ChildItem -Path "$PSScriptRoot/artifacts")) {
        New-OctopusArtifact -Path $item.FullName -Name $item.Name
    }
}

Provided under the Apache License version 2.0.

Report an issue

To use this template in Octopus Deploy, copy the JSON below and paste it into the Library → Step templates → Import dialog.

{
  "Id": "36df3e84-8501-4f2a-85cc-bd9eb22030d1",
  "Name": "Liquibase - Run command",
  "Description": "Run Liqbuibase commands against a database.  You can include Liquibase in the package itself or choose Download to download it during runtime.\n\nNote:\n- AWS EC2 IAM Authentication requires the AWS CLI to be installed.\n- Windows Authentication has been tested with \n  - Microsoft SQL Server \n  - PostgreSQL\n\nOnce the Liquibase commands have executed, the output is stored in an Octopus [output variable](https://octopus.com/docs/projects/variables/output-variables) called `LiquibaseCommandOutput` for use in subsequent Octopus deployment or runbook steps.",
  "Version": 26,
  "ExportedAt": "2024-07-23T23:44:02.126Z",
  "ActionType": "Octopus.Script",
  "Author": "twerthi",
  "Packages": [
    {
      "Name": "liquibaseChangeset",
      "Id": "15eeeac8-d80d-46ba-bc52-413fddae36f3",
      "PackageId": null,
      "FeedId": null,
      "AcquisitionLocation": "Server",
      "Properties": {
        "Extract": "True",
        "SelectionMode": "deferred",
        "PackageParameterName": "liquibaseChangeset"
      }
    }
  ],
  "Parameters": [
    {
      "Id": "a5f6167a-3e45-4337-ad76-fdacf385ac9c",
      "Name": "liquibaseProLicenseKey",
      "Label": "Pro license key",
      "HelpText": "Enter your Liquibase Pro license key. [Request a free 30-day trial.](https://www.liquibase.com/trial) Leave blank to use the Community Edition.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "f56f8e65-bd97-4be4-a9e8-979a5d8e5208",
      "Name": "liquibaseDatabaseType",
      "Label": "Database type",
      "HelpText": "Select the database type to deploy to.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Select",
        "Octopus.SelectOptions": "Cassandra|Cassandra\nCosmosDB|CosmosDB\nDB2|DB2\nMariaDB|MariaDB\nMongoDB|MongoDB\nMySQL|MySQL\nOracle|Oracle\nPostgreSQL|PostgreSQL\nSnowflake|Snowflake\nSqlServer|SqlServer"
      }
    },
    {
      "Id": "e0e2ba23-69f4-4a82-8310-b06f9a485802",
      "Name": "liquibaseCommand",
      "Label": "Command",
      "HelpText": "Use the drop down to select the command to execute.\nCommands with `*` have partial functionality with Community edition, full functionality with Pro edition.\n\nCommands with `**` are Pro only (all Pro only commands require the use of Additional switches).\n\nCommands with `***` require Additiona switches.\n\nAll commands that end in `SQL` will automatically add the `--outputFile` switch and include the generated output as an artifact.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Select",
        "Octopus.SelectOptions": "changelogSync|changelogSync\nchangelogSyncSQL|changelogSyncSQL\nclearCheckSums|clearCheckSums\ndeactivateChangeLog|deactivateChangeLog\ndropAll|dropAll*\nfutureRollbackSQL|futureRollbackSQL\nhistory|history\nrollbackOneChangeSet|rollbackOneChangeSet**\nrollbackOneChangeSetSQL|rollbackOneChangeSetSQL**\nrollbackOneUpdate|rollbackOneUpdate**\nrollbackOneUpdateSQL|rollbackOneUpdateSQL**\nrollbackToDate|rollbackToDate***\nrollbackToDateSQL|rollbackToDateSQL***\nstatus|status\ntag-exists|tag-exists\nupdateSQL|updateSQL\nupdate|update\nupdateTestingRollback|updateTestingRollback\nvalidate|validate"
      }
    },
    {
      "Id": "86049fa3-866d-4687-b128-25be358cc5aa",
      "Name": "liquibaseCommandStyle",
      "Label": "Command style",
      "HelpText": "Select the style of command, Legacy or Modern.  Legacy will place the Liquibase command at the end of the call, Modern will place it at the beginning\n\nLegacy:\n`liquibase --switch1 command`\n\nModern:\n`liquibase command --switch1`",
      "DefaultValue": "modern",
      "DisplaySettings": {
        "Octopus.ControlType": "Select",
        "Octopus.SelectOptions": "legacy|Legacy\nmodern|Modern"
      }
    },
    {
      "Id": "0af1aaa8-0cfb-4018-85fc-c996fd450d8c",
      "Name": "liquibaseCommandArguments",
      "Label": "Command Arguments",
      "HelpText": "Some commands require additional arguments, e.g. , `status --verbose`, `rollbackOneUpdate --force`",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "9f2a3e0c-1afd-4472-acc9-66bd8743ec37",
      "Name": "liquibaseAdditionalSwitches",
      "Label": "Additional switches",
      "HelpText": "A list of additional switches to include for the command, one per line.  (I.e. `--logLevel=debug`)",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "MultiLineText"
      }
    },
    {
      "Id": "ef523320-65ec-44ce-a0cd-0e65a0fed9f9",
      "Name": "liquibaseChangeLogFileName",
      "Label": "Change Log file name",
      "HelpText": "Name of the changelog file in the package.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "2ff32870-827c-45c1-86f8-f31842ef547b",
      "Name": "liquibaseChangeset",
      "Label": "Changeset package",
      "HelpText": "Select the package with the changeset.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Package"
      }
    },
    {
      "Id": "dbb7c649-f87b-42f3-b6c9-6db97df39a2f",
      "Name": "liquibaseServerName",
      "Label": "Server name",
      "HelpText": "Name or IP address of the database server.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "481b1bd7-ed0a-40da-8ee6-81397c8d0769",
      "Name": "liquibaseServerPort",
      "Label": "Server port",
      "HelpText": "The port the database server listens on.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "56db5b8b-ceaa-4ee8-b231-df15ea7d9a43",
      "Name": "liquibaseAuthenticationMethod",
      "Label": "Authentication Method",
      "HelpText": "Method used to authenticate to the database server.",
      "DefaultValue": "usernamepassword",
      "DisplaySettings": {
        "Octopus.ControlType": "Select",
        "Octopus.SelectOptions": "awsiam|AWS EC2 IAM Role\nazuremanagedidentity|Azure Managed Identity\ngcpserviceaccount|GCP Service Account\nusernamepassword|Username\\Password\nwindowsauthentication|Windows Authentication"
      }
    },
    {
      "Id": "8d4337f3-3e37-40e7-983b-b85cc630a720",
      "Name": "liquibaseDatabaseName",
      "Label": "Database name",
      "HelpText": "Name of the database to deploy to.\n- Service name for Oracle\n- KeySpace for Cassandra",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "0524f7f4-fb8e-4747-8f1b-679237e398a7",
      "Name": "liquibaseUsername",
      "Label": "Username",
      "HelpText": "Username of a user that has permission to make changes to the database.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "d58b5a73-681b-434a-92a9-b373216fedc3",
      "Name": "liquibasePassword",
      "Label": "Password",
      "HelpText": "Password for the user with permissions to make changes to the database.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Sensitive"
      }
    },
    {
      "Id": "bac7d86b-eb37-4b3f-a99c-0779ffae3fca",
      "Name": "liquibaseQueryStringParameters",
      "Label": "Connection query string parameters",
      "HelpText": "Add additional parameters to the connection string URL. Example: ?useUnicode=true or ;AuthMech=1",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "8f1c2bc5-6b39-4c95-8eb0-bd97b0fe62f0",
      "Name": "liquibaseClassPath",
      "Label": "Database driver path",
      "HelpText": "Filepath to the location of the .jar driver for the database type.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "cae0020d-595b-407c-a96b-02f7a6bc9788",
      "Name": "liquibaseExecutablePath",
      "Label": "Executable file path",
      "HelpText": "File path to the Liquibase executable.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    },
    {
      "Id": "2eae1d4e-a12d-47dd-8a43-1a6e49983fd9",
      "Name": "liquibaseDownload",
      "Label": "Download Liquibase?",
      "HelpText": "Use this option to download the software necessary to deploy a Liquibase changeset.  This will download Liquibase, java, and the appropriate driver for the selected database type.  Using this option overrides the `Database driver path` and `Executable file path` inputs.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "Checkbox"
      }
    },
    {
      "Id": "3f37288f-a4df-4ed7-b309-bb361a496572",
      "Name": "liquibaseVersion",
      "Label": "Liquibase version",
      "HelpText": "Used with `Download Liquibase` to specify the version of Liquibase to use.",
      "DefaultValue": "",
      "DisplaySettings": {
        "Octopus.ControlType": "SingleLineText"
      }
    }
  ],
  "Properties": {
    "Octopus.Action.Script.ScriptSource": "Inline",
    "Octopus.Action.Script.ScriptBody": "# Configure template\n\n# Check to see if $IsWindows is available\nif ($null -eq $IsWindows) {\n    Write-Host \"Determining Operating System...\"\n    $IsWindows = ([System.Environment]::OSVersion.Platform -eq \"Win32NT\")\n    $IsLinux = ([System.Environment]::OSVersion.Platform -eq \"Unix\")\n}\n\n# Fix ANSI Color on PWSH Core issues when displaying objects\nif ($PSEdition -eq \"Core\") {\n    $PSStyle.OutputRendering = \"PlainText\"\n}\n\n# Set TLS\n[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor [Net.SecurityProtocolType]::Tls11 -bor [System.Net.SecurityProtocolType]::Tls12\n\n# Downloads and extracts liquibase to the work folder\nFunction Get-Liquibase {\n    # Define parameters\n    param ($Version) \n\n    $repositoryName = \"liquibase/liquibase\"\n\n    # Check to see if version wasn't specified\n    if ([string]::IsNullOrEmpty($Version)) {\n        # Get the latest version download url\n        $downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName | Where-Object { $_.EndsWith(\".zip\") })\n    }\n    else {\n        $downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName -Version $Version | Where-Object { $_.EndsWith(\".zip\") })\n    }\n\n    # Extract the downloaded file\n    Expand-DownloadedFile -DownloadUrls $downloadUrl | Out-Null\n    \n    # Parse downloaded version\n    if ($downloadUrl -is [array]) {\n        $downloadedFileName = [System.IO.Path]::GetFileName($downloadUrl[0])\n    }\n    else {\n        $downloadedFileName = [System.IO.Path]::GetFileName($downloadUrl)\n    }\n\n    # Return the downloaded version\n    return $downloadedFileName.SubString($downloadedFileName.IndexOf(\"-\") + 1).Replace(\".zip\", \"\")    \n}\n\n# Downloads the files\nFunction Expand-DownloadedFile {\n    # Define parameters\n    param (\n        $DownloadUrls\n    )\n    \n    # Loop through results\n    foreach ($url in $DownloadUrls) {\n        # Download the zip file\n        $folderName = [System.IO.Path]::GetFileName(\"$PSScriptroot/$($url.Substring($url.LastIndexOf(\"/\")))\").Replace(\".zip\", \"\")\n        $zipFile = \"$PSScriptroot/$folderName/$($url.Substring($url.LastIndexOf(\"/\")))\"\n        Write-Host \"Downloading $zipFile from $url ...\"\n        \n        if ((Test-Path -Path \"$PSScriptroot/$folderName\") -eq $false) {\n            # Create folder\n            New-Item -Path \"$PSScriptroot/$folderName/\" -ItemType Directory\n        }\n\n        # Download the zip file\n        Invoke-WebRequest -Uri $url -OutFile $zipFile -UseBasicParsing | Out-Null\n\n        # Extract package\n        Write-Host \"Extracting $zipFile ...\"\n        Expand-Archive -Path $zipFile -DestinationPath \"$PSSCriptRoot/$folderName\" | Out-Null\n    }\n}\n\n\n# Downloads and extracts Java to the work folder, then adds the location of java.exe to the $env:PATH variabble so it can be called\nFunction Get-Java {\n    # Check to see if a folder needs to be created\n    if ((Test-Path -Path \"$PSScriptRoot/jdk\") -eq $false) {\n        # Create new folder\n        New-Item -ItemType Directory -Path \"$PSSCriptRoot/jdk\"\n    }\n\n    # Download java\n    Write-Output \"Downloading Java ... \"\n    \n    # Determine OS\n    if ($IsWindows) {\n        Invoke-WebRequest -Uri \"https://download.java.net/java/GA/jdk14.0.2/205943a0976c4ed48cb16f1043c5c647/12/GPL/openjdk-14.0.2_windows-x64_bin.zip\" -OutFile \"$PSScriptroot/jdk/openjdk-14.0.2_windows-x64_bin.zip\" -UseBasicParsing\n\n        # Extract\n        Write-Output \"Extracting Java ... \"\n        Expand-Archive -Path \"$PSScriptroot\\jdk\\openjdk-14.0.2_windows-x64_bin.zip\" -DestinationPath \"$PSSCriptRoot/jdk\"\n\n        # Get Java executable\n        $javaExecutable = Get-ChildItem -Path \"$PSScriptRoot\\jdk\" -Recurse | Where-Object { $_.Name -eq \"java.exe\" }\n    }\n    \n    if ($IsLinux) {\n        Invoke-WebRequest -Uri \"https://download.java.net/openjdk/jdk14/ri/openjdk-14+36_linux-x64_bin.tar.gz\" -OutFile \"$PSScriptroot/jdk/openjdk-14+36_linux-x64_bin.tar.gz\" -UseBasicParsing\n\n        # Extract\n        Write-Output \"Extracting Java ... \"\n        tar -xvzf \"$PSScriptroot/jdk/openjdk-14+36_linux-x64_bin.tar.gz\" --directory \"$PSScriptRoot/jdk\"\n\n        # Get Java executable\n        $javaExecutable = Get-ChildItem -Path \"$PSScriptRoot/jdk\" -Recurse | Where-Object { $_.Name -eq \"java\" }   \n    }\n    \n    # Add path to current session as first entry to bypass other versions of Java that may be installed.\n    $env:PATH = \"$($javaExecutable.Directory)$([IO.Path]::PathSeparator)\" + $env:PATH\n    \n}\n\nFunction Get-DriverAssets {\n    # Define parameters\n    param (\n        $DownloadInfo\n    )\n\n    # Declare working variables\n    $assetFilePath = \"\"\n\n    # Check to see if there are multiple assets to download\n    if ($DownloadInfo -is [array]) {\n        # Declare local variables\n        $assetFiles = @()\n\n        # Loop through array\n        foreach ($url in $DownloadInfo) {\n            # Download the asset\n            Write-Host \"Downloading asset from $url...\"\n            $assetPath = \"$PSScriptroot/$($url.Substring($url.LastIndexOf(\"/\")))\"\n            \n            # Skip test assets\n            if ($assetPath.EndsWith(\"tests.jar\")) {\n                Write-Host \"Asset is for testing, skipping ...\"\n                continue\n            }\n            \n            Invoke-WebRequest -Uri $url -Outfile $assetPath -UseBasicParsing\n            $assetFiles += $assetPath\n        }\n\n        # Assign paths\n        $assetFilePath = $assetFiles -join \"$([IO.Path]::PathSeparator)\"\n    }\n    else {\n        # Download asset\n        Write-Host \"Downloading asset from $DownloadInfo ...\"\n        $assetFilePath = \"$PSScriptroot/$($DownloadInfo.Substring($DownloadInfo.LastIndexOf(\"/\")))\"\n        Invoke-WebRequest -Uri $DownloadInfo -Outfile $assetFilePath -UseBasicParsing\n    }\n\n    # Return path\n    return $assetFilePath\n}\n\n# Gets download url of latest release with an asset\nFunction Get-LatestVersionDownloadUrl {\n    # Define parameters\n    param(\n        $Repository,\n        $Version\n    )\n    \n    # Define local variables\n    $releases = \"https://api.github.com/repos/$Repository/releases\"\n    \n    # Get latest version\n    Write-Host \"Determining latest release of $Repository ...\"\n    \n    $tags = (Invoke-WebRequest $releases -UseBasicParsing | ConvertFrom-Json)\n    \n    if ($null -ne $Version) {\n        # Get specific version\n        $tags = ($tags | Where-Object { $_.name.EndsWith($Version) })\n\n        # Check to see if nothing was returned\n        if ($null -eq $tags) {\n            # Not found\n            Write-Host \"No release found matching version $Version, getting highest version using Major.Minor syntax...\"\n\n            # Get the tags\n            $tags = (Invoke-WebRequest $releases -UseBasicParsing | ConvertFrom-Json)\n\n            # Parse the version number into a version object\n            $parsedVersion = [System.Version]::Parse($Version)\n            $partialVersion = \"$($parsedVersion.Major).$($parsedVersion.Minor)\"\n            \n            # Filter tags to ones matching only Major.Minor of version specified\n            $tags = ($tags | Where-Object { $_.name.Contains(\"$partialVersion.\") -and $_.draft -eq $false })\n            \n            # Grab the latest\n            if ($null -eq $tags)\n            {\n            \t# decrement minor version\n                $minorVersion = [int]$parsedVersion.Minor\n                $minorVersion --\n                \n                # return the urls\n                return (Get-LatestVersionDownloadUrl -Repository $Repository -Version \"$($parsedVersion.Major).$($minorVersion)\")\n            }\n        }\n    }\n\n    # Find the latest version with a downloadable asset\n    foreach ($tag in $tags) {\n        if ($tag.assets.Count -gt 0) {\n            return $tag.assets.browser_download_url\n        }\n    }\n\n    # Return the version\n    return $null\n}\n\n# Finds the specified changelog file\nFunction Get-ChangeLog {\n    # Define parameters\n    param ($FileName)\n    \n    # Find file\n    $fileReference = (Get-ChildItem -Path $OctopusParameters[\"Octopus.Action.Package[liquibaseChangeSet].ExtractedPath\"] -Recurse | Where-Object { $_.Name -eq $FileName })\n\n    # Check to see if something weas returned\n    if ($null -eq $fileReference) {\n        # Not found\n        Write-Error \"$FileName was not found in $PSScriptRoot or subfolders.\"\n    }\n\n    # Return the reference\n    return $fileReference\n}\n\n# Downloads the appropriate JDBC driver\nFunction Get-DatabaseJar {\n    # Define parameters\n    param ($DatabaseType)\n\n    # Declare local variables\n    $driverPath = \"\"\n\n    # Check to see if a folder needs to be created\n    if ((Test-Path -Path \"$PSScriptRoot/DatabaseDriver\") -eq $false) {\n        # Create new folder\n        New-Item -ItemType Directory -Path \"$PSSCriptRoot/DatabaseDriver\" | Out-Null\n    }\n\n    # Download the driver for the selected type\n    switch ($DatabaseType) {\n        \"Cassandra\" {\n\n\t\t\t# Get the release download\n            Write-Host \"Downloading Cassandra JDBC driver bundle ...\"\n\t\t\t$downloadUrl = Get-LatestVersionDownloadUrl -Repository \"ing-bank/cassandra-jdbc-wrapper\"\n           \n            # Find driver\n            $driverPath = (Get-DriverAssets -DownloadInfo $downloadUrl)\n\n            # Set repo name\n            $repositoryName = \"liquibase/liquibase-cassandra\"\n            \n            if ([string]::IsNullOrEmpty($liquibaseVersion)) {\n                # Get the latest version for the extension\n                $downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName | Where-Object { $_.EndsWith(\".jar\") })\n           \t}\n            else {\n                # Download version matching extension\n                $downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName -Version $liquibaseVersion | Where-Object { $_.EndsWith(\".jar\") })\n            }           \n\n            $extensionPath = Get-DriverAssets -DownloadInfo $downloadUrl\n            \n            # Make driver path null\n            $driverPath = \"$driverPath$([IO.Path]::PathSeparator)$extensionPath\"\n\n            break\n        }\n        \"CosmosDB\"\n        {\n\t\t\t# Download the (long) list of dependencies\n            $driverPaths = @()\n\n\t\t\t# Set repo name\n            $repositoryName = \"liquibase/liquibase-cosmosdb\"\n\n\t\t\tif ([string]::IsNullOrEmpty($liquibaseVersion))\n            {\n            \t# Get the latest version for the extension\n            \t$downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName | Where-Object {$_.EndsWith(\".jar\")})\n           \t}\n            else\n            {\n            \t# Download version matching extension\n                $downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName -Version $liquibaseVersion | Where-Object {$_.EndsWith(\".jar\")})\n            }    \n            \n            $extensionPath = Get-DriverAssets -DownloadInfo $downloadUrl\n                     \n\t\t\t# Add to driver path\n            $driverPaths += $extensionPath\n            \n            Write-Host \"Downloading azure-cosmos driver ...\"\n            $driverVersion = \"4.28.0\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/azure-cosmos-$driverVersion.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/com/azure/azure-cosmos/$driverVersion/azure-cosmos-$driverVersion.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n            # Add to driver path\n            $driverPaths += $filePath\n            \n            Write-Host \"Downloading azure-core driver ...\"\n            $driverVersion = \"1.27.0\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/azure-core-$driverVersion.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/com/azure/azure-core/$driverVersion/azure-core-$driverVersion.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            $files = Get-ChildItem -Path \"$PSScriptRoot/DatabaseDriver\"\n            \n            Write-Host \"There are these $files\"\n\n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading jackson core driver ...\"\n            $driverVersion = \"2.13.2\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/jackson-core-$driverVersion.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/$driverVersion/jackson-core-$driverVersion.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n            \n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading slf4j core driver ...\"\n            $driverVersion = \"1.7.36\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/slf4j-api-$driverVersion.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/org/slf4j/slf4j-api/$driverVersion/slf4j-api-$driverVersion.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n            \n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty buffer driver ...\"\n            $driverVersion = \"4.1.75\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-buffer-$driverVersion.final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-buffer/$driverVersion.Final/netty-buffer-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n            \n            # Add to driver path\n            $driverPaths += $filePath\n\t\t\t\n            Write-Host \"Downloading reactor-core driver ...\"\n            $driverVersion = \"3.4.16\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/reactor-core-$driverVersion.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/projectreactor/reactor-core/$driverVersion/reactor-core-$driverVersion.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n            \n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading reactor-netty-core driver ...\"\n            $driverVersion = \"1.0.17\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/reactor-core-$driverVersion.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/projectreactor/netty/reactor-netty-core/$driverVersion/reactor-netty-core-$driverVersion.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n            \n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading reactor-netty-core driver ...\"\n            $driverVersion = \"1.0.17\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/reactor-netty-http-$driverVersion.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/projectreactor/netty/reactor-netty-http/$driverVersion/reactor-netty-http-$driverVersion.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n            \n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty-resolver driver ...\"\n            $driverVersion = \"4.1.75\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-resolver-$driverVersion.Final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-resolver/$driverVersion.Final/netty-resolver-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing  | Out-Null\n            \n            \n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty-transport driver ...\"\n            $driverVersion = \"4.1.75\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-transport-$driverVersion.Final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-transport/$driverVersion.Final/netty-transport-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing  | Out-Null\n            \n            \n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading reactivestreams driver ...\"\n            $driverVersion = \"1.0.3\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/reactive-streams-$driverVersion.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/org/reactivestreams/reactive-streams/$driverVersion/reactive-streams-$driverVersion.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading jackson-databind driver ...\"\n            $driverVersion = \"2.13.2.1\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/jackson-databind-$driverVersion.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/$driverVersion/jackson-databind-$driverVersion.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading jackson-annotations driver ...\"\n            $driverVersion = \"2.13.2\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/jackson-annotations-$driverVersion.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-annotations/$driverVersion/jackson-annotations-$driverVersion.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n            \n            Write-Host \"Downloading jackson-module-afterburner driver ...\"\n            $driverVersion = \"2.13.2\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/jackson-module-afterburner-$driverVersion.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/com/fasterxml/jackson/module/jackson-module-afterburner/$driverVersion/jackson-module-afterburner-$driverVersion.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading reactor-netty driver ...\"\n            $driverVersion = \"1.0.17\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/reactor-netty-$driverVersion.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/projectreactor/netty/reactor-netty/$driverVersion/reactor-netty-$driverVersion.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty-transport-native-unix-common driver ...\"\n            $driverVersion = \"4.1.75\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-transport-native-unix-common-$driverVersion.Final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-transport-native-unix-common/$driverVersion.Final/netty-transport-native-unix-common-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty-transport-native-epoll driver ...\"\n            $driverVersion = \"4.1.75\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-transport-native-epoll-$driverVersion.Final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-transport-native-epoll/$driverVersion.Final/netty-transport-native-epoll-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty-tcnative-boringssl-static driver ...\"\n            $driverVersion = \"2.0.51\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-tcnative-boringssl-static-$driverVersion.Final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-tcnative-boringssl-static/$driverVersion.Final/netty-tcnative-boringssl-static-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty-resolver-dns driver ...\"\n            $driverVersion = \"4.1.75\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-resolver-dns-$driverVersion.Final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-resolver-dns/$driverVersion.Final/netty-resolver-dns-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty-handler-proxy driver ...\"\n            $driverVersion = \"4.1.75\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-handler-proxy-$driverVersion.Final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-handler-proxy/$driverVersion.Final/netty-handler-proxy-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty-handler driver ...\"\n            $driverVersion = \"4.1.75\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-handler-$driverVersion.Final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-handler/$driverVersion.Final/netty-handler-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty-common driver ...\"\n            $driverVersion = \"4.1.75\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-common-$driverVersion.Final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-common/$driverVersion.Final/netty-common-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty-codec-socks driver ...\"\n            $driverVersion = \"4.1.75\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-codec-socks-$driverVersion.Final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-codec-socks/$driverVersion.Final/netty-codec-socks-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty-codec-http driver ...\"\n            $driverVersion = \"4.1.75\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-codec-http-$driverVersion.Final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-codec-http/$driverVersion.Final/netty-codec-http-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty-codec-http2 driver ...\"\n            $driverVersion = \"4.1.75\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-codec-http2-$driverVersion.Final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-codec-http2/$driverVersion.Final/netty-codec-http2-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty-codec-dns driver ...\"\n            $driverVersion = \"4.1.75\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-codec-dns-$driverVersion.Final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-codec-dns/$driverVersion.Final/netty-codec-dns-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty-codec driver ...\"\n            $driverVersion = \"4.1.75\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-codec-$driverVersion.Final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-codec/$driverVersion.Final/netty-codec-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading micrometer-core driver ...\"\n            $driverVersion = \"1.8.4\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/micrometer-core-$driverVersion.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/micrometer/micrometer-core/$driverVersion/micrometer-core-$driverVersion.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading metrics-core driver ...\"\n            $driverVersion = \"4.2.9\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/metrics-core-$driverVersion.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/dropwizard/metrics/metrics-core/$driverVersion/metrics-core-$driverVersion.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading LatencyUtils driver ...\"\n            $driverVersion = \"2.0.3\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/LatencyUtils-$driverVersion.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/org/latencyutils/LatencyUtils/$driverVersion/LatencyUtils-$driverVersion.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading jackson-datatype-jsr310 driver ...\"\n            $driverVersion = \"2.12.5\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/jackson-datatype-jsr310-$driverVersion.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/com/fasterxml/jackson/datatype/jackson-datatype-jsr310/$driverVersion/jackson-datatype-jsr310-$driverVersion.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty-tcnative-classes driver ...\"\n            $driverVersion = \"2.0.51\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-tcnative-classes-$driverVersion.Final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-tcnative-classes/$driverVersion.Final/netty-tcnative-classes-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty-transport-classes-kqueue driver ...\"\n            $driverVersion = \"4.1.73\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-transport-classes-kqueue-$driverVersion.Final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-transport-classes-kqueue/$driverVersion.Final/netty-transport-classes-kqueue-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading slf4j-simple driver ...\"\n            $driverVersion = \"1.7.36\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/slf4j-simple-$driverVersion.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/org/slf4j/slf4j-simple/$driverVersion/slf4j-simple-$driverVersion.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty-transport-classes-epoll driver ...\"\n            $driverVersion = \"4.1.75\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-transport-classes-epoll-$driverVersion.Final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-transport-classes-epoll/$driverVersion.Final/netty-transport-classes-epoll-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n            Write-Host \"Downloading netty-transport-native-kqueue driver ...\"\n            $driverVersion = \"4.1.75\"\n            $filePath = \"$PSScriptroot/DatabaseDriver/netty-transport-native-kqueue-$driverVersion.Final.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/io/netty/netty-transport-native-kqueue/$driverVersion.Final/netty-transport-native-kqueue-$driverVersion.Final.jar\" -Outfile $filePath -UseBasicParsing | Out-Null\n            \n\n            # Add to driver path\n            $driverPaths += $filePath\n\n\t\t\t# Return driver list separated by system specific PathSeparator\n            $driverPath = ($driverPaths -join [IO.Path]::PathSeparator)\n            \n            $files = Get-ChildItem -Path \"$PSScriptRoot/DatabaseDriver\"\n            \n            #Write-Host \"There are these $files\"\n            \n       \t\tbreak\n        }        \n        \"DB2\" {\n            # Use built-in driver\n            $driverPath = $null\n            break\n        }\n        \"MariaDB\" {\n            # Download MariaDB driver\n            Write-Host \"Downloading MariaDB driver ...\"\n            $driverPath = \"$PSScriptroot/DatabaseDriver/mariadb-java-client-2.6.2.jar\"\n            Invoke-WebRequest -Uri \"https://downloads.mariadb.com/Connectors/java/connector-java-2.6.2/mariadb-java-client-2.6.2.jar\" -OutFile $driverPath -UseBasicParsing\n             \n            break\n        }\n        \"MongoDB\" {\n            # Download MongoDB driver\n            Write-Host \"Downloading Maven MongoDB driver ...\"\n            $driverPath = \"$PSScriptroot/DatabaseDriver/mongo-java-driver-3.12.7.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/org/mongodb/mongo-java-driver/3.12.7/mongo-java-driver-3.12.7.jar\" -Outfile $driverPath -UseBasicParsing\n            \n            # Check to see if they are using a licenced version\n            if (![string]::IsNullOrWhitespace($liquibaseProLicenseKey)) {\n                # Set the paid version url\n                $mongoVersions = Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/org/liquibase/ext/liquibase-commercial-mongodb\" -UseBasicParsing\n                \n                # Loop through links, look for ones that evaluate to version\n                $versions = @()\n                foreach ($link in $mongoVersions.Links) {\n                    Write-Verbose \"Evaluating: $link\"\n                    if (![string]::IsNullOrWhitespace($link.title)) {\n                        # Get the inner text\n                        $versionNumber = $link.title.Replace(\"/\", \"\")\n\n                        # Check to see if $versionNumber can be parsed as a versionNumber\n                        $versionOut = $null\n                        if ([System.Version]::TryParse($versionNumber, [ref]$versionOut)) {\n                            $versions += $versionOut\n                        }\n                    }\n                }\n\n                # Get the highest version number\n                $info = ($versions | Measure-Object -Maximum)\n\n                $downloadUrl = \"https://repo1.maven.org/maven2/org/liquibase/ext/liquibase-commercial-mongodb/$($info.Maximum)/liquibase-commercial-mongodb-$($info.Maximum).jar\"                \n            }\n            else {\n                # Set repo name\n                $repositoryName = \"liquibase/liquibase-mongodb\"            \n                \n                # Download latest OSS version\n                $downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName | Where-Object { $_.EndsWith(\".jar\") })\n            }\n                        \n            $extensionPath = Get-DriverAssets -DownloadInfo $downloadUrl\n            \n            # Make driver path null\n            $driverPath = \"$driverPath$([IO.Path]::PathSeparator)$extensionPath\"\n            \n            break\n        }\n        \"MySQL\" {\n            # Download MariaDB driver\n            Write-Host \"Downloading MySQL driver ...\"\n            Invoke-WebRequest -Uri \"https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.28.zip\" -OutFile \"$PSScriptroot/DatabaseDriver/mysql-connector-java-8.0.28.zip\" -UseBasicParsing -UserAgent \"curl/7.8.3.1\"\n\n            # Extract package\n            Write-Host \"Extracting MySQL driver ...\"\n            Expand-Archive -Path \"$PSScriptroot/DatabaseDriver/mysql-connector-java-8.0.28.zip\" -DestinationPath \"$PSSCriptRoot/DatabaseDriver\"\n\n            # Find driver\n            $driverPath = (Get-ChildItem -Path \"$PSScriptRoot/DatabaseDriver\" -Recurse | Where-Object { $_.Name -eq \"mysql-connector-java-8.0.28.jar\" }).FullName\n\n            break\n        }\n        \"Oracle\" {\n            # Download Oracle driver\n            Write-Host \"Downloading Oracle driver ...\"\n            $driverPath = \"$PSScriptroot/DatabaseDriver/ojdbc10.jar\"\n            Invoke-WebRequest -Uri \"https://download.oracle.com/otn-pub/otn_software/jdbc/211/ojdbc11.jar\" -OutFile $driverPath -UseBasicParsing\n\n            break\n        }\n        \"SqlServer\" {\n            # Download Microsoft driver\n            Write-Host \"Downloading Sql Server driver ...\"\n            Invoke-WebRequest -Uri \"https://go.microsoft.com/fwlink/?linkid=2186163\" -OutFile \"$PSScriptroot/DatabaseDriver/sqljdbc_10.2.0.0_enu.zip\" -UseBasicParsing\n\n            # Extract package\n            Write-Host \"Extracting SqlServer driver ...\"\n            Expand-Archive -Path \"$PSScriptroot/DatabaseDriver/sqljdbc_10.2.0.0_enu.zip\" -DestinationPath \"$PSSCriptRoot/DatabaseDriver\"\n\n            # Find driver\n            $driverPath = (Get-ChildItem -Path \"$PSSCriptRoot/DatabaseDriver\" -Recurse | Where-Object { $_.Name -eq \"mssql-jdbc-10.2.0.jre11.jar\" }).FullName\n            \n            # Determine architecture\n            if ([System.Environment]::Is64BitOperatingSystem) {\n                # Locate auth dll\n                $authDll = Get-ChildItem -Path \"$PSScriptRoot/DatabaseDriver\" -Recurse | Where-Object { $_.Name -eq \"mssql-jdbc_auth-10.2.0.x64.dll\" }\n            }\n            else {\n                $authDll = Get-ChildItem -Path \"$PSScriptRoot/DatabaseDriver\" -Recurse | Where-Object { $_.Name -eq \"mssql-jdbc_auth-10.2.0.x86.dll\" }\n            }\n            \n            # Add the dll to the path so it can find it.\n            $env:PATH += \"$([IO.Path]::PathSeparator)$($authDll.Directory)\"\n            \n            break\n        }\n        \"PostgreSQL\" {\n            # Download PostgreSQL driver\n            Write-Host \"Downloading PostgreSQL driver ...\"\n            $driverPath = \"$PSScriptroot/DatabaseDriver/postgresql-42.2.12.jar\"\n            Invoke-WebRequest -Uri \"https://jdbc.postgresql.org/download/postgresql-42.2.12.jar\" -OutFile $driverPath -UseBasicParsing\n            \n            # Download the WAFFLE jna driver for Windows Authentication\n            $repositoryName = \"waffle/waffle\"\n            \n            # Latest version of Waffle (2.3.0) doesn't seem to work, can't find sspi method, specify version 1.9.0\n            $downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName -Version \"1.9.0\" | Where-Object { $_.EndsWith(\".zip\") })\n            Expand-DownloadedFile -DownloadUrls $downloadUrl | Out-Null\n            \n            # Get all waffle jars\n            $waffleFolder = (Get-ChildItem -Path \"$PSScriptroot\" -Recurse | Where-Object { $_.PSIsContainer -and $_.Name -like \"Waffle*\" })           \n            $waffleJars = (Get-ChildItem -Path $waffleFolder.FullName -Recurse | Where-Object { $_.Extension -eq \".jar\" })\n            \n            foreach ($jar in $waffleJars) {\n                $driverPath += \"$([IO.Path]::PathSeparator)$($jar.FullName)\"\n            }\n\n            break\n        }\n        \"Snowflake\" {\n            # Set repo name\n            $repositoryName = \"liquibase/liquibase-snowflake\"\n\n            # Download Snowflake driver\n            Write-Host \"Downloading Snowflake driver ...\"\n            $driverPath = \"$PSScriptroot/DatabaseDriver/snowflake-jdbc-3.9.2.jar\"\n            Invoke-WebRequest -Uri \"https://repo1.maven.org/maven2/net/snowflake/snowflake-jdbc/3.9.2/snowflake-jdbc-3.9.2.jar\" -OutFile $driverPath -UseBasicParsing\n\n            if ([string]::IsNullOrEmpty($liquibaseVersion)) {\n                # Get the latest version for the extension\n                $downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName | Where-Object { $_.EndsWith(\".jar\") })\n           \t}\n            else {\n                # Download version matching extension\n                $downloadUrl = (Get-LatestVersionDownloadUrl -Repository $repositoryName -Version $liquibaseVersion | Where-Object { $_.EndsWith(\".jar\") })\n            }\n                        \n            $extensionPath = Get-DriverAssets -DownloadInfo $downloadUrl\n            \n            # Make driver path null\n            $driverPath = \"$driverPath$([IO.Path]::PathSeparator)$extensionPath\"\n\n\n            break\n        }\n        default {\n            # Display error\n            Write-Error \"Unknown database type: $DatabaseType.\"\n        }\n    }\n\n    # Return the driver location\n    return $driverPath\n}\n\n# Returns the connection string formatted for the database type\nFunction Get-ConnectionUrl {\n    # Define parameters\n    param ($DatabaseType, \n        $ServerPort, \n        $ServerName, \n        $DatabaseName, \n        $QueryStringParameters)\n\n    # Define local variables\n    $connectionUrl = \"\"\n\n    # Download the driver for the selected type\n    switch ($DatabaseType) {\n        \"Cassandra\" {\n            #$connectionUrl = \"jdbc:cassandra://{0}:{1};DefaultKeyspace={2}\"\n            $connectionUrl = \"jdbc:cassandra://{0}:{1}/{2}\"\n            break\n        }\n        \"CosmosDB\"\n        {\n            $connectionUrl = \"cosmosdb://{0}:$($liquibasePassword)@{0}:{1}/{2}\" \n            break\n        }        \n        \"DB2\" {\n            $connectionUrl = \"jdbc:db2://{0}:{1}/{2}\"\n            break\n        }\n        \"MariaDB\" {\n            $connectionUrl = \"jdbc:mariadb://{0}:{1}/{2}\"\n            \n            # Check for Windows Authentication type\n            if ($liquibaseAuthenticationMethod -eq \"windowsauthentication\") {\n                # Add querysting parameter\n                $connectionUrl += \"?integratedSecurity=true\"\n            }\n            \n            break\n        }\n        \"MongoDB\" {        \n            $connectionUrl = \"mongodb://{0}:{1}/{2}\"            \n            break\n        }\n        \"MySQL\" {\n        \n            $connectionUrl = \"jdbc:mysql://{0}:{1}/{2}\"\n            \n            # Check for Windows Authentication type\n            if ($liquibaseAuthenticationMethod -eq \"windowsauthentication\") {\n                # Add querysting parameter\n                $connectionUrl += \"?integratedSecurity=true\"\n            }\n            \n            break\n        }\n        \"Oracle\" {\n            $connectionUrl = \"jdbc:oracle:thin:@{0}:{1}/{2}\"\n            break\n        }\n        \"SqlServer\" {\n            $connectionUrl = \"jdbc:sqlserver://{0}:{1};database={2};\"\n            \n            switch ($liquibaseAuthenticationMethod) {\n                \"azuremanagedidentity\" {\n                    # Add querystring parameter\n                    $connectionUrl += \"Authentication=ActiveDirectoryMSI;\"\n                    break\n                }\n                \"windowsauthentication\" {\n                    # Add querysting parameter\n                    $connectionUrl += \"integratedSecurity=true;\"\n                \t\n                    break\n                }\n            }\n            \n            break\n        }\n        \"PostgreSQL\" {\n            $connectionUrl = \"jdbc:postgresql://{0}:{1}/{2}\"\n            \n            # Check for Windows Authentication type\n            if ($liquibaseAuthenticationMethod -eq \"windowsauthentication\") {\n                # Add querysting parameter\n                $connectionUrl += \"?gsslib=sspi\"\n            }\n            \n            break\n        }\n        \"Snowflake\" {\n            $connectionUrl = \"jdbc:snowflake://{0}.snowflakecomputing.com?db={2}\"\n            break\n        }\n        default {\n            # Display error\n            Write-Error \"Unkonwn database type: $DatabaseType.\"\n        }\n    }\n\n    if (![string]::IsNullOrWhitespace($QueryStringParameters)) {       \t\n        if ($connectionUrl.Contains(\"?\")) {\n           \t# Replace the ? with & in connection string parameters\n            $QueryStringParameters = $QueryStringParameters.Replace(\"?\", \"&\")\n        }\n        \n        # Appen connecion string\n        $connectionUrl += \"$QueryStringParameters\"\n    }\n\n    # Return the url\n    return ($connectionUrl -f $ServerName, $ServerPort, $DatabaseName)\n}\n\n# Create array for arguments\n$liquibaseArguments = @()\n\n# Check to see if it's running on Windows\nif ($IsWindows) {\n    # Disable the progress bar so downloading files via Invoke-WebRequest are faster\n    $ProgressPreference = 'SilentlyContinue'\n}\n\n# Check for license key\nif (![string]::IsNullOrWhitespace($liquibaseProLicenseKey)) {\n    # Add key to arguments\n    $liquibaseArguments += \"--liquibaseProLicenseKey=$liquibaseProLicenseKey\"\n}\n\n# Find Change log\n$changeLogFile = (Get-ChangeLog -FileName $liquibaseChangeLogFileName)\n$liquibaseArguments += \"--changeLogFile=$($changeLogFile.Name)\"\n\n# Set the location to where the file is\nSet-Location -Path $changeLogFile.Directory\n\n# Check to see if it needs to be downloaed to machine\nif ($liquibaseDownload -eq $true) {\n    # Download and extract liquibase - get the version for extensions that are version specific\n    $liquibaseVersion = Get-Liquibase -Version $liquibaseVersion -DownloadFolder $workingFolder\n\n    # Download and extract java and add it to PATH environment variable\n    Get-Java\n\n    # Get the driver\n    $driverPath = Get-DatabaseJar -DatabaseType $liquibaseDatabaseType\n\n    # Check to see if it's null\n    if ($null -ne $driverPath) {\n        # Create folder to hold jar files to override\n        New-Item -Path \"$PWD/liquibase_libs/\" -ItemType Directory    \n\n        # Copy contents into liquibase_libs folder\n        $driverPaths = $driverPath.Split([IO.Path]::PathSeparator)\n\n        foreach ($driver in $driverPaths) {\n            # Copy the items\n            $files = Get-ChildItem -Path $driver\n\n            foreach ($file in $files) {\n                Write-Host \"Copying $($file.FullName) to $PWD/liquibase_libs/$($file.Name)\"\n                Copy-Item -Path $file.FullName -Destination \"$PWD/liquibase_libs/$($file.Name)\"\n            }\n        }\n    }\n}\nelse {\n    if (![string]::IsNullOrEmpty($liquibaseClassPath)) {\n        $liquibaseArguments += \"--classpath=$liquibaseClassPath\"\n    }\n}\n\n# Check to see if liquibase path has been defined\nif ([string]::IsNullOrWhitespace($liquibaseExecutablePath)) {\n\n\tif ($env:IsContainer)\n    {\n    \t$liquibaseExecutablePath = \"/\"\t\n    }\n    else\n    {\n    \t# Assign root\n    \t$liquibaseExecutablePath = $PSSCriptRoot\n    }\n}\n\n# Get the executable location\nif ($IsWindows) {\n    $liquibaseExecutable = Get-ChildItem -Path $liquibaseExecutablePath -Recurse | Where-Object { $_.Name -eq \"liquibase.bat\" }\n}\n\nif ($IsLinux) {\n    $liquibaseExecutable = Get-ChildItem -Path $liquibaseExecutablePath -Recurse | Where-Object { $_.Name -eq \"liquibase\" }\n}\n\n# Add path to current session\n$env:PATH += \"$([IO.Path]::PathSeparator)$($liquibaseExecutable.Directory)\"\n\n# Check to make sure it was found\nif ([string]::IsNullOrEmpty($liquibaseExecutable)) {\n    # Could not find the executable\n    Write-Error \"Unable to find liquibase.bat in $PSScriptRoot or subfolders.\"\n}\n\n# Get connection Url\n$connectionUrl = Get-ConnectionUrl -DatabaseType $liquibaseDatabaseType -ServerPort $liquibaseServerPort -ServerName $liquibaseServerName -DatabaseName $liquibaseDatabaseName -QueryStringParameters $liquibaseQueryStringParameters\n\n# Add username\n$liquibaseArguments += \"--username=$liquibaseUsername\"\n\n# Determine authentication method\nswitch ($liquibaseAuthenticationMethod) {\n    \"azuremanagedidentity\" {\n        # SQL Server driver doesn't assign password\n        if ($liquibaseDatabaseType -ne \"SqlServer\") {\n            # Get login token\n            Write-Host \"Generating Azure Managed Identity token ...\"\n            $token = Invoke-RestMethod -Method GET -Uri \"http://169.254.169.254/metadata/identity/oauth2/token?api-version=2018-02-01&resource=https://ossrdbms-aad.database.windows.net\" -Headers @{\"MetaData\" = \"true\" } -UseBasicParsing\n\n            $liquibasePassword = $token.access_token\n            $liquibaseArguments += \"--password=`\"$liquibasePassword`\"\"\n        }\n    }\n    \"awsiam\" {\n        # Region is part of the RDS endpoint, extract\n        $region = ($liquibaseServerName.Split(\".\"))[2]\n\n        Write-Host \"Generating AWS IAM token ...\"\n        $liquibasePassword = (aws rds generate-db-auth-token --hostname $liquibaseServerName --region $region --port $liquibaseServerPort --username $liquibaseUsername)\n        $liquibaseArguments += \"--password=`\"$liquibasePassword`\"\"\n\n        break\n    }\n    \"gcpserviceaccount\" {\n        # Define header\n        $header = @{ \"Metadata-Flavor\" = \"Google\" }\n\n        # Retrieve service accounts\n        $serviceAccounts = Invoke-RestMethod -Method Get -Uri \"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/\" -Headers $header -UseBasicParsing\n\n        # Results returned in plain text format, get into array and remove empty entries\n        $serviceAccounts = $serviceAccounts.Split([Environment]::NewLine, [StringSplitOptions]::RemoveEmptyEntries)\n\n        # Retreive the specific service account assigned to the VM\n        $serviceAccount = $serviceAccounts | Where-Object { $_.Contains(\"iam.gserviceaccount.com\") }\n\n        Write-Host \"Generating GCP IAM token ...\"\n        # Retrieve token for account\n        $token = Invoke-RestMethod -Method Get -Uri \"http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/$serviceAccount/token\" -Headers $header -UseBasicParsing\n        \n        $liquibasePassword = $token.access_token\n        $liquibaseArguments += \"--password=`\"$liquibasePassword`\"\"\n    }\n    \"usernamepassword\" {\n        # Add password\n        $liquibaseArguments += \"--password=`\"$liquibasePassword`\"\"\n        \n        break\n    }\n}\n\n# Add connection url\n$liquibaseArguments += \"--url=`\"$connectionUrl`\"\"\n\n# Determine if the output variable needs to be set\nif ($liquibaseCommand.EndsWith(\"SQL\")) {\n    # Add the output variable as the command name\n    $liquibaseArguments += \"--outputFile=`\"$PSScriptRoot/artifacts/$($liquibaseCommand).sql`\"\"\n    \n    # Create the folder\n    if ((Test-Path -Path \"$PSScriptRoot/artifacts\") -eq $false) {\n        New-Item -Path \"$PSScriptRoot/artifacts\" -ItemType \"Directory\"\n    }\n}\n\n\n# Add the additional switches\nforeach ($liquibaseSwitch in $liquibaseAdditionalSwitches) {\n    $liquibaseArguments += $liquibaseSwitch\n}\n\nswitch ($liquibaseCommandStyle) {\n    \"legacy\" {\n        # Add the command to execute\n        $liquibaseArguments += $liquibaseCommand\n    }\n    \"modern\" {\n        # Insert the command at the beginning\n        $liquibaseArguments = @($liquibaseCommand) + $liquibaseArguments\n    }\n}\n\n# Add command arguments\n$liquibaseArguments += $liquibaseCommandArguments\n\n# Display what's going to be run\nif (![string]::IsNullOrWhitespace($liquibasePassword)) {\n    $liquibaseDisplayArguments = $liquibaseArguments.PSObject.Copy()\n    for ($i = 0; $i -lt $liquibaseDisplayArguments.Count; $i++) {\n        if ($null -ne $liquibaseDisplayArguments[$i]) {\n            if ($liquibaseDisplayArguments[$i].Contains($liquibasePassword)) {\n                $liquibaseDisplayArguments[$i] = $liquibaseDisplayArguments[$i].Replace($liquibasePassword, \"****\")\n            }\n        }\n    }\n    \n    Write-Host \"Executing the following command: $($liquibaseExecutable.FullName) $liquibaseDisplayArguments\"\n}\nelse {\n    Write-Host \"Executing the following command: $($liquibaseExecutable.FullName) $liquibaseArguments\"\n}\n\n\n# Check to see if it's running in a container (this variable is provided by the build of the container itself)\nif ($env:IsContainer)\n{\n\t# Download any additional drivers based on the database technology being deployed to\n    $driverPath = Get-DatabaseJar -DatabaseType $liquibaseDatabaseType\n\n    # Check to see if it's null\n    if ($null -ne $driverPath) {\n        # Create folder to hold jar files to override\n        New-Item -Path \"$PWD/liquibase_libs/\" -ItemType Directory    \n\n        # Copy contents into liquibase_libs folder\n        $driverPaths = $driverPath.Split([IO.Path]::PathSeparator)\n\n        foreach ($driver in $driverPaths) {\n            # Copy the items\n            $files = Get-ChildItem -Path $driver\n\n            foreach ($file in $files) {\n                Write-Host \"Copying $($file.FullName) to $PWD/liquibase_libs/$($file.Name)\"\n                Copy-Item -Path $file.FullName -Destination \"$PWD/liquibase_libs/$($file.Name)\"\n            }\n        }\n    }\n}\n\n\n\n# Declare variable to hold output from Tee-Object\n$liquibaseCommandOutput;\n\n# Redirection of stderr to stdout is done different on Windows versus Linux\nif ($IsWindows) {\n    $liquibaseArguments += \"2>&1\"\n    # Execute Liquibase\n    & $liquibaseExecutable.FullName $liquibaseArguments | Tee-Object -Variable liquibaseCommandOutput\n}\n\nif ($IsLinux) {\n    # Execute Liquibase\n    & $liquibaseExecutable.FullName $liquibaseArguments 2>&1 | Tee-Object -Variable liquibaseCommandOutput\n}\n\nSet-OctopusVariable -name \"LiquibaseCommandOutput\" -value $liquibaseCommandOutput\n\n# Check exit code\nif ($lastExitCode -ne 0) {\n    # Fail the step\n    Write-Error \"Execution of Liquibase failed!\"\n}\n\n# Check to see if there were any files output\nif ((Test-Path -Path \"$PSScriptRoot/artifacts\") -eq $true) {\n    # Loop through items\n    foreach ($item in (Get-ChildItem -Path \"$PSScriptRoot/artifacts\")) {\n        New-OctopusArtifact -Path $item.FullName -Name $item.Name\n    }\n}",
    "Octopus.Action.Script.Syntax": "PowerShell"
  },
  "Category": "Liquibase",
  "HistoryUrl": "https://github.com/OctopusDeploy/Library/commits/master/step-templates//opt/buildagent/work/75443764cd38076d/step-templates/liquibase-run-command.json",
  "Website": "/step-templates/36df3e84-8501-4f2a-85cc-bd9eb22030d1",
  "Logo": "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",
  "$Meta": {
    "Type": "ActionTemplate"
  }
}

History

Page updated on Tuesday, July 23, 2024