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.
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": "iVBORw0KGgoAAAANSUhEUgAAAMgAAADICAYAAACtWK6eAAAAAXNSR0IArs4c6QAAGvtJREFUeF7tXQuYHEW1/k/PJgEiEJSHBFTEkJ3eDc9gFJCQgIg8fAERNBJ2emJULr5QfOG9wqdXwU/Fz1wexkzvgqJiRIgCAUQNL0OQIGAys4kL5l5NlJdEAkqSnT73q97ZdXa2e7qqd3Yzu3Xq++bLl51zTtX5T/1T3VWnqghSBAFBIBYBEmwEAUEgHgEhiPQOQaAOAkIQ6R6CgBBE+oAgkA4BGUHS4SZaliAgBLEk0OJmOgSEIOlwEy1LEBCCWBJocTMdAkKQdLiJliUICEEsCbS4mQ4BIUg63ETLEgSEIJYEWtxMh4AQJB1uomUJAkIQSwItbqZDQAiSDjfRsgQBIYglgRY30yEgBEmHm2hZgoAQxJJAi5vpEBCCpMNNtCxBQAhiSaDFzXQICEHS4SZaliAgBLEk0OJmOgSEIOlwEy1LEBCCWBJocTMdAkKQdLiJliUICEEsCbS4mQ4BIUg63ETLEgSEIJYEWtxMh4AQJB1uomUJAkIQSwItbqZDQAiSDjfRsgQBIYglgRY30yEgBEmHW8O1DurgXSbvhhZl+KV/ondjF73c8ErEoDECQhBjyMwVpuV4n0mEGQEjS4RpzDgIhAMA7AvGq0DYHUBULLYC+DsDTxOwCYz/ZQc9VMZ6TMTa0hL6q3lrRMMEASGICVqastMW8oEtAd7qACcw8BYA0zRVTcU2MvAAgHvYwd3rl9KfTA2IfH0EhCAN6iHT5vMeEyZiPgjnADihQWbNzDAeBOHGHYwbejrpGTNlkY5CQAgyzH7R6vFUYnySCB8DMHGY5hqpflWmjCvXXkdPNNKobbaEIMOIuJvjT4JwBYAJwzAzsqqE/ywV6CsjW8n4tS4ESRHbmYt4wj97cQOAeSnUR12FgDuDXszvvp6eG/XKx3iFQpAUAXRzfBsIp6VQ3WkqRHig+AJOwDIq77RGjMGKhSCGQXNzfAkIY/KRhYBvFX36lKHLVosLQQzD73q8CcBUQ7VmEd++32sxeeWl1NssDWr2dghBDCI0fRHvnenFmJ4+zThoW7uUSgZuWy0qBDEMv+vxtiabzjXyoNyCfTYsoWeNlCwWFoIYBt/NcQEEz1CtOcQJy0sFendzNGZstEIIYhin6Qv4gEwLHhpz7yGMf8HBrFKB1hq6bLW4ECRF+NvzPIsZNzFwYAr1naGyFQHOKnXRL3dG5WO5TiFIyugdtpAP3BHgOwDek9LEaKndVQ7w8Q1d1D1aFY6neoQgw4ymm+NzQPgMgKOGaaqh6szoVmkw3T51NdSwZcaEIA0KeDbP73AY5zNwVoNMpjVzGxGuKxZoWZSBbAfP6e6ilWmN26YnBGlwxCtrJacR4xQmnAjg1Q2uotbccwz8hgh3Bozb1/u0Oao+tWNxVwdf4AC/FoLoR0QIoo9VKsnpHZx1gKMcB4cGQBsBhwA4CMCuhga3A9gI4I/MKJGDxwH8XmdWys3z6WBcAuAYDjBXCKKPvBBEH6uGSmYX8Ku4BXs7DvZCL3bnDHYhRgsHIHbQS4Dak761xcGW7Q6eSbO41+7x3IDxgep1GyGIWRiFIGZ4jQnpthx/ICDMJ+DttQ0WgpiFUAhihldTSrd38BuDDI5Vj1Dg8N/XxDVUCGIWQiGIGV5NId3ewUeEhGAcD2C2yaq+EMQshEIQM7x2inS7x4dzHxHUKSnq333SNkQIYoacEMQMr1GRbvsgtwcB5hIwFxxOFU9pVMVCEDMkhSBmeI2ItNvBh7CDuUQ4Hhyeo6WmgUeibCr5NFbyx0bCf2ObQhBjyIavcNiHed/e7Zij3iHYwVvAOGL4VrUsXFXy6UItSREKERCCjFJHcPM8A8BJxDiRgZMATB6lqvur+Xu5Ba1p1lNGuZ1NVZ0QZATDceA83nX3PZADYwGAN41gVYmmycHs4lK6L1FQBAYhIAQZgQ6hDqueAOQqK9itI1CFqclPlnz6tqmSyMsjVsP7gOvxJ8D4dOX09obbNzT4MAj/XSrQLYZ6Il5BQEaQBnWFcPHOwZcANMOe77uJcV2xk37QIPesNSMEaUDow1EDITkatl6Rolk9DKxwgBVFn1ZE6bfnuK3M2FeyefXRFYLoYxUp6Xp8MYCvD9NMWvVEUvQbrpD4Ig6wQAiiD7cQRB+rIZJtef4QM64dhok0qn9gYGW9kaLaqNvBJyODi8E4Wf1dVtLNIBeCmOE1IO3m+VwwfpRSXU+N0IsA9xOwKiCsQYA13V2kNk0llmyOzyDgbBDOrxYWgiRCN0hACGKGVyg97aM8qeUlrCbg8BTq9VS2gHAPAfcHjAcyW7Fm3TJSOwm1SqvHrQ6HpFD74o+MUhKCaEE5ICQEMcMrlM56fBEB30yhWquyBYA6QOEeJ8DKdV30qKnNtkX82qCMucThdQxnA3Dq2RCCmCEsBDHDC+pQhpZerGbgYENVJf4CgHsB/CotIUKC5vhYIpwUvleoBEeDIgQxAEtysczAqowel1LflK5OeSF8fwBWOQ5+nSbVI3yc24pj4ODNascgIUx/f4VO5VEygYPD1y8ldeCDFA0EZATRAKlapM3j7zKwqI6aOjn9ZgS4xdkN9667ml40qaJ1Ib8+U8ZxTDgGCEnRyAPpeko+qVNVpGgiIATRBKpfzPX4VgCnD1Ej3M6MW4IW3GySMRseC+SEuwRnU9+d6q8zbJK2OAOLu31St/FK0URACKIJVBVB1OPJof3/Z+CyDHDzOp8e0zGl0t6ZcSypwxUoPGBhtH7RJd1dJ0A1MkIQQ9Bcj9XM055grGTGZTqr0m05flNAOLVyDM9OSXuXdHfDQFfEhSCGuLkesxo1un26tJ5qM5Ciqn2S7m4Y535xIYghcPUOf271+GgC1Aq2OrBtp4wUNe6sUTfySrq7YZCrxIUg6bEb0HQ9fmuY0qGO+WyOsoaBJd0+LWmO5ozdVghBhhG7Vo93zwA+961g79xC6CXGcu67h/D7cY2R6w/MwiQEMcPr36NGntV07F1gTE9pojFqhPuYsTxDWL6uQD1xRttzfGJAUOnu39CZWGhM48a+FSFIihiqtYuMg5121zgB3QwsV59un1bVc+Gw83jfHRPxKXB4C5akuxvGWwhiCJgSdz1W9/2N5mEMzwH4NQirmPFgEilUG9X1CjQB54ChFgYH2iq5WGYBF4KY4aUyeU1ysQytV8T73id+BcLdKu1dhxD9FYWJjMB7QTgn6nYrIYhZSIQgZnip0eMnAOYZqiWJbwNjFRPuQYCVpu8IMxbyfr0BTgVwTtSdINWVC0GSQjH4eyGIGV5qBPkzDf9+9OcZWA31SUGI8BFqIc90GHO574BrtZ12go4rQhAdlP4tIwQxw0uNIJtM7uOomN8ECgnxEJex2nSEUDbUbsEM4ThmzAHhrWDsb9j0UJwDvF53224a++NNRwhiGNGsx8sJeKem2jIiLIu7krmejdY8H+cEYdr7cYQwqXFvzTrria0u+aRS6KVoIiAE0QSqXyzsuIz7Y9UI65jx0wzjJ+s6qahrvj3Ps8oBTgp3CvYdbt3w4jDaTdrU8AaMQYNCkBRBa8vzPGaol/WBQsDvQLi2WCBfx2S4lpIJdwfOBof7QVI9MunUpWScALPWddHvdOVFrg8BIUjKntCW5yOZ8QgIGxDgv0qddGPdRyaPd28B5gbqpbrvGrVG7hSsV/VTHODcNO89KaEZV2pCkGGEc+Yi3m3NEvpnnAl14gjvwOmgkBTq04j3CO0WE9BVdnCl7EHXhmyIoBAkPXaxmioh0MngXOZwsW7Uz+slxi+Y8J2ST3ePgHtWmRSCNDjcbo6PIoJ6R5kHwhsabL6euRUErCDCinpJi6PYnnFRlRBkBMMY5kO1hAc8qM+7AExqYHVrAKgRYnW5Fw9tuJ7U+oyUBiMgBGkwoPXMhY9ehD1ZfYA9Sf0b9P2r9rkTwr8TAVuhPgx1ZNDWgPAsOdhEATb1ApuDydjUs5i2jWLTra1KCGJt6MVxHQSEIDooiYy1CAhBrA29OK6DgBBEByWRsRYBIYi1oRfHdRAQguigJDLWIiAEsTb04rgOAkIQHZRExloEhCDWhl4c10FACKKDkshYi4AQxNrQi+M6CAhBdFASGWsREIJYG3pxXAcBIYgOSiJjLQJCEGtDL47rICAE0UFJZKxFQAhibejFcR0EhCA6KImMtQgIQZos9G6Of0MOtnKAkuPge3IAw84NkBBk5+I/pHZFEBDm9H9BwMeKPi1usmZa0xwhSJOFupYgqnmBg8Pl8LedEyhyPWYAywA82TIJV/zhGnq+UU2pnGG7CISZHKDHIXzfxl9D1+OLAbwPgLr4czUTruku0C+icI4iiLostOTTKY2Ki9jRR6CfIP0af2MHZ3QvJXXm0rCKm+OPgHB1rREGFnf7pO7Ns6K0edzJQEets+TgvOJS+kHt32MIIqPITuottQQJm7GtBVOeXEL/GE6bXI//GnVHXvjIAGTX+7R+OPbHgm5bjt/EhAdj2rq+5FNWlyAgLKh3//lYwGMstjGSIAx0dvvkpXWovYOPCBz8Pk6fGF6xkzrT2h8relmPLyLgm3HtjbrtKW4EYeCybp8uHSu+j5d2RhJEOcfA2d0+3ZTGUXVdmAOoq5KjC+PcpOsC0tTbbDptHn+YgWvi2jVhIvZ7/Fp6uvp7IUhzRbEeQb7a7dMlaZvrevwIgCNr9Rkooxf7dV9P6u7vcV1mnM9vKGfQE+UkAb8p+qQu0BlUhCDN1SViCQLgtpJPZ6RtrtvBJ8PBzwHsUmPjwpJPV6W1O9b0sh5/joCv1bT7OWKcXuwkdbGnEKSJgxpPEMbKUiepS19Sl9aF/PpMOZzBOZId9FCAG6M6ReoKxohiNscnOISzmPBaAA87ZSxd10V/i2q+jCDNFdQRJUhzuTo2WlOHIJd2+3TZ2PBi/LRyTBFEXWmGHdi/TNgywcGWF3vxj41d9PL4CQegO4Ic0cFT/tWCvTKMKcQI1vn02EjhoK6ae2k7ZtFErC8tITV9PyJl+iLee0IZBzOwQ8V41148/2gXbWlEZe3zeGJ5MqbCwf4I8CICbNZ5Dx4xgrge/xDAwVHO6d7VPS3H+0wEzmDCLCC8EXZ6rT0GuhDgWwBeRYQvRdYX8aiY9fhSYpygK98vF3bgiMKEe6KmYV2P49ZB1pR8+g/TdxA3x58BYT6Aw2p0nwkv1CGsJuDeYoFip9mTOlz7BfwK/hfmVXBX2FdfOKrqUWtYN5V8+nZaHFUbWj2eSsC5BLwnvI2LI2/6Vf4sLvp0Q1K7a7/P5vgMIrwbhDeD0R6hr8i3koHHerfhWz030Au1MiNNEJVeUVtKJZ/akpx183wBAlyke40ZMX7IhPfHEHJIzlkYWMQQyld32ESXSmrOkC/j1inqLJhebUoQAhShdC4CfQmEy0sF+koSzkMImufZCHBF2KmSy1MMXBuJY8I7rOuxmqg5F8Ark6sJJVZkWvDRtUvoiST59hy3sYPLmfGOJNmB7wnrwPh6yafrq3WakiBxjxnaztYIliI6/FgjSCrfGQ+WOukYXd16mOjaGJCrQxDXY7U29GFjm8BvHcI71hXo73G6ihwB4SEAk1PYV+t/g971mo4gbp57wI29/NJaggAg4C9Fn16T1FniRsYkvdjvYwji5vkrYKReXwNhealA746qN3GBWtMZIry3WCCVwIumIojr8QIA12n6oS1mM0HCIBMuLhboG3GAuR7/BMA8bUB1BOMI4vEGAIdEmmCoi0j/CMJBQPiJLMR4c+Qakse/BaA9YtZzQz2edXfSrU1DkOkdnM04KCVgv4aAMNOYgZno+ySWcUqQzURYEzAecQhHMYdYTI0Fg3BGqUC31X5f2ZKgCBJXngLwGAOrtOrptxJBkIMX8Z6TehE5K0WEXxQL9M5+9XrtIsbHi530neoGZz1eRMB3Y5zYzMD3GLh10g6UXiZMcRwcQg5OA6C2Igwp/e1pGoK4Hv8MajYjujzOwMXdPt01CJS+WQoFSnzHADDeCELAkqJPHxrS2T3+LgOLYjDs2daCo2uztN16v7qEi0oFutKwnj7xCIK053lWwBiSPaDECfhA7UxV3IwhOdhcLJCayRsorscPR/1gMnBHSxkXrr0u+uW+Xr6cQzi1KQhy2Hk8eccEqF+qoS9WhK+XCvTZesNEXN5Xv864IkiAt5W66JdxeFRSfAb9kAzI1owibXk+khkqZy6qnFny6eZU9cQQZEaOX1Mm/F+MzdUgXMVl3NfdRRvrxTuCsKcycHuEzrOTAhyStJbienwngLfV6hNweVMQJJvjU4hwR0QD7yz69PYksGYs4jeUe/E4gN2iZMcLQVTAij59PgmPNo+/xsDnogJerd+W4xwT/Ai5rqJPubT1xI0g6u+ux+o9o+6IDzXlGuAucrCqhbDq8aX0l3ptyXr8A0K4NjSoqKn3JB/6v4+bqm4Kgrg5/jIIX4wI1KeLPsXup6iWdz1W89fnjWeC6O5Nb13IhzkBolbW7y/5dHw/Rm6erwbjI7WYOYz2dZ1UTOpcdeqJfMRS9to8/ikDZyXZrvl+FYBra9coqvxYG7MQaFjNEIY90SwEGXSSx0AzCe8rFejHOl66Hn8CwJDnZaU7TkaQp0o+vVoHi8ovtUqG3K9WvhoL12M16h5aI7O55NMBw60n6h1E2Tz0I7xXeRvuZOCNunX0y6n3CWqBV5vu4nqsdr/uYWpPQ35bUxOEgVNqX8zjnKqkFUQehDBOCKJSU47WCGooEvfSWkMQNaO0Z41Ns3ry/HswjhjSrjoLhTMWslsOwkdANa1vVAi4qejT2dVKrscqRWR3I0Oawk1NEJOtuaYr46byA8N53ykwEf0hektso1JNVIU7tmHPqHyh2sZMm897TJiEyDMFaghyK4DTa/V161EJk9scRJ+Co7Fdoj3Pbw8Y7yPgRAYO1Oyzaop/0PZj12OVGzYkT0+NYro24+SagiBxJ3/ULvvXc7bN4zvUiBMl06gRpN4z90jnYim/dLdBZz0+i4CfDsGC8GipQAO7PNvy/HlmfLVWTreedo/fGQDLI+OiQZBqPXWOQdnBLAJmgXEy+vbORBfCfaUCzR740ao5bK//78z4RncnRa5z6BKnWQgSu3db5zGrLceLmXBhnNOmBAkIb1lfoAdq7dUbdUaDIACeK/mUmKzoevysym6ubT8BlxR9GiBEm8dx06O69agp2+g0FkOCVLc1XFDcgfdHHRvVLzcpwF7907fZPH+eIogO4KkycOwGn57UJcQQzGJzcBgrmfWnyZTh7i4aGNIq6e5a2byV+fh7Abwi8vHFwdFxZ3XV/RWrGIsiSL2VWgZ+vkuA86vnzyttVI8kkVOUo0QQtaD2wPZtOC3qUUs9Wk2chNsZOE4Hx/YOfnXgIHJ/R716Zizk/coB1FpLbcr9v6utIUjlvSNuZizyvadeCowT4Mh1XfSoqjDr8dsIUGsZQwvjxlInqazhyJKQSXBmvT3pZqSrAcSEIKqiuOG+vxFq9ZgJ96uFJPU3yuB49O3nyCc1NHIEWcgzKYBafY0uhEeJcQcIjzCHj26K7JHrLMrAaBGk0thniXBFUMbD6kcp28FznAyOZoZaUI0cYeJW312P/wd9afRRZXA9Hh9DfXsr1PpC/ZfiiBGkXpY2B5hb/QOrGuN6/KeYnKwtJZ/2qm5wW55/Xie9fRkDV3b7pKaLw6JIHjBmMyMuzSbcltE0BAkByfO9YAzM0yd1fN3vowiipht7tyE2bVrXdr/cKBPEtHkvEmF23CaqEZkFiiJInr8IxpdjGh/mSxHhUQSYToRZceslaoTv9uld1XbqzWJWyalFSrXoqKa/Y5Mhwx/gyuNoUxGkzjOxaYcYJB9FkAohrwDjM8MyXlFuZoIQ4QvFAtWerDLgdkKiXzp4IghSmeRYkbiSnlBjHNYN3M+yrOTTe0OiNGwfwDAfsfoxiTkmJ12QKlpxBFF7oDO9uF/t/tSuQE0dVl1P0OwjCAFaaSOuxyrvKnKfhTY21YIxL+mtOT7bofCw9HSFcE2pQBfEKbs5XgjC99IZD7UGyNGUBAl/2fv2hahfvPo5O5ooxBFEqVeG5sSMYABbiLCIA1wwVgjCgNHhf60ez3UAlVU9RRPaeLF6Owrz/FlwuN15V6N6CDeWCvEv3P221HFTThCS5CQD++rwj66ST4NSb0Z6BDkzooFPau1JX8T7cy8+5ADncczhD1W21UtYMc0ec2WjPc/TAobaX3BqDKC3OAEuU7MmuqeO9NupLBQOeqGsfFdIsSdd7eVP2ti0lYAfBQ6WpDml/6AOnrJLBpcTY0g6fQQ2tzHwcJo96dMX8AGZDObHHEAxUBUD6mhWlW704+qXbJ2O7+b5Cma8n+ovQv5NjbK9Aa7b0EVDjssdExfoqGk8hzEHhP0ZmMrAy0R4mhlPw8HPVEdIuzJeDbQiCnO4221a5e89EwOsSkqX1glWo2SyC3kmApzpAHszhzNWrwThrwRsDhhrmHDrep+2Drc+dcRS0IssEVwwsuGHoE40eQaE59UMX9En9Xg67KImTHbswMEOh0f+HEyMfxBh444yNm4HNg73aKfsB3k6ejEdFD6RTCXCE1zGn1sm4s8vT8JfehbTtjgnxgRBdCLQCILo1CMydiEgBLEr3uKtIQJCEEPARNwuBIQgdsVbvDVEQAhiCJiI24WAEMSueIu3hggIQQwBE3G7EBCC2BVv8dYQgXFDEHchn4YAQ04OVHjUSzUxxEvELUNg3BAk28EHkQO1f2BIEYJY1qsb6O64IYjCJO6EPCFIA3uMZabGFUFUnlLULkEhiGW9uoHujiuCKFwqe9QL1VtPhSAN7DGWmRp3BOmP38DdeYQ5QhDLenUD3R23BGkgRmLKYgSEIBYHX1xPRkAIkoyRSFiMgBDE4uCL68kICEGSMRIJixEQglgcfHE9GQEhSDJGImExAkIQi4MvricjIARJxkgkLEZACGJx8MX1ZASEIMkYiYTFCAhBLA6+uJ6MgBAkGSORsBgBIYjFwRfXkxEQgiRjJBIWIyAEsTj44noyAkKQZIxEwmIEhCAWB19cT0ZACJKMkUhYjIAQxOLgi+vJCAhBkjESCYsREIJYHHxxPRkBIUgyRiJhMQJCEIuDL64nIyAEScZIJCxGQAhicfDF9WQEhCDJGImExQgIQSwOvriejIAQJBkjkbAYASGIxcEX15MREIIkYyQSFiMgBLE4+OJ6MgJCkGSMRMJiBIQgFgdfXE9G4P8B14ctMDPQ3L4AAAAASUVORK5CYII=",
"$Meta": {
"Type": "ActionTemplate"
}
}
Page updated on Tuesday, July 23, 2024