From 6cd742db4e1f07cc7210238a68989df2bdf2da3e Mon Sep 17 00:00:00 2001 From: Florian Date: Tue, 26 Oct 2021 18:46:30 +0100 Subject: [PATCH 01/21] Fix function call following refactoring --- powershell/Invoke-ActivateAlteryx.ps1 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/powershell/Invoke-ActivateAlteryx.ps1 b/powershell/Invoke-ActivateAlteryx.ps1 index 687fc09..f82736a 100644 --- a/powershell/Invoke-ActivateAlteryx.ps1 +++ b/powershell/Invoke-ActivateAlteryx.ps1 @@ -16,7 +16,7 @@ function Invoke-ActivateAlteryx { File name: Invoke-ActivateAlteryx.ps1 Author: Florian Carrier Creation date: 2021-07-05 - Last modified: 2021-08-30 + Last modified: 2021-10-26 .LINK https://www.powershellgallery.com/packages/PSAYX @@ -46,7 +46,7 @@ function Invoke-ActivateAlteryx { # Get global preference variables Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState # License utility - $LicenseUtility = Get-AlteryxLicenseUtility -Path (Join-Path -Path $Properties.InstallationPath -ChildPath "bin") + $LicenseUtility = Get-AlteryxUtility -Utility "License" -Path $Properties.InstallationPath } Process { Write-Log -Type "INFO" -Message "Activating Alteryx licenses" From 96e88dab8be450575bb36d1959d5d4bc1d4d7447 Mon Sep 17 00:00:00 2001 From: Florian Date: Mon, 1 Nov 2021 18:13:22 +0000 Subject: [PATCH 02/21] Add check for licensing system connectivity --- conf/default.ini | 4 +- powershell/Invoke-ActivateAlteryx.ps1 | 89 +++++++++++++++------------ 2 files changed, 52 insertions(+), 41 deletions(-) diff --git a/conf/default.ini b/conf/default.ini index bb32719..a62e17d 100644 --- a/conf/default.ini +++ b/conf/default.ini @@ -35,11 +35,13 @@ InstallationOptions = install.ini # Installation language Language = English # Version -Version = 2021.3.2.54175 +Version = 2021.3.3.63061 # SSL/TLS EnableSSL = false [License] +# Licensing system URL +LicensingURL = whitelist.alteryx.com # License file LicenseFile = # License email diff --git a/powershell/Invoke-ActivateAlteryx.ps1 b/powershell/Invoke-ActivateAlteryx.ps1 index f82736a..de73774 100644 --- a/powershell/Invoke-ActivateAlteryx.ps1 +++ b/powershell/Invoke-ActivateAlteryx.ps1 @@ -16,7 +16,7 @@ function Invoke-ActivateAlteryx { File name: Invoke-ActivateAlteryx.ps1 Author: Florian Carrier Creation date: 2021-07-05 - Last modified: 2021-10-26 + Last modified: 2021-11-01 .LINK https://www.powershellgallery.com/packages/PSAYX @@ -49,51 +49,60 @@ function Invoke-ActivateAlteryx { $LicenseUtility = Get-AlteryxUtility -Utility "License" -Path $Properties.InstallationPath } Process { - Write-Log -Type "INFO" -Message "Activating Alteryx licenses" - if ($PSCmdlet.ShouldProcess("Alteryx", "Activate")) { - # Check license key(s) - if (Test-Object -Path $Properties.LicenseFile -NotFound) { - Write-Log -Type "ERROR" -Message "License file path not found $($Properties.LicenseFile)" -ExitCode 1 - } - $Keys = Get-Content -Path $Properties.LicenseFile - if ($Keys.Count -gt 1) { - $Success = "$($Keys.Count) licenses were successfully activated" - $Failure = "Licenses could not be activated" - $Keys = $Keys -join " " - } elseif ($Keys.Count -eq 1) { - $Success = "$($Keys.Count) license was successfully activated" - $Failure = "License could not be activated" - } else { - Write-Log -Type "ERROR" -Message "No license key was provided" -ExitCode 1 - } - # Check email address - if ($null -eq $Properties.LicenseEmail) { - if ($Unattended) { - Write-Log -Type "ERROR" -Message "No email address provided for license activation" - Write-Log -Type "WARN" -Message "Retrieving email address associated with current session through Windows Active Directory" - $Email = Get-ADUser -Identity $env:UserName -Properties "mail" | Select-Object -ExpandProperty "mail" - Write-Log -Type "DEBUG" -Message $Email + Write-Log -Type "INFO" -Message "Activating Alteryx license" + # Check licensing system connectivity + Write-Log -Type "INFO" -Message "Checking licensing system connectivity" + Write-Log -Type "DEBUG" -Message $Properties.LicensingURL + if ((Test-HTTPStatus -URI $Properties.LicensingURL) -eq $true) { + # Activate license + if ($PSCmdlet.ShouldProcess("Alteryx", "Activate")) { + # Check license key(s) + if (Test-Object -Path $Properties.LicenseFile -NotFound) { + Write-Log -Type "ERROR" -Message "License file path not found $($Properties.LicenseFile)" -ExitCode 1 + } + $Keys = Get-Content -Path $Properties.LicenseFile + if ($Keys.Count -gt 1) { + $Success = "$($Keys.Count) licenses were successfully activated" + $Failure = "Licenses could not be activated" + $Keys = $Keys -join " " + } elseif ($Keys.Count -eq 1) { + $Success = "$($Keys.Count) license was successfully activated" + $Failure = "License could not be activated" + } else { + Write-Log -Type "ERROR" -Message "No license key was provided" -ExitCode 1 + } + # Check email address + if ($null -eq $Properties.LicenseEmail) { + if ($Unattended) { + Write-Log -Type "ERROR" -Message "No email address provided for license activation" + Write-Log -Type "WARN" -Message "Retrieving email address associated with current session through Windows Active Directory" + $Email = Get-ADUser -Identity $env:UserName -Properties "mail" | Select-Object -ExpandProperty "mail" + Write-Log -Type "DEBUG" -Message $Email + } else { + # Prompt for email address and validate format + do { + $Email = Read-Host -Prompt "Please enter the email address for license activation" + } until ($Email -as [System.Net.Mail.MailAddress]) + } + } else { + $Email = $Properties.LicenseEmail + } + # Call license utility + $Activation = Add-AlteryxLicense -Path $LicenseUtility -Key $Keys -Email $Email + # Check activation status + if (Select-String -InputObject $Activation -Pattern "License(s) successfully activated." -SimpleMatch -Quiet) { + Write-Log -Type "CHECK" -Message $Success } else { - # Prompt for email address and validate format - do { - $Email = Read-Host -Prompt "Please enter the email address for license activation" - } until ($Email -as [System.Net.Mail.MailAddress]) + # Output error and stop script + Write-Log -Type "ERROR" -Message $Activation + Write-Log -Type "ERROR" -Message $Failure -ExitCode 1 } } else { - $Email = $Properties.LicenseEmail - } - # Call license utility - $Activation = Add-AlteryxLicense -Path $LicenseUtility -Key $Keys -Email $Email - # Check activation status - if (Select-String -InputObject $Activation -Pattern "License(s) successfully activated." -SimpleMatch -Quiet) { Write-Log -Type "CHECK" -Message $Success - } else { - # Output error and stop script - Write-Log -Type "ERROR" -Message $Activation - Write-Log -Type "ERROR" -Message $Failure -ExitCode 1 } } else { - Write-Log -Type "CHECK" -Message $Success + Write-Log -Type "ERROR" -Message "Unable to reach licensing system" + Write-Log -Type "WARN" -Message "Skipping license activation" } } } \ No newline at end of file From 1e0daaa1b5a83f952a712f797f6fa70be9f1d29c Mon Sep 17 00:00:00 2001 From: Florian Date: Mon, 1 Nov 2021 18:17:19 +0000 Subject: [PATCH 03/21] Disable data packages by default --- conf/install.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/install.ini b/conf/install.ini index 049fdce..770a44a 100644 --- a/conf/install.ini +++ b/conf/install.ini @@ -2,4 +2,4 @@ Server = true PredictiveTools = true IntelligenceSuite = true -DataPackages = true \ No newline at end of file +DataPackages = false \ No newline at end of file From 928a74ebf41da3882a8b43a88585cfd7d7246fb2 Mon Sep 17 00:00:00 2001 From: Florian Date: Mon, 1 Nov 2021 18:17:55 +0000 Subject: [PATCH 04/21] Clear error pipeline --- powershell/Update-Alteryx.ps1 | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/powershell/Update-Alteryx.ps1 b/powershell/Update-Alteryx.ps1 index 0cf905a..8aa3fdf 100644 --- a/powershell/Update-Alteryx.ps1 +++ b/powershell/Update-Alteryx.ps1 @@ -10,7 +10,7 @@ function Update-Alteryx { File name: Update-Alteryx.ps1 Author: Florian Carrier Creation date: 2021-09-02 - Last modified: 2021-09-10 + Last modified: 2021-11-01 #> [CmdletBinding ( SupportsShouldProcess = $true @@ -43,7 +43,8 @@ function Update-Alteryx { Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState # Retrieve Alteryx Service utility path $AlteryxService = Get-AlteryxServerProcess -Process "Service" -InstallDirectory $Properties.InstallationPath - # Define error counter + # Clear error pipeline + $Error.Clear() } Process { Write-Log -Type "CHECK" -Object "Starting Alteryx Server upgrade to $($Properties.Version)" @@ -59,7 +60,7 @@ function Update-Alteryx { Install-Alteryx -Properties $Properties -InstallationProperties $InstallationProperties -Unattended:$Unattended # Check for errors if ($Error.Count -gt 0) { - Write-Log -Type "ERROR" -Object "Upgrade process failed with $($Errors.Count) errors" + Write-Log -Type "ERROR" -Object "Upgrade process failed with $($Error.Count) errors" Write-Log -Type "WARN" -Object "Restoring previous version ($BackupVersion)" # Overwrite target version $Properties.Version = $BackupVersion From c4e9c6f77307c1e4a883f35c6bbb2ca8c13b21b8 Mon Sep 17 00:00:00 2001 From: Florian Date: Mon, 1 Nov 2021 18:18:14 +0000 Subject: [PATCH 05/21] Update documentation --- Deploy-Alteryx.ps1 | 85 +++++++++++++++++++++++++--------------------- README.md | 26 +++++++++++--- 2 files changed, 68 insertions(+), 43 deletions(-) diff --git a/Deploy-Alteryx.ps1 b/Deploy-Alteryx.ps1 index 62f45da..f408e29 100644 --- a/Deploy-Alteryx.ps1 +++ b/Deploy-Alteryx.ps1 @@ -3,14 +3,15 @@ <# .SYNOPSIS - Setup Alteryx + Deploy Alteryx .DESCRIPTION - Setup and configure Alteryx + Deploy and configure Alteryx .PARAMETER Action The action parameter corresponds to the operation to perform. - Eight options are available: + + Ten options are available: - backup: backup the Alteryx application database - configure: configure the Alteryx application - install: install the Alteryx application @@ -29,7 +30,7 @@ File name: Deploy-Alteryx.psm1 Author: Florian Carrier Creation date: 2021-06-13 - Last modified: 2021-09-10 + Last modified: 2021-11-01 Dependencies: - PowerShell Tool Kit (PSTK) - Alteryx PowerShell Module (PSAYX) @@ -66,7 +67,7 @@ Param ( "uninstall", "upgrade" )] - [String] + [System.String] $Action, [Parameter ( Position = 2, @@ -80,7 +81,7 @@ Param ( Mandatory = $false, HelpMessage = "Database backup path" )] - [String] + [System.String] $BackupPath, [Parameter ( Position = 4, @@ -102,14 +103,14 @@ Param ( Begin { # ---------------------------------------------------------------------------- - # Global preferences + # * Global preferences # ---------------------------------------------------------------------------- $ErrorActionPreference = "Stop" - $DebugPreference = "Continue" + $DebugPreference = "SilentlyContinue" Set-StrictMode -Version Latest # ---------------------------------------------------------------------------- - # Global variables + # * Global variables # ---------------------------------------------------------------------------- # General $ISOTimeStamp = Get-Date -Format "yyyyMMdd_HHmmss" @@ -121,28 +122,34 @@ Begin { $CustomProperties = "custom.ini" # ---------------------------------------------------------------------------- - # Modules + # * Modules # ---------------------------------------------------------------------------- - # List all required modules - $Modules = @("PSTK", "PSAYX") - foreach ($Module in $Modules) { - try { - # Check if module is installed - Import-Module -Name "$Module" -ErrorAction "Stop" -Force - Write-Log -Type "CHECK" -Object "The $Module module was successfully loaded." - } catch { - # Otherwise check if package is available locally - try { - Import-Module -Name (Join-Path -Path $LibDirectory -ChildPath "$Module") -ErrorAction "Stop" -Force - Write-Log -Type "CHECK" -Object "The $Module module was successfully loaded from the library directory." - } catch { - Throw "The $Module library could not be loaded. Make sure it has been made available on the machine or manually put it in the ""$LibDirectory"" directory" - } - } - } + # Dependencies + $Modules = [Ordered]@{ + "PSTK" = "1.2.4" + "PSAYX" = "1.0.0" + } + # Load modules + foreach ($Module in $Modules.GetEnumerator()) { + try { + # Check if package is available locally + Import-Module -Name (Join-Path -Path $LibDirectory -ChildPath $Module.Name) -MinimumVersion $Module.Value -ErrorAction "Stop" -Force + $Version = (Get-Module -Name $Module.Name).Version + Write-Log -Type "CHECK" -Object "The $($Module.Name) module (v$Version) was successfully loaded from the library directory." + } catch { + try { + # Otherwise check if module is installed + Import-Module -Name $Module.Name -MinimumVersion $Module.Value -ErrorAction "Stop" -Force + $Version = (Get-Module -Name $Module.Name).Version + Write-Log -Type "CHECK" -Object "The $($Module.Name) module (v$Version) was successfully loaded." + } catch { + Throw "The $($Module.Name) module (v$($Module.Value)) could not be loaded. Make sure it has been installed on the machine or packaged in the ""$LibDirectory"" directory" + } + } + } # ---------------------------------------------------------------------------- - # Script configuration + # * Script configuration # ---------------------------------------------------------------------------- # General settings $Properties = Get-Properties -File $DefaultProperties -Directory $ConfDirectory -Custom $CustomProperties @@ -159,7 +166,7 @@ Begin { Write-Log -Type "DEBUG" -Message $PSCmdlet.MyInvocation.Line # ------------------------------------------------------------------------------ - # Checks + # * Checks # ------------------------------------------------------------------------------ # Ensure shell is running as 64 bit process if ([Environment]::Is64BitProcess -eq $false) { @@ -167,7 +174,7 @@ Begin { } # ---------------------------------------------------------------------------- - # Functions + # * Functions # ---------------------------------------------------------------------------- # Load PowerShell functions $Functions = Get-ChildItem -Path $Properties.PSDirectory @@ -178,7 +185,7 @@ Begin { } # ---------------------------------------------------------------------------- - # Variables + # * Variables # ---------------------------------------------------------------------------- # (Re)load environment variables # Write-Log -Type "DEBUG" -Message "Load environment variables" @@ -188,7 +195,7 @@ Begin { # } # ---------------------------------------------------------------------------- - # Options + # * Options # ---------------------------------------------------------------------------- # Installation properties $ValidateSet = @( @@ -211,17 +218,17 @@ Begin { Process { # Check operation to perform switch ($Action) { - "activate" { Invoke-ActivateAlteryx -Properties $Properties -Unattended:$Unattended } - "backup" { Invoke-BackupAlteryx -Properties $Properties -Unattended:$Unattended } + "activate" { Invoke-ActivateAlteryx -Properties $Properties -Unattended:$Unattended } + "backup" { Invoke-BackupAlteryx -Properties $Properties -Unattended:$Unattended } "install" { Install-Alteryx -Properties $Properties -InstallationProperties $InstallationProperties -Unattended:$Unattended } - "restart" { Invoke-RestartAlteryx -Properties $Properties -Unattended:$Unattended } - "restore" { Invoke-RestoreAlteryx -Properties $Properties -Unattended:$Unattended } + "restart" { Invoke-RestartAlteryx -Properties $Properties -Unattended:$Unattended } + "restore" { Invoke-RestoreAlteryx -Properties $Properties -Unattended:$Unattended } "show" { Show-Configuration -Properties $Properties -InstallationProperties $InstallationProperties } - "start" { Invoke-StartAlteryx -Properties $Properties -Unattended:$Unattended } - "stop" { Invoke-StopAlteryx -Properties $Properties -Unattended:$Unattended } + "start" { Invoke-StartAlteryx -Properties $Properties -Unattended:$Unattended } + "stop" { Invoke-StopAlteryx -Properties $Properties -Unattended:$Unattended } "uninstall" { Uninstall-Alteryx -Properties $Properties -InstallationProperties $InstallationProperties -Unattended:$Unattended } "upgrade" { Update-Alteryx -Properties $Properties -InstallationProperties $InstallationProperties -Unattended:$Unattended } - default { Write-Log -Type "ERROR" -Message """$Action"" operation is not supported" -ExitCode 1 } + default { Write-Log -Type "ERROR" -Message """$Action"" operation is not supported" -ExitCode 1 } } } diff --git a/README.md b/README.md index 2c68b83..d61645e 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,28 @@ # Alteryx Deploy -Alteryx automated deployment utility +Alteryx automated deployment utility. + +## Usage + +1. Check the `default.ini` configuration file located under the `conf` folder; +2. If needed, add custom configuration to the `custom.ini` configuration file in the same configuration folder; +3. Update the installation configuration in the file `install.ini`; +4. Run the `Deploy-Alteryx.ps1` script with the corresponding action parameter; + - backup: backup the Alteryx application database + - configure: configure the Alteryx application + - install: install the Alteryx application + - restart: restart the Alteryx application + - restore: restore a backup of the Alteryx application database + - show: display the script configuration + - start: start the Alteryx application + - stop: stop the Alteryx application + - uninstall: uninstall the Alteryx application + - upgrade: upgrade the Alteryx application +5. Check the logs. ## Dependencies -This module depends on the usage of functions provided by two modules: +This module depends on the usage of functions provided by two PowerShell modules: -1. PowerShell Tool Kit (PSTK) module -2. Alteryx PowerShell (PSAYX) module +1. [PowerShell Tool Kit (PSTK) module (version 1.2.4)](https://www.powershellgallery.com/packages/PSTK) +2. [Alteryx PowerShell (PSAYX) module (version 1.0.0)](https://www.powershellgallery.com/packages/PSAYX) From 06951e7e0bce1a22d96a9d7b0b929da395535c56 Mon Sep 17 00:00:00 2001 From: Florian Date: Mon, 15 Nov 2021 00:18:27 +0000 Subject: [PATCH 06/21] Fix conflict with version parameter --- Deploy-Alteryx.ps1 | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Deploy-Alteryx.ps1 b/Deploy-Alteryx.ps1 index f408e29..7fbd860 100644 --- a/Deploy-Alteryx.ps1 +++ b/Deploy-Alteryx.ps1 @@ -30,7 +30,7 @@ File name: Deploy-Alteryx.psm1 Author: Florian Carrier Creation date: 2021-06-13 - Last modified: 2021-11-01 + Last modified: 2021-11-10 Dependencies: - PowerShell Tool Kit (PSTK) - Alteryx PowerShell Module (PSAYX) @@ -106,7 +106,7 @@ Begin { # * Global preferences # ---------------------------------------------------------------------------- $ErrorActionPreference = "Stop" - $DebugPreference = "SilentlyContinue" + # $DebugPreference = "SilentlyContinue" Set-StrictMode -Version Latest # ---------------------------------------------------------------------------- @@ -134,14 +134,14 @@ Begin { try { # Check if package is available locally Import-Module -Name (Join-Path -Path $LibDirectory -ChildPath $Module.Name) -MinimumVersion $Module.Value -ErrorAction "Stop" -Force - $Version = (Get-Module -Name $Module.Name).Version - Write-Log -Type "CHECK" -Object "The $($Module.Name) module (v$Version) was successfully loaded from the library directory." + $ModuleVersion = (Get-Module -Name $Module.Name).Version + Write-Log -Type "CHECK" -Object "The $($Module.Name) module (v$ModuleVersion) was successfully loaded from the library directory." } catch { try { # Otherwise check if module is installed Import-Module -Name $Module.Name -MinimumVersion $Module.Value -ErrorAction "Stop" -Force - $Version = (Get-Module -Name $Module.Name).Version - Write-Log -Type "CHECK" -Object "The $($Module.Name) module (v$Version) was successfully loaded." + $ModuleVersion = (Get-Module -Name $Module.Name).Version + Write-Log -Type "CHECK" -Object "The $($Module.Name) module (v$ModuleVersion) was successfully loaded." } catch { Throw "The $($Module.Name) module (v$($Module.Value)) could not be loaded. Make sure it has been installed on the machine or packaged in the ""$LibDirectory"" directory" } From f6a6a6e435e0847d91466e302743d294770a27c3 Mon Sep 17 00:00:00 2001 From: Florian Date: Mon, 15 Nov 2021 00:18:42 +0000 Subject: [PATCH 07/21] Update README --- README.md | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) diff --git a/README.md b/README.md index d61645e..fd03af9 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,21 @@ Alteryx automated deployment utility. +## Table of contents + +- [Usage](#usage) +- [Process](#process) + - [Installation](#installation) + - [Upgrade](#upgrade) + - [Uninstallation](#uninstallation) + - [Activate](#activate) + - [Backup](#backup) + - [Restore](#restore) + - [Start](#start) + - [Stop](#stop) + - [Restart](#restart) +- [Dependencies](#dependencies) + ## Usage 1. Check the `default.ini` configuration file located under the `conf` folder; @@ -20,6 +35,133 @@ Alteryx automated deployment utility. - upgrade: upgrade the Alteryx application 5. Check the logs. +## Process + +Below are the execution steps of the `Deploy-Alteryx.ps1` script. + +### Installation + +Below are the steps to install the Alteryx application. + +```powershell +Deploy-Alteryx.ps1 -action "install" +``` + +1. Install Alteryx Server (or Designer if specified with the `-Product` parameter; +2. Install Predictive Tools (if enabled); +3. Install Intelligence Suite (if enabled); +4. Install Data packages (if enabled). + +### Upgrade + +Below are the steps to upgrade the Alteryx application. + +```powershell +Deploy-Alteryx.ps1 -action "upgrade" +``` + +1. Backup Alteryx database and configuration files; +2. Upgrade Alteryx Server (or Designer if specified with the `-Product` parameter; +3. Install Predictive Tools (if enabled); +4. Install Intelligence Suite (if enabled); +5. Install Data packages (if enabled); +6. Check installation status and rollback if errors occurred. + +### Uninstallation + +Below are the steps to uninstall the Alteryx application. + +```powershell +Deploy-Alteryx.ps1 -action "uninstall" +``` + +1. Uninstall Alteryx Server (or Designer if specified with the `-Product` parameter. + +**Warnings:** + +1. The uninstallation process requires the original installation executable file. +2. The uninstallation of Alteryx Server does also remove all dependencies such as Precdictive Tools, Intelligence Suite, etc. + +### Activate + +Below are the steps to activate (license) the Alteryx application. + +```powershell +Deploy-Alteryx.ps1 -action "activate" +``` + +1. Check licensing system connectivity (); +2. Check license file path; +3. Activate Alteryx application. + +### Backup + +Below are the steps to backup the Alteryx application database. + +```powershell +Deploy-Alteryx.ps1 -action "backup" +``` + +1. Check Alteryx Service status and stop it if it is running; +2. Create database dump; +3. Create copy of application configuration files; +4. Backup controller token; +5. Compress all backup files; +6. Restart Alteryx Service (if it was running previously). + +### Restore + +Below are the steps to restore the Alteryx application database. + +```powershell +Deploy-Alteryx.ps1 -action "restore" +``` + +1. Check Alteryx Service status and stop it if it is running; +2. Check backup path; + - If backup file is an archive (.ZIP), extract files from archive. + - If backup path is a directory, select most recent backup file (using [last write time](https://docs.microsoft.com/en-us/dotnet/api/system.io.filesysteminfo.lastwritetime)). +3. Restore MongoDB database; +4. Restore application configuration files; +5. Restore controller token; +6. Reset storage keys; +7. Restart Alteryx Service (if it was running previously). + +### Start + +Below are the steps to start the Alteryx application. + +```powershell +Deploy-Alteryx.ps1 -action "start" +``` + +1. Check Alteryx Service status; +2. If it is not already running, start Alteryx Service; +3. Check if the service started properly. + +### Stop + +Below are the steps to stop the Alteryx application. + +```powershell +Deploy-Alteryx.ps1 -action "stop" +``` + +1. Check Alteryx Service status; +2. If it is not already stopped, stop Alteryx Service; +3. Check if the service stopped properly. + +### Restart + +Below are the steps to restart the Alteryx application. + +```powershell +Deploy-Alteryx.ps1 -action "restart" +``` + +1. Stop Alteryx Service; +2. Start Alteryx Service. + ## Dependencies This module depends on the usage of functions provided by two PowerShell modules: From 9e2c0f1082f0a034d2a2263eca002f55274d4c11 Mon Sep 17 00:00:00 2001 From: Florian Date: Mon, 15 Nov 2021 00:19:08 +0000 Subject: [PATCH 08/21] Add warning for system configuration --- powershell/Install-Alteryx.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/powershell/Install-Alteryx.ps1 b/powershell/Install-Alteryx.ps1 index 08f088a..29cdc6c 100644 --- a/powershell/Install-Alteryx.ps1 +++ b/powershell/Install-Alteryx.ps1 @@ -104,6 +104,7 @@ function Install-Alteryx { Write-Log -Type "WARN" -Message "Do not forget to configure system settings" } else { # TODO start system settings + Write-Log -Type "WARN" -Message "Do not forget to configure system settings" } } } From f643e9bbf095bb5d33a8dc2553b6e43be0621bf0 Mon Sep 17 00:00:00 2001 From: Florian Date: Mon, 15 Nov 2021 17:19:41 +0000 Subject: [PATCH 09/21] Add parameter validation --- Deploy-Alteryx.ps1 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Deploy-Alteryx.ps1 b/Deploy-Alteryx.ps1 index 7fbd860..771291a 100644 --- a/Deploy-Alteryx.ps1 +++ b/Deploy-Alteryx.ps1 @@ -30,7 +30,7 @@ File name: Deploy-Alteryx.psm1 Author: Florian Carrier Creation date: 2021-06-13 - Last modified: 2021-11-10 + Last modified: 2021-11-15 Dependencies: - PowerShell Tool Kit (PSTK) - Alteryx PowerShell Module (PSAYX) @@ -74,6 +74,7 @@ Param ( Mandatory = $false, HelpMessage = "Version parameter overwrite" )] + [ValidateNotNullOrEmpty ()] [System.String] $Version, [Parameter ( @@ -81,7 +82,8 @@ Param ( Mandatory = $false, HelpMessage = "Database backup path" )] - [System.String] + [ValidateNotNullOrEmpty ()] + [System.IO.Path] $BackupPath, [Parameter ( Position = 4, @@ -92,6 +94,7 @@ Param ( "Designer", "Server" )] + [ValidateNotNullOrEmpty ()] [System.String] $Product = "Server", [Parameter ( @@ -106,8 +109,7 @@ Begin { # * Global preferences # ---------------------------------------------------------------------------- $ErrorActionPreference = "Stop" - # $DebugPreference = "SilentlyContinue" - Set-StrictMode -Version Latest + $ProgressPreference = "Continue" # ---------------------------------------------------------------------------- # * Global variables From 93c172c231db3c20dbc5763a150895cdbbcc2d5c Mon Sep 17 00:00:00 2001 From: Florian Date: Mon, 15 Nov 2021 17:20:07 +0000 Subject: [PATCH 10/21] Add destination directory check --- powershell/Invoke-BackupAlteryx.ps1 | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/powershell/Invoke-BackupAlteryx.ps1 b/powershell/Invoke-BackupAlteryx.ps1 index 797a6ca..ac79cb9 100644 --- a/powershell/Invoke-BackupAlteryx.ps1 +++ b/powershell/Invoke-BackupAlteryx.ps1 @@ -10,7 +10,7 @@ function Invoke-BackupAlteryx { File name: Invoke-BackupAlteryx.ps1 Author: Florian Carrier Creation date: 2021-08-26 - Last modified: 2021-09-10 + Last modified: 2021-11-15 #> [CmdletBinding ( SupportsShouldProcess = $true @@ -127,6 +127,9 @@ function Invoke-BackupAlteryx { # ---------------------------------------------------------------------------- # Compress backup Write-Log -Type "INFO" -Message "Compress backup files" + if (Test-Object -Path $Properties.BackupDirectory -NotFound) { + New-Item -Path $Properties.BackupDirectory -ItemType Directory -Force | Out-Null + } Compress-Archive -Path "$TempBackupPath\*" -DestinationPath $BackupPath -CompressionLevel "Optimal" -WhatIf:$WhatIfPreference Write-Log -Type "DEBUG" -Message $BackupPath if (Test-Object -Path $BackupPath -NotFound) { From 8754477e04ae46412ef0122dec4ef726198dce97 Mon Sep 17 00:00:00 2001 From: Florian Carrier Date: Wed, 17 Nov 2021 15:41:11 +0000 Subject: [PATCH 11/21] Use installer base name --- powershell/Install-Alteryx.ps1 | 4 ++-- powershell/Uninstall-Alteryx.ps1 | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/powershell/Install-Alteryx.ps1 b/powershell/Install-Alteryx.ps1 index 29cdc6c..6690d33 100644 --- a/powershell/Install-Alteryx.ps1 +++ b/powershell/Install-Alteryx.ps1 @@ -16,7 +16,7 @@ function Install-Alteryx { File name: Install-Alteryx.ps1 Author: Florian Carrier Creation date: 2021-07-05 - Last modified: 2021-09-14 + Last modified: 2021-11-15 .LINK https://www.powershellgallery.com/packages/PSAYX @@ -85,7 +85,7 @@ function Install-Alteryx { if (Test-Path -Path $ServerPath) { Write-Log -Type "INFO" -Message "Installing Alteryx $($InstallationProperties.Product)" if ($PSCmdlet.ShouldProcess($ServerPath, "Install")) { - $ServerLog = Join-Path -Path $Properties.LogDirectory -ChildPath "${ISOTimeStamp}_${ServerFileName}.log" + $ServerLog = Join-Path -Path $Properties.LogDirectory -ChildPath "${ISOTimeStamp}_${ServerPath.BaseName}.log" $ServerInstall = Install-AlteryxServer -Path $ServerPath -InstallDirectory $Properties.InstallationPath -Log $ServerLog -Serial $Properties.LicenseEmail -Language $Properties.Language -AllUsers -Unattended:$Unattended Write-Log -Type "DEBUG" -Message $ServerInstall if ($ServerInstall.ExitCode -eq 0) { diff --git a/powershell/Uninstall-Alteryx.ps1 b/powershell/Uninstall-Alteryx.ps1 index 3e811d2..8e21700 100644 --- a/powershell/Uninstall-Alteryx.ps1 +++ b/powershell/Uninstall-Alteryx.ps1 @@ -16,7 +16,7 @@ function Uninstall-Alteryx { File name: Uninstall-Alteryx.ps1 Author: Florian Carrier Creation date: 2021-07-08 - Last modified: 2021-09-14 + Last modified: 2021-11-15 .LINK https://www.powershellgallery.com/packages/PSAYX @@ -76,7 +76,7 @@ function Uninstall-Alteryx { if (Test-Path -Path $ServerPath) { Write-Log -Type "INFO" -Message "Uninstalling Alteryx $($InstallationProperties.Product)" if ($PSCmdlet.ShouldProcess($ServerPath, "Uninstall")) { - $ServerLog = Join-Path -Path $Properties.LogDirectory -ChildPath "${ISOTimeStamp}_${ServerFileName}.log" + $ServerLog = Join-Path -Path $Properties.LogDirectory -ChildPath "${ISOTimeStamp}_${ServerPath.BaseName}.log" $ServerUninstall = Uninstall-AlteryxServer -Path $ServerPath -Log $ServerLog -Unattended:$Unattended Write-Log -Type "DEBUG" -Message $ServerUninstall if ($ServerUninstall.ExitCode -eq 0) { From 9dda69f9c2e54528fb43b4fb62526749cdb45d3a Mon Sep 17 00:00:00 2001 From: Florian Carrier Date: Thu, 18 Nov 2021 19:06:48 +0000 Subject: [PATCH 12/21] Revert "Use installer base name" This reverts commit 8754477e04ae46412ef0122dec4ef726198dce97. --- powershell/Install-Alteryx.ps1 | 4 ++-- powershell/Uninstall-Alteryx.ps1 | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/powershell/Install-Alteryx.ps1 b/powershell/Install-Alteryx.ps1 index 6690d33..29cdc6c 100644 --- a/powershell/Install-Alteryx.ps1 +++ b/powershell/Install-Alteryx.ps1 @@ -16,7 +16,7 @@ function Install-Alteryx { File name: Install-Alteryx.ps1 Author: Florian Carrier Creation date: 2021-07-05 - Last modified: 2021-11-15 + Last modified: 2021-09-14 .LINK https://www.powershellgallery.com/packages/PSAYX @@ -85,7 +85,7 @@ function Install-Alteryx { if (Test-Path -Path $ServerPath) { Write-Log -Type "INFO" -Message "Installing Alteryx $($InstallationProperties.Product)" if ($PSCmdlet.ShouldProcess($ServerPath, "Install")) { - $ServerLog = Join-Path -Path $Properties.LogDirectory -ChildPath "${ISOTimeStamp}_${ServerPath.BaseName}.log" + $ServerLog = Join-Path -Path $Properties.LogDirectory -ChildPath "${ISOTimeStamp}_${ServerFileName}.log" $ServerInstall = Install-AlteryxServer -Path $ServerPath -InstallDirectory $Properties.InstallationPath -Log $ServerLog -Serial $Properties.LicenseEmail -Language $Properties.Language -AllUsers -Unattended:$Unattended Write-Log -Type "DEBUG" -Message $ServerInstall if ($ServerInstall.ExitCode -eq 0) { diff --git a/powershell/Uninstall-Alteryx.ps1 b/powershell/Uninstall-Alteryx.ps1 index 8e21700..3e811d2 100644 --- a/powershell/Uninstall-Alteryx.ps1 +++ b/powershell/Uninstall-Alteryx.ps1 @@ -16,7 +16,7 @@ function Uninstall-Alteryx { File name: Uninstall-Alteryx.ps1 Author: Florian Carrier Creation date: 2021-07-08 - Last modified: 2021-11-15 + Last modified: 2021-09-14 .LINK https://www.powershellgallery.com/packages/PSAYX @@ -76,7 +76,7 @@ function Uninstall-Alteryx { if (Test-Path -Path $ServerPath) { Write-Log -Type "INFO" -Message "Uninstalling Alteryx $($InstallationProperties.Product)" if ($PSCmdlet.ShouldProcess($ServerPath, "Uninstall")) { - $ServerLog = Join-Path -Path $Properties.LogDirectory -ChildPath "${ISOTimeStamp}_${ServerPath.BaseName}.log" + $ServerLog = Join-Path -Path $Properties.LogDirectory -ChildPath "${ISOTimeStamp}_${ServerFileName}.log" $ServerUninstall = Uninstall-AlteryxServer -Path $ServerPath -Log $ServerLog -Unattended:$Unattended Write-Log -Type "DEBUG" -Message $ServerUninstall if ($ServerUninstall.ExitCode -eq 0) { From 95a9b44d00b032084da10fd4a2776d8d664da73f Mon Sep 17 00:00:00 2001 From: Florian Carrier Date: Sun, 21 Nov 2021 01:49:18 +0000 Subject: [PATCH 13/21] Disable InstallAware log --- conf/default.ini | 2 ++ powershell/Install-Alteryx.ps1 | 10 +++++++--- powershell/Uninstall-Alteryx.ps1 | 12 +++++++++--- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/conf/default.ini b/conf/default.ini index a62e17d..01a49f6 100644 --- a/conf/default.ini +++ b/conf/default.ini @@ -38,6 +38,8 @@ Language = English Version = 2021.3.3.63061 # SSL/TLS EnableSSL = false +# InstallAware log +InstallAwareLog = false [License] # Licensing system URL diff --git a/powershell/Install-Alteryx.ps1 b/powershell/Install-Alteryx.ps1 index 29cdc6c..e8010f2 100644 --- a/powershell/Install-Alteryx.ps1 +++ b/powershell/Install-Alteryx.ps1 @@ -16,7 +16,7 @@ function Install-Alteryx { File name: Install-Alteryx.ps1 Author: Florian Carrier Creation date: 2021-07-05 - Last modified: 2021-09-14 + Last modified: 2021-11-20 .LINK https://www.powershellgallery.com/packages/PSAYX @@ -85,8 +85,12 @@ function Install-Alteryx { if (Test-Path -Path $ServerPath) { Write-Log -Type "INFO" -Message "Installing Alteryx $($InstallationProperties.Product)" if ($PSCmdlet.ShouldProcess($ServerPath, "Install")) { - $ServerLog = Join-Path -Path $Properties.LogDirectory -ChildPath "${ISOTimeStamp}_${ServerFileName}.log" - $ServerInstall = Install-AlteryxServer -Path $ServerPath -InstallDirectory $Properties.InstallationPath -Log $ServerLog -Serial $Properties.LicenseEmail -Language $Properties.Language -AllUsers -Unattended:$Unattended + if ($Properties.InstallAwareLog -eq $true) { + $InstallAwareLog = Join-Path -Path $Properties.LogDirectory -ChildPath "${ISOTimeStamp}_${ServerFileName}.log" + $ServerInstall = Install-AlteryxServer -Path $ServerPath -InstallDirectory $Properties.InstallationPath -Log $InstallAwareLog -Serial $Properties.LicenseEmail -Language $Properties.Language -AllUsers -Unattended:$Unattended + } else { + $ServerInstall = Install-AlteryxServer -Path $ServerPath -InstallDirectory $Properties.InstallationPath -Serial $Properties.LicenseEmail -Language $Properties.Language -AllUsers -Unattended:$Unattended + } Write-Log -Type "DEBUG" -Message $ServerInstall if ($ServerInstall.ExitCode -eq 0) { Write-Log -Type "CHECK" -Message "Alteryx $($InstallationProperties.Product) installed successfully" diff --git a/powershell/Uninstall-Alteryx.ps1 b/powershell/Uninstall-Alteryx.ps1 index 3e811d2..0759def 100644 --- a/powershell/Uninstall-Alteryx.ps1 +++ b/powershell/Uninstall-Alteryx.ps1 @@ -16,7 +16,7 @@ function Uninstall-Alteryx { File name: Uninstall-Alteryx.ps1 Author: Florian Carrier Creation date: 2021-07-08 - Last modified: 2021-09-14 + Last modified: 2021-11-21 .LINK https://www.powershellgallery.com/packages/PSAYX @@ -70,14 +70,20 @@ function Uninstall-Alteryx { # Alteryx Server # ------------------------------------------------------------------------------ # TODO check if Alteryx is installed + # Deactivate license keys + Invoke-DeactivateAlteryx -Properties $Properties -All -Unattended:$Unattended # Update file version number $ServerFileName = Set-Tags -String $ServerInstaller -Tags (Resolve-Tags -Tags $Tags -Prefix "<" -Suffix ">") $ServerPath = Join-Path -Path $Properties.SrcDirectory -ChildPath $ServerFileName if (Test-Path -Path $ServerPath) { Write-Log -Type "INFO" -Message "Uninstalling Alteryx $($InstallationProperties.Product)" if ($PSCmdlet.ShouldProcess($ServerPath, "Uninstall")) { - $ServerLog = Join-Path -Path $Properties.LogDirectory -ChildPath "${ISOTimeStamp}_${ServerFileName}.log" - $ServerUninstall = Uninstall-AlteryxServer -Path $ServerPath -Log $ServerLog -Unattended:$Unattended + if ($Properties.InstallAwareLog -eq $true) { + $InstallAwareLog = Join-Path -Path $Properties.LogDirectory -ChildPath "${ISOTimeStamp}_${ServerFileName}.log" + $ServerUninstall = Uninstall-AlteryxServer -Path $ServerPath -Log $InstallAwareLog -Unattended:$Unattended + } else { + $ServerUninstall = Uninstall-AlteryxServer -Path $ServerPath -Unattended:$Unattended + } Write-Log -Type "DEBUG" -Message $ServerUninstall if ($ServerUninstall.ExitCode -eq 0) { Write-Log -Type "CHECK" -Message "Alteryx Server uninstalled successfully" From 90b17a4afd28e44aee102e81ee69c9b340a8b676 Mon Sep 17 00:00:00 2001 From: Florian Carrier Date: Sun, 21 Nov 2021 01:49:53 +0000 Subject: [PATCH 14/21] Remove redundant debug message --- powershell/Invoke-ActivateAlteryx.ps1 | 1 - 1 file changed, 1 deletion(-) diff --git a/powershell/Invoke-ActivateAlteryx.ps1 b/powershell/Invoke-ActivateAlteryx.ps1 index de73774..32efd09 100644 --- a/powershell/Invoke-ActivateAlteryx.ps1 +++ b/powershell/Invoke-ActivateAlteryx.ps1 @@ -52,7 +52,6 @@ function Invoke-ActivateAlteryx { Write-Log -Type "INFO" -Message "Activating Alteryx license" # Check licensing system connectivity Write-Log -Type "INFO" -Message "Checking licensing system connectivity" - Write-Log -Type "DEBUG" -Message $Properties.LicensingURL if ((Test-HTTPStatus -URI $Properties.LicensingURL) -eq $true) { # Activate license if ($PSCmdlet.ShouldProcess("Alteryx", "Activate")) { From 7784d6537f8bd9d9913191d14dcdf6fb46f10439 Mon Sep 17 00:00:00 2001 From: Florian Carrier Date: Sun, 21 Nov 2021 01:49:58 +0000 Subject: [PATCH 15/21] Create Invoke-DeactivateAlteryx.ps1 --- powershell/Invoke-DeactivateAlteryx.ps1 | 114 ++++++++++++++++++++++++ 1 file changed, 114 insertions(+) create mode 100644 powershell/Invoke-DeactivateAlteryx.ps1 diff --git a/powershell/Invoke-DeactivateAlteryx.ps1 b/powershell/Invoke-DeactivateAlteryx.ps1 new file mode 100644 index 0000000..f7a05b3 --- /dev/null +++ b/powershell/Invoke-DeactivateAlteryx.ps1 @@ -0,0 +1,114 @@ +function Invoke-DeactivateAlteryx { + <# + .SYNOPSIS + Deactivate Alteryx license + + .DESCRIPTION + Deactivate one or more license keys for Alteryx + + .PARAMETER Properties + The properties parameter corresponds to the configuration of the application. + + .PARAMETER Unattended + The unattended switch specifies if the script should run in non-interactive mode. + + .NOTES + File name: Invoke-DeactivateAlteryx.ps1 + Author: Florian Carrier + Creation date: 2021-11-20 + Last modified: 2021-11-21 + + .LINK + https://www.powershellgallery.com/packages/PSAYX + + .LINK + https://help.alteryx.com/current/product-activation-and-licensing/use-command-line-options + #> + [CmdletBinding ( + SupportsShouldProcess = $true + )] + Param ( + [Parameter ( + Position = 1, + Mandatory = $true, + HelpMessage = "Properties" + )] + [ValidateNotNullOrEmpty ()] + [System.Collections.Specialized.OrderedDictionary] + $Properties, + [Parameter ( + HelpMessage = "Switch to remove all license keys" + )] + [Switch] + $All, + [Parameter ( + HelpMessage = "Non-interactive mode" + )] + [Switch] + $Unattended + ) + Begin { + # Get global preference variables + Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState + # License utility + $LicenseUtility = Get-AlteryxUtility -Utility "License" -Path $Properties.InstallationPath + } + Process { + Write-Log -Type "INFO" -Message "Deactivating Alteryx license" + # Check licensing system connectivity + Write-Log -Type "INFO" -Message "Checking licensing system connectivity" + if ((Test-HTTPStatus -URI $Properties.LicensingURL) -eq $true) { + # Deactivate license + if ($PSCmdlet.ShouldProcess("Alteryx", "Deactivate")) { + if ($All) { + # Remove all license keys + $Deactivation = Remove-AlteryxLicense -Path $LicenseUtility + # Check deactivation status + if (Select-String -InputObject $Dectivation -Pattern "License(s) successfully removed." -SimpleMatch -Quiet) { + Write-Log -Type "CHECK" -Message "All licenses were successfully deactivated" + } else { + # Output error + Write-Log -Type "DEBUG" -Message $Deactivation + } + } else { + # Check license key(s) + if (Test-Object -Path $Properties.LicenseFile -NotFound) { + Write-Log -Type "ERROR" -Message "License file path not found $($Properties.LicenseFile)" -ExitCode 1 + } + # Deactivate each key + $Keys = Get-Content -Path $Properties.LicenseFile + $Count = 0 + foreach ($Key in $Keys) { + $Dectivation = Remove-AlteryxLicense -Path $LicenseUtility -Key $Key + # Check deactivation status + if (Select-String -InputObject $Dectivation -Pattern "License(s) successfully removed." -SimpleMatch -Quiet) { + $Count += 1 + } else { + # Output error + Write-Log -Type "DEBUG" -Message $Deactivation + } + } + # Check outcome + if ($Keys.Count -gt 1) { + $Success = "$($Keys.Count) licenses were successfully deactivated" + $ErrorCount = $Keys.Count - $Count + $Failure = "$ErrorCount out of $($Keys.Count) licenses could not be deactivated" + } elseif ($Keys.Count -eq 1) { + $Success = "$($Keys.Count) license was successfully deactivated" + $Failure = "License could not be deactivated" + } else { + Write-Log -Type "ERROR" -Message "No license key was provided" -ExitCode 1 + } + if ($Count -eq $Keys.Count) { + Write-Log -Type "CHECK" -Message $Success + } else { + Write-Log -Type "ERROR" -Message $Failure + } + } + } + } else { + Write-Log -Type "ERROR" -Message "Unable to reach licensing system" + Write-Log -Type "WARN" -Message "Skipping license deactivation" + } + } +} \ No newline at end of file From 40dfaaa2d1077ddedc7686090e2924176e891776 Mon Sep 17 00:00:00 2001 From: Florian Carrier Date: Sun, 21 Nov 2021 01:50:18 +0000 Subject: [PATCH 16/21] Add support for newer versions --- powershell/Invoke-StartAlteryx.ps1 | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/powershell/Invoke-StartAlteryx.ps1 b/powershell/Invoke-StartAlteryx.ps1 index 7505268..f2f327f 100644 --- a/powershell/Invoke-StartAlteryx.ps1 +++ b/powershell/Invoke-StartAlteryx.ps1 @@ -10,7 +10,7 @@ function Invoke-StartAlteryx { File name: Invoke-StartAlteryx.ps1 Author: Florian Carrier Creation date: 2021-07-08 - Last modified: 2021-07-30 + Last modified: 2021-11-21 #> [CmdletBinding ( SupportsShouldProcess = $true @@ -36,7 +36,7 @@ function Invoke-StartAlteryx { # Variables $ServiceName = "AlteryxService" # Retrieve Alteryx Service utility path - $AlteryxService = Get-AlteryxServerProcess -Process "Service" -InstallDirectory $Properties.InstallationPath + $AlteryxService = Get-AlteryxUtility -Utility "Service" -Path $Properties.InstallationPath } Process { Write-Log -Type "INFO" -Message "Starting Alteryx Service" @@ -55,8 +55,13 @@ function Invoke-StartAlteryx { $Process = Start-Process -FilePath $AlteryxService -ArgumentList "start" -Verb "RunAs" -PassThru -Wait Write-Log -Type "DEBUG" -Message $Process # Check process outcome - # TODO check why exit code is 2 - if ($Process.ExitCode -eq 2) { + if (Compare-Version -Version $Properties.Version -Operator "ge" -Reference "2021.4.1") { + $ExpectedExitCode = 0 + } else { + # Do not ask + $ExpectedExitCode = 2 + } + if ($Process.ExitCode -eq $ExpectedExitCode) { # Wait for service to start while ((Get-Service -Name $ServiceName).Status -eq "StartPending") { Write-Log -Type "INFO" -Message "Alteryx Service is starting..." From 270fff05129f91ddfeab759e267831df9db8836b Mon Sep 17 00:00:00 2001 From: Florian Carrier Date: Sun, 21 Nov 2021 01:50:58 +0000 Subject: [PATCH 17/21] Update to match PSAYX refactoring --- powershell/Invoke-StopAlteryx.ps1 | 4 ++-- powershell/Update-Alteryx.ps1 | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/powershell/Invoke-StopAlteryx.ps1 b/powershell/Invoke-StopAlteryx.ps1 index f425e82..503236e 100644 --- a/powershell/Invoke-StopAlteryx.ps1 +++ b/powershell/Invoke-StopAlteryx.ps1 @@ -10,7 +10,7 @@ function Invoke-StopAlteryx { File name: Invoke-StopAlteryx.ps1 Author: Florian Carrier Creation date: 2021-07-08 - Last modified: 2021-08-30 + Last modified: 2021-11-20 #> [CmdletBinding ( SupportsShouldProcess = $true @@ -36,7 +36,7 @@ function Invoke-StopAlteryx { # Variables $ServiceName = "AlteryxService" # Retrieve Alteryx Service utility path - $AlteryxService = Get-AlteryxServerProcess -Process "Service" -InstallDirectory $Properties.InstallationPath + $AlteryxService = Get-AlteryxUtility -Utility "Service" -Path $Properties.InstallationPath } Process { Write-Log -Type "INFO" -Message "Stopping Alteryx Service" diff --git a/powershell/Update-Alteryx.ps1 b/powershell/Update-Alteryx.ps1 index 8aa3fdf..a1e53c8 100644 --- a/powershell/Update-Alteryx.ps1 +++ b/powershell/Update-Alteryx.ps1 @@ -10,7 +10,7 @@ function Update-Alteryx { File name: Update-Alteryx.ps1 Author: Florian Carrier Creation date: 2021-09-02 - Last modified: 2021-11-01 + Last modified: 2021-11-20 #> [CmdletBinding ( SupportsShouldProcess = $true @@ -42,7 +42,7 @@ function Update-Alteryx { # Get global preference vrariables Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState # Retrieve Alteryx Service utility path - $AlteryxService = Get-AlteryxServerProcess -Process "Service" -InstallDirectory $Properties.InstallationPath + $AlteryxService = Get-AlteryxUtility -Utility "Service" -Path $Properties.InstallationPath # Clear error pipeline $Error.Clear() } From 4e6d238b3b227a299114d46853531fa855e9206c Mon Sep 17 00:00:00 2001 From: Florian Carrier Date: Sun, 21 Nov 2021 15:57:40 +0000 Subject: [PATCH 18/21] Expand WhatIf coverage --- powershell/Install-Alteryx.ps1 | 38 +++--- powershell/Invoke-BackupAlteryx.ps1 | 63 +++++----- powershell/Invoke-RestoreAlteryx.ps1 | 174 +++++++++++++++------------ powershell/Invoke-StartAlteryx.ps1 | 14 +-- powershell/Uninstall-Alteryx.ps1 | 12 +- 5 files changed, 160 insertions(+), 141 deletions(-) diff --git a/powershell/Install-Alteryx.ps1 b/powershell/Install-Alteryx.ps1 index e8010f2..382f6d5 100644 --- a/powershell/Install-Alteryx.ps1 +++ b/powershell/Install-Alteryx.ps1 @@ -82,9 +82,9 @@ function Install-Alteryx { # Update file version number $ServerFileName = Set-Tags -String $ServerInstaller -Tags (Resolve-Tags -Tags $Tags -Prefix "<" -Suffix ">") $ServerPath = Join-Path -Path $Properties.SrcDirectory -ChildPath $ServerFileName - if (Test-Path -Path $ServerPath) { - Write-Log -Type "INFO" -Message "Installing Alteryx $($InstallationProperties.Product)" - if ($PSCmdlet.ShouldProcess($ServerPath, "Install")) { + Write-Log -Type "INFO" -Message "Installing Alteryx $($InstallationProperties.Product)" + if ($PSCmdlet.ShouldProcess($ServerPath, "Install")) { + if (Test-Path -Path $ServerPath) { if ($Properties.InstallAwareLog -eq $true) { $InstallAwareLog = Join-Path -Path $Properties.LogDirectory -ChildPath "${ISOTimeStamp}_${ServerFileName}.log" $ServerInstall = Install-AlteryxServer -Path $ServerPath -InstallDirectory $Properties.InstallationPath -Log $InstallAwareLog -Serial $Properties.LicenseEmail -Language $Properties.Language -AllUsers -Unattended:$Unattended @@ -97,10 +97,10 @@ function Install-Alteryx { } else { Write-Log -Type "ERROR" -Message "An error occured during the installation" -ExitCode $ServerInstall.ExitCode } + } else { + Write-Log -Type "ERROR" -Message "Path not found $ServerPath" + Write-Log -Type "ERROR" -Message "Alteryx $($InstallationProperties.Product) installation file could not be located" -ExitCode 1 } - } else { - Write-Log -Type "ERROR" -Message "Path not found $ServerPath" - Write-Log -Type "ERROR" -Message "Alteryx $($InstallationProperties.Product) installation file could not be located" -ExitCode 1 } # Configuration if ($InstallationProperties.Product -eq "Server") { @@ -125,9 +125,9 @@ function Install-Alteryx { $RPath = Join-Path -Path $Properties.SrcDirectory -ChildPath $RFileName } # Check source file - if (Test-Path -Path $RPath) { - Write-Log -Type "INFO" -Message "Installing Predictive Tools" - if ($PSCmdlet.ShouldProcess($RPath, "Install")) { + Write-Log -Type "INFO" -Message "Installing Predictive Tools" + if ($PSCmdlet.ShouldProcess($RPath, "Install")) { + if (Test-Path -Path $RPath) { $RCommand = (@("&", $RPath, $Arguments) -join " ").Trim() Write-Log -Type "DEBUG" -Message $RCommand $RInstall = Start-Process -FilePath $RPath -ArgumentList $Arguments -Verb "RunAs" -PassThru -Wait @@ -137,10 +137,10 @@ function Install-Alteryx { } else { Write-Log -Type "ERROR" -Message "An error occured during the installation" -ExitCode $RInstall.ExitCode } + } else { + Write-Log -Type "ERROR" -Message "Path not found $RPath" + Write-Log -Type "ERROR" -Message "Predictive Tools installation file could not be located" -ExitCode 1 } - } else { - Write-Log -Type "ERROR" -Message "Path not found $RPath" - Write-Log -Type "ERROR" -Message "Predictive Tools installation file could not be located" -ExitCode 1 } } # ------------------------------------------------------------------------------ @@ -150,9 +150,9 @@ function Install-Alteryx { # Update file version number $AISFileName = Set-Tags -String $AISInstaller -Tags (Resolve-Tags -Tags $Tags -Prefix "<" -Suffix ">") $AISPath = Join-Path -Path $Properties.SrcDirectory -ChildPath $AISFileName - if (Test-Path -Path $AISPath) { - Write-Log -Type "INFO" -Message "Installing Intelligence Suite" - if ($PSCmdlet.ShouldProcess($AISPath, "Install")) { + Write-Log -Type "INFO" -Message "Installing Intelligence Suite" + if ($PSCmdlet.ShouldProcess($AISPath, "Install")) { + if (Test-Path -Path $AISPath) { $AISCommand = (@("&", $AISPath, $Arguments) -join " ").Trim() Write-Log -Type "DEBUG" -Message $AISCommand $AISInstall = Start-Process -FilePath $AISPath -ArgumentList $Arguments -Verb "RunAs" -PassThru -Wait @@ -162,10 +162,10 @@ function Install-Alteryx { } else { Write-Log -Type "ERROR" -Message "An error occured during the installation" -ExitCode $AISInstall.ExitCode } + } else { + Write-Log -Type "ERROR" -Message "Path not found $AISPath" + Write-Log -Type "ERROR" -Message "Alteryx Intelligence Suite installation file could not be located" -ExitCode 1 } - } else { - Write-Log -Type "ERROR" -Message "Path not found $AISPath" - Write-Log -Type "ERROR" -Message "Alteryx Intelligence Suite installation file could not be located" -ExitCode 1 } } # ------------------------------------------------------------------------------ @@ -218,7 +218,7 @@ function Install-Alteryx { # ------------------------------------------------------------------------------ # Licensing # ------------------------------------------------------------------------------ - Invoke-ActivateAlteryx -Properties $Properties -Unattended:$Unattended + Invoke-ActivateAlteryx -Properties $Properties -Unattended:$Unattended } End { Write-Log -Type "CHECK" -Message "Alteryx $($InstallationProperties.Product) $($Properties.Version) installed successfully" diff --git a/powershell/Invoke-BackupAlteryx.ps1 b/powershell/Invoke-BackupAlteryx.ps1 index ac79cb9..ff77cd8 100644 --- a/powershell/Invoke-BackupAlteryx.ps1 +++ b/powershell/Invoke-BackupAlteryx.ps1 @@ -10,7 +10,7 @@ function Invoke-BackupAlteryx { File name: Invoke-BackupAlteryx.ps1 Author: Florian Carrier Creation date: 2021-08-26 - Last modified: 2021-11-15 + Last modified: 2021-11-21 #> [CmdletBinding ( SupportsShouldProcess = $true @@ -64,16 +64,18 @@ function Invoke-BackupAlteryx { # ---------------------------------------------------------------------------- # Check Alteryx service status Write-Log -Type "INFO" -Message "Check Alteryx Service status" - $Service = "AlteryxService" - if (Test-Service -Name $Service) { - $WindowsService = Get-Service -Name $Service - Write-Log -Type "DEBUG" -Message $Service - $ServiceStatus = $WindowsService.Status - if ($ServiceStatus -eq "Running") { - Invoke-StopAlteryx -Properties $Properties -Unattended:$Unattended + if ($PSCmdlet.ShouldProcess("Alteryx Service", "Stop")) { + $Service = "AlteryxService" + if (Test-Service -Name $Service) { + $WindowsService = Get-Service -Name $Service + Write-Log -Type "DEBUG" -Message $Service + $ServiceStatus = $WindowsService.Status + if ($ServiceStatus -eq "Running") { + Invoke-StopAlteryx -Properties $Properties -Unattended:$Unattended + } + } else { + Write-Log -Type "ERROR" -Message "Alteryx Service ($Service) could not be found" -ExitCode 1 } - } else { - Write-Log -Type "ERROR" -Message "Alteryx Service ($Service) could not be found" -ExitCode 1 } # ---------------------------------------------------------------------------- # Create database dump @@ -100,15 +102,16 @@ function Invoke-BackupAlteryx { # Backup configuration files if ($Backup.Configuration -eq $true) { Write-Log -Type "INFO" -Message "Backup configuration files" - $ProgramData = Join-Path -Path ([Environment]::GetEnvironmentVariable("ProgramData")) -ChildPath "Alteryx" - foreach ($ConfigurationFile in $ConfigurationFiles.GetEnumerator()) { - $FilePath = Join-Path -Path $ProgramData -ChildPath $ConfigurationFile.Value - if (Test-Object -Path $FilePath) { - if ($PSCmdlet.ShouldProcess($FilePath, "Back-up")) { + if ($PSCmdlet.ShouldProcess("Configuration files", "Back-up")) { + $ProgramData = Join-Path -Path ([Environment]::GetEnvironmentVariable("ProgramData")) -ChildPath "Alteryx" + foreach ($ConfigurationFile in $ConfigurationFiles.GetEnumerator()) { + $FilePath = Join-Path -Path $ProgramData -ChildPath $ConfigurationFile.Value + if (Test-Object -Path $FilePath) { Copy-Object -Path $FilePath -Destination $TempBackupPath -Force + } else { + Write-Log -Type "WARN" -Message "$($ConfigurationFile.Name) configuration file could not be found" + Write-Log -Type "DEBUG" -Message $FilePath } - } else { - Write-Log -Type "WARN" -Message "$($ConfigurationFile.Name) configuration file could not be found ($FilePath)" } } } @@ -127,18 +130,20 @@ function Invoke-BackupAlteryx { # ---------------------------------------------------------------------------- # Compress backup Write-Log -Type "INFO" -Message "Compress backup files" - if (Test-Object -Path $Properties.BackupDirectory -NotFound) { - New-Item -Path $Properties.BackupDirectory -ItemType Directory -Force | Out-Null - } - Compress-Archive -Path "$TempBackupPath\*" -DestinationPath $BackupPath -CompressionLevel "Optimal" -WhatIf:$WhatIfPreference - Write-Log -Type "DEBUG" -Message $BackupPath - if (Test-Object -Path $BackupPath -NotFound) { - Write-Log -Type "ERROR" -Message "Backup files compression failed" -ErrorCode 1 - } else { - # Remove staging folder - Write-Log -Type "INFO" -Message "Remove staging backup folder" - if ($PSCmdlet.ShouldProcess($TempBackupPath, "Remove")) { - Remove-Object -Path $TempBackupPath -Type "Folder" + if ($PSCmdlet.ShouldProcess("Compress", "Back-up")) { + if (Test-Object -Path $Properties.BackupDirectory -NotFound) { + New-Item -Path $Properties.BackupDirectory -ItemType Directory -Force | Out-Null + } + Compress-Archive -Path "$TempBackupPath\*" -DestinationPath $BackupPath -CompressionLevel "Optimal" -WhatIf:$WhatIfPreference + Write-Log -Type "DEBUG" -Message $BackupPath + if (Test-Object -Path $BackupPath -NotFound) { + Write-Log -Type "ERROR" -Message "Backup files compression failed" -ErrorCode 1 + } else { + # Remove staging folder + Write-Log -Type "INFO" -Message "Remove staging backup folder" + if ($PSCmdlet.ShouldProcess($TempBackupPath, "Remove")) { + Remove-Object -Path $TempBackupPath -Type "Folder" + } } } # ---------------------------------------------------------------------------- diff --git a/powershell/Invoke-RestoreAlteryx.ps1 b/powershell/Invoke-RestoreAlteryx.ps1 index 2bf8a08..9b5fe13 100644 --- a/powershell/Invoke-RestoreAlteryx.ps1 +++ b/powershell/Invoke-RestoreAlteryx.ps1 @@ -10,7 +10,7 @@ function Invoke-RestoreAlteryx { File name: Invoke-RestoreAlteryx.ps1 Author: Florian Carrier Creation date: 2021-08-26 - Last modified: 2021-08-31 + Last modified: 2021-11-21 Comment: User configuration files are out of scope of this procedure: - %APPDATA%\Alteryx\Engine\UserConnections.xml - %APPDATA%\Alteryx\Engine\UserAlias.xml @@ -67,79 +67,87 @@ function Invoke-RestoreAlteryx { } Process { Write-Log -Type "CHECK" -Message "Start $RestoreType restore of Alteryx Server" - # ---------------------------------------------------------------------------- - # Check Alteryx service status - Write-Log -Type "INFO" -Message "Check Alteryx Service status" - $Service = "AlteryxService" - if (Test-Service -Name $Service) { - $WindowsService = Get-Service -Name $Service - Write-Log -Type "DEBUG" -Message $Service - $ServiceStatus = $WindowsService.Status - if ($ServiceStatus -eq "Running") { - Invoke-StopAlteryx -Properties $Properties + if ($PSCmdlet.ShouldProcess("Alteryx Service", "Stop")) { + # ---------------------------------------------------------------------------- + # Check Alteryx service status + Write-Log -Type "INFO" -Message "Check Alteryx Service status" + $Service = "AlteryxService" + if (Test-Service -Name $Service) { + $WindowsService = Get-Service -Name $Service + Write-Log -Type "DEBUG" -Message $Service + $ServiceStatus = $WindowsService.Status + if ($ServiceStatus -eq "Running") { + Invoke-StopAlteryx -Properties $Properties -Unattended:$Unattended + } + } else { + Write-Log -Type "ERROR" -Message "Alteryx Service ($Service) could not be found" -ExitCode 1 } - } else { - Write-Log -Type "ERROR" -Message "Alteryx Service ($Service) could not be found" -ExitCode 1 } # ---------------------------------------------------------------------------- # Check source backup path - if ($null -eq (Get-KeyValue -Hashtable $Properties -Key "BackupPath" -Silent)) { - $SourcePath = $Properties.BackupDirectory - } else { - $SourcePath = $Properties.BackupPath - } - if (Test-Object -Path $SourcePath) { - if ($SourcePath -is [System.IO.FileInfo]) { - if ([System.IO.Path]::GetExtension($SourcePath) -eq ".zip") { + if ($PSCmdlet.ShouldProcess("Backup files", "Retrieve")) { + if ($null -eq (Get-KeyValue -Hashtable $Properties -Key "BackupPath" -Silent)) { + $SourcePath = $Properties.BackupDirectory + } else { + $SourcePath = $Properties.BackupPath + } + if (Test-Object -Path $SourcePath) { + if ($SourcePath -is [System.IO.FileInfo]) { + if ([System.IO.Path]::GetExtension($SourcePath) -eq ".zip") { + # Extract archive file + Write-Log -Type "INFO" -Message "Extract backup file contents" + $BackupPath = Join-Path -Path $Properties.TempDirectory -ChildPath ([System.IO.Path]::GetFileNameWithoutExtension($SourcePath)) + Expand-Archive -Path $SourcePath -DestinationPath $BackupPath -Force -WhatIf:$WhatIfPreference + $Staging = $true + } else { + Write-Log -Type "ERROR" -Message "Only ZIP or uncompressed files are supported" -ExitCode 1 + } + } else { + # Select most recent backup in the directory + Write-Log -Type "WARN" -Message "No backup file was specified" + Write-Log -Type "DEBUG" -Message $SourcePath + Write-Log -Type "INFO" -Message "Retrieving most recent backup" + $BackupFile = (Get-Object -Path $SourcePath -ChildItem -Type "File" -Filter "*.zip" | Sort-Object -Descending -Property "LastWriteTime" | Select-Object -First 1).FullName + Write-Log -Type "DEBUG" -Message $BackupFile # Extract archive file Write-Log -Type "INFO" -Message "Extract backup file contents" - $BackupPath = Join-Path -Path ([System.IO.Path]::GetDirectoryName($SourcePath)) -ChildPath ([System.IO.Path]::GetFileNameWithoutExtension($SourcePath)) - Expand-Archive -Path $SourcePath -DestinationPath $BackupPath -Force -WhatIf:$WhatIfPreference + $BackupPath = Join-Path -Path $Properties.TempDirectory -ChildPath ([System.IO.Path]::GetFileNameWithoutExtension($BackupFile)) + Expand-Archive -Path $BackupFile -DestinationPath $BackupPath -Force -WhatIf:$WhatIfPreference $Staging = $true - } else { - Write-Log -Type "ERROR" -Message "Only ZIP or uncompressed files are supported" -ExitCode 1 } } else { - # Select most recent backup in the directory - Write-Log -Type "WARN" -Message "No backup file was specified" - Write-Log -Type "DEBUG" -Message $SourcePath - Write-Log -Type "INFO" -Message "Retrieving most recent backup" - $BackupFile = (Get-Object -Path $SourcePath -ChildItem -Type "File" -Filter "*.zip" | Sort-Object -Descending -Property "LastWriteTime" | Select-Object -First 1).FullName - Write-Log -Type "DEBUG" -Message $BackupFile - # Extract archive file - Write-Log -Type "INFO" -Message "Extract backup file contents" - $BackupPath = Join-Path -Path ([System.IO.Path]::GetDirectoryName($BackupFile)) -ChildPath ([System.IO.Path]::GetFileNameWithoutExtension($BackupFile)) - Expand-Archive -Path $BackupFile -DestinationPath $BackupPath -Force -WhatIf:$WhatIfPreference - $Staging = $true + Write-Log -Type "ERROR" -Message "No database backup could be found" -ExitCode 1 } - } else { - Write-Log -Type "ERROR" -Message "No database backup could be found" -ExitCode 1 } # ---------------------------------------------------------------------------- # Restore database if ($Restore.Database -eq $true) { Write-Log -Type "INFO" -Message "Restore MongoDB database from backup" - $MongoDBPath = Join-Path -Path $BackupPath -ChildPath "MongoDB" - $DatabaseRestore = Restore-AlteryxDatabase -SourcePath $MongoDBPath -TargetPath $TargetPath -ServicePath $ServicePath - if ($DatabaseRestore -match "failed") { - Write-Log -Type "ERROR" -Message $DatabaseRestore - Write-Log -Type "ERROR" -Message "Database restore failed" -ExitCode 1 - } else { - Write-Log -Type "DEBUG" -Message $DatabaseRestore + if ($PSCmdlet.ShouldProcess("MongoDB", "Restore")) { + $MongoDBPath = Join-Path -Path $BackupPath -ChildPath "MongoDB" + $DatabaseRestore = Restore-AlteryxDatabase -SourcePath $MongoDBPath -TargetPath $TargetPath -ServicePath $ServicePath + if ($DatabaseRestore -match "failed") { + Write-Log -Type "ERROR" -Message $DatabaseRestore + Write-Log -Type "ERROR" -Message "Database restore failed" -ExitCode 1 + } else { + Write-Log -Type "DEBUG" -Message $DatabaseRestore + } } } # ---------------------------------------------------------------------------- # Restore configuration files if ($Restore.Configuration -eq $true) { Write-Log -Type "INFO" -Message "Restore configuration files" - $BackupConfigurationFiles = Get-Object -Path $BackupPath -ChildItem -Filter "*.xml" - foreach ($ConfigurationFile in $ConfigurationFiles.GetEnumerator()) { - $BackupConfigurationFile = $BackupConfigurationFiles | Where-Object -Property "BaseName" -EQ -Value $ConfigurationFile.Name - if ($null -ne $BackupConfigurationFile) { - # Overwrite existing file - Copy-Object -Path $BackupConfigurationFile.FullName -Destination $ConfigurationFile.Value -Force - } else { - Write-Log -Type "WARN" -Message "$($ConfigurationFile.Name) backup configuration file could not be found" + if ($PSCmdlet.ShouldProcess("Configuration files", "Restore")) { + $BackupConfigurationFiles = Get-Object -Path $BackupPath -ChildItem -Filter "*.xml" + foreach ($ConfigurationFile in $ConfigurationFiles.GetEnumerator()) { + $BackupConfigurationFile = $BackupConfigurationFiles | Where-Object -Property "BaseName" -EQ -Value $ConfigurationFile.Name + if ($null -ne $BackupConfigurationFile) { + # Overwrite existing file + Copy-Object -Path $BackupConfigurationFile.FullName -Destination $ConfigurationFile.Value -Force + } else { + Write-Log -Type "WARN" -Message "$($ConfigurationFile.Name) backup configuration file could not be found" + } } } } @@ -147,15 +155,17 @@ function Invoke-RestoreAlteryx { # Set controller token if ($Restore.Token -eq $true) { Write-Log -Type "INFO" -Message "Restore controller token" - $TokenFile = Join-Path -Path $BackupPath -ChildPath "ControllerToken.txt" - if (Test-Object -Path $TokenFile) { - $ControllerToken = Get-Content -Path $TokenFile -Raw - $SetToken = Set-AlteryxServerSecret -Secret $ControllerToken.Trim() -Path $ServicePath - if ($SetToken -match "failed") { - Write-Log -Type "ERROR" -Message $SetToken - Write-Log -Type "ERROR" -Message "Controller token update failed" - } else { - Write-Log -Type "DEBUG" -Message $SetToken + if ($PSCmdlet.ShouldProcess("Controller token", "Restore")) { + $TokenFile = Join-Path -Path $BackupPath -ChildPath "ControllerToken.txt" + if (Test-Object -Path $TokenFile) { + $ControllerToken = Get-Content -Path $TokenFile -Raw + $SetToken = Set-AlteryxServerSecret -Secret $ControllerToken.Trim() -Path $ServicePath + if ($SetToken -match "failed") { + Write-Log -Type "ERROR" -Message $SetToken + Write-Log -Type "ERROR" -Message "Controller token update failed" + } else { + Write-Log -Type "DEBUG" -Message $SetToken + } } } } @@ -173,22 +183,24 @@ function Invoke-RestoreAlteryx { # Reset storage key if ($Restore.Configuration -eq $true) { Write-Log -Type "INFO" -Message "Restore storage key" - $XPath = "SystemSettings/Controller/StorageKeysEncrypted" - # Retrieve backup storage keys value - $BackUpRunTimeSettings = Get-Object -Path $BackupPath -ChildItem -Filter "RunTimeSettings.xml" - if ($null -ne $BackUpRunTimeSettings) { - $BackupXML = New-Object -TypeName "System.XML.XMLDocument" - $BackupXML.Load($BackUpRunTimeSettings.FullName) - $BackupXMLNode = Select-XMLNode -XML $BackupXML -XPath $XPath - Write-Log -Type "DEBUG" -Message $BackupXMLNode.InnerText - # Update configuration file - $RunTimeSettingsXML = New-Object -TypeName "System.XML.XMLDocument" - $RunTimeSettingsXML.Load($ConfigurationFiles.RunTimeSettings) - $NewXMLNode = Select-XMLNode -XML $RunTimeSettingsXML -XPath $XPath - $NewXMLNode.InnerText = $BackupXMLNode.InnerText - $RunTimeSettingsXML.Save($ConfigurationFiles.RunTimeSettings) - } else { - Write-Log -Type "WARN" -Message "RunTimeSettings.xml backup configuration file could not be located" + if ($PSCmdlet.ShouldProcess("Storage Key", "Restore")) { + $XPath = "SystemSettings/Controller/StorageKeysEncrypted" + # Retrieve backup storage keys value + $BackUpRunTimeSettings = Get-Object -Path $BackupPath -ChildItem -Filter "RunTimeSettings.xml" + if ($null -ne $BackUpRunTimeSettings) { + $BackupXML = New-Object -TypeName "System.XML.XMLDocument" + $BackupXML.Load($BackUpRunTimeSettings.FullName) + $BackupXMLNode = Select-XMLNode -XML $BackupXML -XPath $XPath + Write-Log -Type "DEBUG" -Message $BackupXMLNode.InnerText + # Update configuration file + $RunTimeSettingsXML = New-Object -TypeName "System.XML.XMLDocument" + $RunTimeSettingsXML.Load($ConfigurationFiles.RunTimeSettings) + $NewXMLNode = Select-XMLNode -XML $RunTimeSettingsXML -XPath $XPath + $NewXMLNode.InnerText = $BackupXMLNode.InnerText + $RunTimeSettingsXML.Save($ConfigurationFiles.RunTimeSettings) + } else { + Write-Log -Type "WARN" -Message "RunTimeSettings.xml backup configuration file could not be located" + } } } # ---------------------------------------------------------------------------- @@ -198,8 +210,10 @@ function Invoke-RestoreAlteryx { Remove-Object -Path $BackupPath -Type "Folder" } # Restart service if it was running before - if ($ServiceStatus -eq "Running") { - Invoke-StartAlteryx -Properties $Properties + if ($PSCmdlet.ShouldProcess("Alteryx Service", "Restart")) { + if ($ServiceStatus -eq "Running") { + Invoke-StartAlteryx -Properties $Properties -Unattended:$Unattended + } } } End { diff --git a/powershell/Invoke-StartAlteryx.ps1 b/powershell/Invoke-StartAlteryx.ps1 index f2f327f..7bff17d 100644 --- a/powershell/Invoke-StartAlteryx.ps1 +++ b/powershell/Invoke-StartAlteryx.ps1 @@ -40,13 +40,13 @@ function Invoke-StartAlteryx { } Process { Write-Log -Type "INFO" -Message "Starting Alteryx Service" - # Check service status - $WindowsService = Get-Service -Name $ServiceName - Write-Log -Type "DEBUG" -Message $WindowsService - if ($WindowsService.Status -eq "Running") { - Write-Log -Type "WARN" -Message "Alteryx Service ($ServiceName) is already running" - } else { - if ($PSCmdlet.ShouldProcess("Alteryx Service", "Start")) { + if ($PSCmdlet.ShouldProcess("Alteryx Service", "Start")) { + # Check service status + $WindowsService = Get-Service -Name $ServiceName + Write-Log -Type "DEBUG" -Message $WindowsService + if ($WindowsService.Status -eq "Running") { + Write-Log -Type "WARN" -Message "Alteryx Service ($ServiceName) is already running" + } else { if ($Unattended -eq $false) { $Confirm = Confirm-Prompt -Prompt "Do you want to start the Alteryx Service?" } diff --git a/powershell/Uninstall-Alteryx.ps1 b/powershell/Uninstall-Alteryx.ps1 index 0759def..1100a2c 100644 --- a/powershell/Uninstall-Alteryx.ps1 +++ b/powershell/Uninstall-Alteryx.ps1 @@ -75,9 +75,9 @@ function Uninstall-Alteryx { # Update file version number $ServerFileName = Set-Tags -String $ServerInstaller -Tags (Resolve-Tags -Tags $Tags -Prefix "<" -Suffix ">") $ServerPath = Join-Path -Path $Properties.SrcDirectory -ChildPath $ServerFileName - if (Test-Path -Path $ServerPath) { - Write-Log -Type "INFO" -Message "Uninstalling Alteryx $($InstallationProperties.Product)" - if ($PSCmdlet.ShouldProcess($ServerPath, "Uninstall")) { + Write-Log -Type "INFO" -Message "Uninstalling Alteryx $($InstallationProperties.Product)" + if ($PSCmdlet.ShouldProcess($ServerPath, "Uninstall")) { + if (Test-Path -Path $ServerPath) { if ($Properties.InstallAwareLog -eq $true) { $InstallAwareLog = Join-Path -Path $Properties.LogDirectory -ChildPath "${ISOTimeStamp}_${ServerFileName}.log" $ServerUninstall = Uninstall-AlteryxServer -Path $ServerPath -Log $InstallAwareLog -Unattended:$Unattended @@ -90,10 +90,10 @@ function Uninstall-Alteryx { } else { Write-Log -Type "ERROR" -Message "An error occured during the uninstallation" -ExitCode $ServerUninstall.ExitCode } + } else { + Write-Log -Type "ERROR" -Message "Path not found $ServerPath" + Write-Log -Type "ERROR" -Message "Alteryx $($InstallationProperties.Product) executable file could not be located" -ExitCode 1 } - } else { - Write-Log -Type "ERROR" -Message "Path not found $ServerPath" - Write-Log -Type "ERROR" -Message "Alteryx $($InstallationProperties.Product) executable file could not be located" -ExitCode 1 } # TODO enable uninstall of standalone components Write-Log -Type "CHECK" -Message "Uninstallation of Alteryx $($InstallationProperties.Product) $Version successfull" From 7d4af063b3b5cde86c0128042699478d6033cf56 Mon Sep 17 00:00:00 2001 From: Florian Carrier Date: Sun, 21 Nov 2021 15:58:02 +0000 Subject: [PATCH 19/21] Add license key parameter --- Deploy-Alteryx.ps1 | 74 ++++++++++++++++--------- conf/default.ini | 2 +- powershell/Invoke-ActivateAlteryx.ps1 | 41 +++++++------- powershell/Invoke-DeactivateAlteryx.ps1 | 51 ++++++++++------- 4 files changed, 101 insertions(+), 67 deletions(-) diff --git a/Deploy-Alteryx.ps1 b/Deploy-Alteryx.ps1 index 771291a..bc4d8e1 100644 --- a/Deploy-Alteryx.ps1 +++ b/Deploy-Alteryx.ps1 @@ -11,28 +11,30 @@ .PARAMETER Action The action parameter corresponds to the operation to perform. - Ten options are available: - - backup: backup the Alteryx application database - - configure: configure the Alteryx application - - install: install the Alteryx application - - restart: restart the Alteryx application - - restore: restore a backup of the Alteryx application database - - show: display the script configuration - - start: start the Alteryx application - - stop: stop the Alteryx application - - uninstall: uninstall the Alteryx application - - upgrade: upgrade the Alteryx application + Eleven options are available: + + - activate: activate the Alteryx application license + - backup: backup the Alteryx application database + - deactivate: deactivate the Alteryx application license + - install: install the Alteryx application + - restart: restart the Alteryx application + - restore: restore a backup of the Alteryx application database + - show: display the script configuration + - start: start the Alteryx application + - stop: stop the Alteryx application + - uninstall: uninstall the Alteryx application + - upgrade: upgrade the Alteryx application .PARAMETER Unattended The unattended switch define if the script should run in silent mode without any user interaction. .NOTES - File name: Deploy-Alteryx.psm1 + File name: Deploy-Alteryx.ps1 Author: Florian Carrier Creation date: 2021-06-13 Last modified: 2021-11-15 Dependencies: - PowerShell Tool Kit (PSTK) - - Alteryx PowerShell Module (PSAYX) + - Alteryx PowerShell Module (PSAYX) .LINK https://github.com/Akaizoku/alteryx-deploy @@ -58,6 +60,7 @@ Param ( [ValidateSet ( "activate", "backup", + "deactivate", "install", "restart", "restore", @@ -83,7 +86,7 @@ Param ( HelpMessage = "Database backup path" )] [ValidateNotNullOrEmpty ()] - [System.IO.Path] + [System.String] $BackupPath, [Parameter ( Position = 4, @@ -97,6 +100,18 @@ Param ( [ValidateNotNullOrEmpty ()] [System.String] $Product = "Server", + [Parameter ( + Position = 5, + Mandatory = $false, + HelpMessage = "License key(s)" + )] + [ValidatePattern ("^\w{4}-\w{4}-\w{4}-\w{4}-\w{4}-\w{4}-\w{4}-\w{4}(\s\w{4}-\w{4}-\w{4}-\w{4}-\w{4}-\w{4}-\w{4}-\w{4})*$")] + [Alias ( + "Keys", + "Serial" + )] + [System.String[]] + $LicenseKey, [Parameter ( HelpMessage = "Run script in non-interactive mode" )] @@ -129,7 +144,7 @@ Begin { # Dependencies $Modules = [Ordered]@{ "PSTK" = "1.2.4" - "PSAYX" = "1.0.0" + "PSAYX" = "1.0.1" } # Load modules foreach ($Module in $Modules.GetEnumerator()) { @@ -215,22 +230,29 @@ Begin { if ($PSBoundParameters.ContainsKey("BackupPath")) { $Properties.Add("BackupPath", $BackupPath) } + if ($PSBoundParameters.ContainsKey("LicenseKey")) { + if ($LicenseKey.Count -eq 1 -And $LicenseKey -match "\s") { + $LicenseKey = $LicenseKey.Split(" ") + } + $Properties.Add("LicenseKey", @($LicenseKey)) + } } Process { # Check operation to perform switch ($Action) { - "activate" { Invoke-ActivateAlteryx -Properties $Properties -Unattended:$Unattended } - "backup" { Invoke-BackupAlteryx -Properties $Properties -Unattended:$Unattended } - "install" { Install-Alteryx -Properties $Properties -InstallationProperties $InstallationProperties -Unattended:$Unattended } - "restart" { Invoke-RestartAlteryx -Properties $Properties -Unattended:$Unattended } - "restore" { Invoke-RestoreAlteryx -Properties $Properties -Unattended:$Unattended } - "show" { Show-Configuration -Properties $Properties -InstallationProperties $InstallationProperties } - "start" { Invoke-StartAlteryx -Properties $Properties -Unattended:$Unattended } - "stop" { Invoke-StopAlteryx -Properties $Properties -Unattended:$Unattended } - "uninstall" { Uninstall-Alteryx -Properties $Properties -InstallationProperties $InstallationProperties -Unattended:$Unattended } - "upgrade" { Update-Alteryx -Properties $Properties -InstallationProperties $InstallationProperties -Unattended:$Unattended } - default { Write-Log -Type "ERROR" -Message """$Action"" operation is not supported" -ExitCode 1 } + "activate" { Invoke-ActivateAlteryx -Properties $Properties -Unattended:$Unattended } + "backup" { Invoke-BackupAlteryx -Properties $Properties -Unattended:$Unattended } + "deactivate" { Invoke-DeactivateAlteryx -Properties $Properties -Unattended:$Unattended } + "install" { Install-Alteryx -Properties $Properties -InstallationProperties $InstallationProperties -Unattended:$Unattended } + "restart" { Invoke-RestartAlteryx -Properties $Properties -Unattended:$Unattended } + "restore" { Invoke-RestoreAlteryx -Properties $Properties -Unattended:$Unattended } + "show" { Show-Configuration -Properties $Properties -InstallationProperties $InstallationProperties } + "start" { Invoke-StartAlteryx -Properties $Properties -Unattended:$Unattended } + "stop" { Invoke-StopAlteryx -Properties $Properties -Unattended:$Unattended } + "uninstall" { Uninstall-Alteryx -Properties $Properties -InstallationProperties $InstallationProperties -Unattended:$Unattended } + "upgrade" { Update-Alteryx -Properties $Properties -InstallationProperties $InstallationProperties -Unattended:$Unattended } + default { Write-Log -Type "ERROR" -Message """$Action"" operation is not supported" -ExitCode 1 } } } diff --git a/conf/default.ini b/conf/default.ini index 01a49f6..4d0e2f0 100644 --- a/conf/default.ini +++ b/conf/default.ini @@ -45,7 +45,7 @@ InstallAwareLog = false # Licensing system URL LicensingURL = whitelist.alteryx.com # License file -LicenseFile = +LicenseFile = # License email LicenseEmail = diff --git a/powershell/Invoke-ActivateAlteryx.ps1 b/powershell/Invoke-ActivateAlteryx.ps1 index 32efd09..836ffd2 100644 --- a/powershell/Invoke-ActivateAlteryx.ps1 +++ b/powershell/Invoke-ActivateAlteryx.ps1 @@ -16,7 +16,7 @@ function Invoke-ActivateAlteryx { File name: Invoke-ActivateAlteryx.ps1 Author: Florian Carrier Creation date: 2021-07-05 - Last modified: 2021-11-01 + Last modified: 2021-11-21 .LINK https://www.powershellgallery.com/packages/PSAYX @@ -49,23 +49,26 @@ function Invoke-ActivateAlteryx { $LicenseUtility = Get-AlteryxUtility -Utility "License" -Path $Properties.InstallationPath } Process { - Write-Log -Type "INFO" -Message "Activating Alteryx license" - # Check licensing system connectivity - Write-Log -Type "INFO" -Message "Checking licensing system connectivity" - if ((Test-HTTPStatus -URI $Properties.LicensingURL) -eq $true) { - # Activate license - if ($PSCmdlet.ShouldProcess("Alteryx", "Activate")) { + Write-Log -Type "INFO" -Message "Activating Alteryx" + if ($PSCmdlet.ShouldProcess("Alteryx", "Activate")) { + # Check licensing system connectivity + Write-Log -Type "INFO" -Message "Checking licensing system connectivity" + if ((Test-HTTPStatus -URI $Properties.LicensingURL) -eq $true) { # Check license key(s) - if (Test-Object -Path $Properties.LicenseFile -NotFound) { - Write-Log -Type "ERROR" -Message "License file path not found $($Properties.LicenseFile)" -ExitCode 1 + if (-Not (Find-Key -Hashtable $Properties -Key "LicenseKey")) { + # Read keys from license file + if (Test-Object -Path $Properties.LicenseFile -NotFound) { + Write-Log -Type "ERROR" -Message "License file path not found $($Properties.LicenseFile)" -ExitCode 1 + } + $Properties.LicenseKey = @(Get-Content -Path $Properties.LicenseFile) } - $Keys = Get-Content -Path $Properties.LicenseFile - if ($Keys.Count -gt 1) { - $Success = "$($Keys.Count) licenses were successfully activated" + # Count keys + if ($Properties.LicenseKey.Count -gt 1) { + $Success = "$($Properties.LicenseKey.Count) licenses were successfully activated" $Failure = "Licenses could not be activated" - $Keys = $Keys -join " " - } elseif ($Keys.Count -eq 1) { - $Success = "$($Keys.Count) license was successfully activated" + $Properties.LicenseKey = $Properties.LicenseKey -join " " + } elseif ($Properties.LicenseKey.Count -eq 1) { + $Success = "$($Properties.LicenseKey.Count) license was successfully activated" $Failure = "License could not be activated" } else { Write-Log -Type "ERROR" -Message "No license key was provided" -ExitCode 1 @@ -87,7 +90,7 @@ function Invoke-ActivateAlteryx { $Email = $Properties.LicenseEmail } # Call license utility - $Activation = Add-AlteryxLicense -Path $LicenseUtility -Key $Keys -Email $Email + $Activation = Add-AlteryxLicense -Path $LicenseUtility -Key $Properties.LicenseKey -Email $Email # Check activation status if (Select-String -InputObject $Activation -Pattern "License(s) successfully activated." -SimpleMatch -Quiet) { Write-Log -Type "CHECK" -Message $Success @@ -97,11 +100,9 @@ function Invoke-ActivateAlteryx { Write-Log -Type "ERROR" -Message $Failure -ExitCode 1 } } else { - Write-Log -Type "CHECK" -Message $Success + Write-Log -Type "ERROR" -Message "Unable to reach licensing system" + Write-Log -Type "WARN" -Message "Skipping license activation" } - } else { - Write-Log -Type "ERROR" -Message "Unable to reach licensing system" - Write-Log -Type "WARN" -Message "Skipping license activation" } } } \ No newline at end of file diff --git a/powershell/Invoke-DeactivateAlteryx.ps1 b/powershell/Invoke-DeactivateAlteryx.ps1 index f7a05b3..fcd51a1 100644 --- a/powershell/Invoke-DeactivateAlteryx.ps1 +++ b/powershell/Invoke-DeactivateAlteryx.ps1 @@ -54,12 +54,12 @@ function Invoke-DeactivateAlteryx { $LicenseUtility = Get-AlteryxUtility -Utility "License" -Path $Properties.InstallationPath } Process { - Write-Log -Type "INFO" -Message "Deactivating Alteryx license" + Write-Log -Type "INFO" -Message "Deactivating Alteryx" + if ($PSCmdlet.ShouldProcess("Alteryx", "Deactivate")) { # Check licensing system connectivity Write-Log -Type "INFO" -Message "Checking licensing system connectivity" if ((Test-HTTPStatus -URI $Properties.LicensingURL) -eq $true) { # Deactivate license - if ($PSCmdlet.ShouldProcess("Alteryx", "Deactivate")) { if ($All) { # Remove all license keys $Deactivation = Remove-AlteryxLicense -Path $LicenseUtility @@ -72,13 +72,20 @@ function Invoke-DeactivateAlteryx { } } else { # Check license key(s) - if (Test-Object -Path $Properties.LicenseFile -NotFound) { - Write-Log -Type "ERROR" -Message "License file path not found $($Properties.LicenseFile)" -ExitCode 1 + if (-Not (Find-Key -Hashtable $Properties -Key "LicenseKey")) { + # Read keys from license file + if (Test-Object -Path $Properties.LicenseFile -NotFound) { + Write-Log -Type "ERROR" -Message "License file path not found $($Properties.LicenseFile)" -ExitCode 1 + } + $Properties.LicenseKey = @(Get-Content -Path $Properties.LicenseFile) + } + if ($Properties.LicenseKey.Count -eq 0) { + Write-Log -Type "ERROR" -Message "No license key was provided" -ExitCode 1 } # Deactivate each key - $Keys = Get-Content -Path $Properties.LicenseFile - $Count = 0 - foreach ($Key in $Keys) { + $Count = 0 + foreach ($Key in $Properties.LicenseKey) { + Write-Log -Type "INFO" -Message "Deactivating license key $Key" $Dectivation = Remove-AlteryxLicense -Path $LicenseUtility -Key $Key # Check deactivation status if (Select-String -InputObject $Dectivation -Pattern "License(s) successfully removed." -SimpleMatch -Quiet) { @@ -89,26 +96,30 @@ function Invoke-DeactivateAlteryx { } } # Check outcome - if ($Keys.Count -gt 1) { - $Success = "$($Keys.Count) licenses were successfully deactivated" - $ErrorCount = $Keys.Count - $Count - $Failure = "$ErrorCount out of $($Keys.Count) licenses could not be deactivated" - } elseif ($Keys.Count -eq 1) { - $Success = "$($Keys.Count) license was successfully deactivated" + if ($Properties.LicenseKey.Count -gt 1) { + $Success = "$($Properties.LicenseKey.Count) licenses were successfully deactivated" + $ErrorCount = $Properties.LicenseKey.Count - $Count + if ($ErrorCount -eq $Properties.LicenseKey.Count) { + $Failure = "None of the licenses could not be deactivated" + } else { + $Failure = "$ErrorCount out of $($Properties.LicenseKey.Count) licenses could not be deactivated" + } + } elseif ($Properties.LicenseKey.Count -eq 1) { + $Success = "$($Properties.LicenseKey.Count) license was successfully deactivated" $Failure = "License could not be deactivated" - } else { - Write-Log -Type "ERROR" -Message "No license key was provided" -ExitCode 1 } - if ($Count -eq $Keys.Count) { + if ($Count -eq $Properties.LicenseKey.Count) { Write-Log -Type "CHECK" -Message $Success - } else { + } elseif ($ErrorCount -eq $Properties.LicenseKey.Count) { Write-Log -Type "ERROR" -Message $Failure + } else { + Write-Log -Type "WARN" -Message $Failure } } + } else { + Write-Log -Type "ERROR" -Message "Unable to reach licensing system" + Write-Log -Type "WARN" -Message "Skipping license deactivation" } - } else { - Write-Log -Type "ERROR" -Message "Unable to reach licensing system" - Write-Log -Type "WARN" -Message "Skipping license deactivation" } } } \ No newline at end of file From 22e4b572d174b163e0e92934b15157daf9871ad0 Mon Sep 17 00:00:00 2001 From: Florian Carrier Date: Sun, 21 Nov 2021 16:47:52 +0000 Subject: [PATCH 20/21] Create CHANGELOG.md --- CHANGELOG.md | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..ee6b638 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,50 @@ +# Changelog + +All notable changes to the [Alteryx deploy](https://github.com/Akaizoku/alteryx-deploy) project will be documented in this file. + +The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), +and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). + +## [1.1.0](https://github.com/Akaizoku/alteryx-deploy/releases/1.1.0) - 2021-11-21 + +### Added + +- `Invoke-StartAlteryx` now checks for release version to ensure compatibility +- Check connectivity to licensing system +- Disable Alteryx license action +- Disable Alteryx license(s) during uninstallation +- License key parameter + +### Changed + +- Disabled InstallAware logging by default to improve performances +- Improved documentation + +### Fixed + +- Fix conflict with version parameter and PowerShell modules versions +- Fix `Get-AlteryxUtility` function call following refactoring of [PSAYX](https://github.com/Akaizoku/PSAYX) + +## [1.0.0](https://github.com/Akaizoku/alteryx-deploy/releases/1.0.0) - 2021-09-20 + +Minimum viable product (MVP) release for the Alteryx automated deployment utility. + +### Added + +The following functions have been added: + +- Install-Alteryx +- Invoke-ActivateAlteryx +- Invoke-BackupAlteryx +- Invoke-RestartAlteryx +- Invoke-RestoreAlteryx +- Invoke-StartAlteryx +- Invoke-StopAlteryx +- Show-Configuration +- Uninstall-Alteryx +- Update-Alteryx + +The following files have been added: + +- LICENSE +- README.md From dd5db1ad466827fb60ec6dd281ce3bf3625d37d4 Mon Sep 17 00:00:00 2001 From: Florian Carrier Date: Sun, 21 Nov 2021 16:48:49 +0000 Subject: [PATCH 21/21] Update documentation --- README.md | 312 +++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 275 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index fd03af9..94cb4f0 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,45 @@ # Alteryx Deploy -Alteryx automated deployment utility. +`alteryx-deploy` is a small PowerShell utility for the automation of the deployment and maintenance of Alteryx. ## Table of contents -- [Usage](#usage) -- [Process](#process) - - [Installation](#installation) - - [Upgrade](#upgrade) - - [Uninstallation](#uninstallation) - - [Activate](#activate) - - [Backup](#backup) - - [Restore](#restore) - - [Start](#start) - - [Stop](#stop) - - [Restart](#restart) -- [Dependencies](#dependencies) +1. [Usage](#usage) +2. [Pre-requisites](#pre-requisites) + 1. [Permissions](#permissions) + 2. [PowerShell version](#powershell-version) + 3. [PowerShell Modules](#powershell-modules) + 4. [Alteryx](#alteryx) +3. [Configuration](#configuration) + 1. [Script configuration](#script-configuration) + 2. [Installation configuration](#installation-configuration) +4. [Parameters](#parameters) + 1. [Mandatory](#mandatory) + 1. [Action](#action) + 2. [Optional](#optional) + 1. [Version](#version) + 2. [Backup Path](#backup-path) + 3. [Product](#product) + 4. [License Key](#license-key) + 5. [Unattended](#unattended) + 6. [WhatIf](#whatif) + 7. [Debug](#debug) +5. [Process](#process) + 1. [Installation](#installation) + 2. [Upgrade](#upgrade) + 3. [Uninstallation](#uninstallation) + 4. [Activation](#activation) + 5. [Deactivation](#deactivation) + 6. [Backup](#backup) + 7. [Restore](#restore) + 8. [Start](#start) + 9. [Stop](#stop) + 10. [Restart](#restart) +6. [Logs](#logs) +7. [Dependencies](#dependencies) +8. [Compatibility](#compatibility) +9. [Known issues](#known-issues) + 1. [Access to the cloud file is denied](#access-to-the-cloud-file-is-denied) ## Usage @@ -23,28 +47,170 @@ Alteryx automated deployment utility. 2. If needed, add custom configuration to the `custom.ini` configuration file in the same configuration folder; 3. Update the installation configuration in the file `install.ini`; 4. Run the `Deploy-Alteryx.ps1` script with the corresponding action parameter; - - backup: backup the Alteryx application database - - configure: configure the Alteryx application - - install: install the Alteryx application - - restart: restart the Alteryx application - - restore: restore a backup of the Alteryx application database - - show: display the script configuration - - start: start the Alteryx application - - stop: stop the Alteryx application - - uninstall: uninstall the Alteryx application - - upgrade: upgrade the Alteryx application + - activate: activate the Alteryx application license + - backup: backup the Alteryx application database + - deactivate: deactivate the Alteryx application license + - install: install the Alteryx application + - restart: restart the Alteryx application + - restore: restore a backup of the Alteryx application database + - show: display the script configuration + - start: start the Alteryx application + - stop: stop the Alteryx application + - uninstall: uninstall the Alteryx application + - upgrade: upgrade the Alteryx application 5. Check the logs. +## Pre-requisites + +### Permissions + +This script requires administrator rights to be run. + +### PowerShell version + +This script requires [PowerShell version 5.0](https://docs.microsoft.com/en-us/powershell/scripting/windows-powershell/whats-new/what-s-new-in-windows-powershell-50) or later to be run. + +### PowerShell Modules + +This script makes use of functions from the PowerShell Tool Kit ([PSTK]) module and Alteryx PowerShell ([PSAYX]) module as described in the [dependencies section](#dependencies). + +The modules must be [installed](https://docs.microsoft.com/en-us/powershell/module/powershellget/install-module) on the local machine, or placed in the `lib` folder at the root of the script directory. + +Example script structure with embedded dependencies: + +```cmd +.alteryx-deploy ++---conf ++---lib +| +---PSAYX +| \---PSTK ++---powershell +\---res +``` + +### Alteryx + +Alteryx installation files must be made available in the source directory (default `D:\Sources`). See the [compatibility section](#compatibility) for more information about the supported versions. + +You can download them from . + +Please refer to [Alteryx system requirements](https://help.alteryx.com/20213/server/system-requirements) for minimum machine requirements. + +## Configuration + +### Script configuration + +The default configuration of the utility is stored into `default.ini`. This file should not be amended. All custom configuration must be made in the `custom.ini` file. Any customisation done in that file will override the default values. + +Below is an example of custom configuration file: + +```ini +[Paths] +# Sources directory +SrcDirectory = D:\Alteryx\Sources +# Alteryx installation directory +InstallationPath = D:\Alteryx\Server +# Backup directory +BackupDirectory = D:\Alteryx\Server\backup +# Data packages installation directory +DataPackagesPath = D:\Alteryx\Data +``` + +### Installation configuration + +To configure which products should be installed, edit the `install.ini` configuration file located in the `conf` directory. + +Below is an example of installation configuration file: + +```ini +[Installation] +Server = true +PredictiveTools = true +IntelligenceSuite = true +DataPackages = false +``` + +## Parameters + +In addition to the configuration files presented above, parameters will define the operation performed during the execution. + +### Mandatory + +This section lists the mandatory parameters that must be specified to run the script. + +#### Action + +The `Action` parameter corresponds to the operation to perform. + +Eleven options are available: + +- activate: activate the Alteryx application license +- backup: backup the Alteryx application database +- deactivate: deactivate the Alteryx application license +- install: install the Alteryx application +- restart: restart the Alteryx application +- restore: restore a backup of the Alteryx application database +- show: display the script configuration +- start: start the Alteryx application +- stop: stop the Alteryx application +- uninstall: uninstall the Alteryx application +- upgrade: upgrade the Alteryx application + +### Optional + +This section lists the optional parameters that can be specified at runtime. + +#### Version + +The `Version` parameter is optional and enables the user to overwrite the version set in the configuration files. + +#### Backup Path + +The `BackupPath` parameter is optional and enables the user to specify a backup file to use for a database restore. + +#### Product + +The `Product` parameter is optional and enables the user to define if Alteryx Designer should be installed instead of the default Alteryx Server. + +#### License Key + +The `LicenseKey` parameter is optional and enables the user to specify license keys at runtime. + +#### Unattended + +The `Unattended` switch enables the user to specify that the script should run without any interaction. + +If this switch is not used, the setup wizard from Alteryx will be displayed and the user will need to go through the installation steps manually. + +#### WhatIf + +The `WhatIf` switch enables the user to test a command without executing the actions of the command. This means that changes are not applied but processing steps are simply displayed. + +#### Debug + +The `Debug` standard switch enable the display of additional log information. + +A lot of useful debug messages have been defined. Should you wish to enable them, it is recommended to make use of the [`$DebugPreference`](https://docs.microsoft.com/en-us/powershell/module/Microsoft.PowerShell.Core/About/about_Preference_Variables#debugpreference) variable. + +```powershell +$DebugPreference = "Continue" +``` + ## Process -Below are the execution steps of the `Deploy-Alteryx.ps1` script. +Below are the execution steps of the `.\Deploy-Alteryx.ps1` script. + +**Remarks**: + +1. The execution steps will vary depending on the configuration of the scripts. +2. The steps described below correspond to a complete and successfull execution of the script. ### Installation Below are the steps to install the Alteryx application. ```powershell -Deploy-Alteryx.ps1 -action "install" +.\Deploy-Alteryx.ps1 -Action "install" ``` 1. Install Alteryx Server (or Designer if specified with the `-Product` parameter; @@ -57,7 +223,7 @@ Deploy-Alteryx.ps1 -action "install" Below are the steps to upgrade the Alteryx application. ```powershell -Deploy-Alteryx.ps1 -action "upgrade" +.\Deploy-Alteryx.ps1 -Action "upgrade" ``` 1. Backup Alteryx database and configuration files; @@ -72,7 +238,7 @@ Deploy-Alteryx.ps1 -action "upgrade" Below are the steps to uninstall the Alteryx application. ```powershell -Deploy-Alteryx.ps1 -action "uninstall" +.\Deploy-Alteryx.ps1 -Action "uninstall" ``` 1. Uninstall Alteryx Server (or Designer if specified with the `-Product` parameter. @@ -82,24 +248,36 @@ Deploy-Alteryx.ps1 -action "uninstall" 1. The uninstallation process requires the original installation executable file. 2. The uninstallation of Alteryx Server does also remove all dependencies such as Precdictive Tools, Intelligence Suite, etc. -### Activate +### Activation Below are the steps to activate (license) the Alteryx application. ```powershell -Deploy-Alteryx.ps1 -action "activate" +.\Deploy-Alteryx.ps1 -Action "activate" +``` + +1. Check licensing system connectivity (); +2. Check license file path; +3. Activate Alteryx licenses. + +### Deactivation + +Below are the steps to deactivate (license) the Alteryx application. + +```powershell +.\Deploy-Alteryx.ps1 -Action "deactivate" ``` 1. Check licensing system connectivity (); 2. Check license file path; -3. Activate Alteryx application. +3. Deactivate Alteryx licenses. ### Backup Below are the steps to backup the Alteryx application database. ```powershell -Deploy-Alteryx.ps1 -action "backup" +.\Deploy-Alteryx.ps1 -Action "backup" ``` 1. Check Alteryx Service status and stop it if it is running; @@ -114,7 +292,7 @@ Deploy-Alteryx.ps1 -action "backup" Below are the steps to restore the Alteryx application database. ```powershell -Deploy-Alteryx.ps1 -action "restore" +.\Deploy-Alteryx.ps1 -Action "restore" ``` 1. Check Alteryx Service status and stop it if it is running; @@ -132,7 +310,7 @@ Deploy-Alteryx.ps1 -action "restore" Below are the steps to start the Alteryx application. ```powershell -Deploy-Alteryx.ps1 -action "start" +.\Deploy-Alteryx.ps1 -Action "start" ``` 1. Check Alteryx Service status; @@ -144,7 +322,7 @@ Deploy-Alteryx.ps1 -action "start" Below are the steps to stop the Alteryx application. ```powershell -Deploy-Alteryx.ps1 -action "stop" +.\Deploy-Alteryx.ps1 -Action "stop" ``` 1. Check Alteryx Service status; @@ -156,15 +334,75 @@ Deploy-Alteryx.ps1 -action "stop" Below are the steps to restart the Alteryx application. ```powershell -Deploy-Alteryx.ps1 -action "restart" +.\Deploy-Alteryx.ps1 -Action "restart" ``` 1. Stop Alteryx Service; 2. Start Alteryx Service. +## Logs + +Transcript log files are generated in the log directory of the script. + +- The naming convention is as follows: `_-Alteryx.log` +- The format of the log is: `\t\t` + +Additional log files are generated during the installation, upgrade, or uninstallation of Alteryx as an XML file in teh same log directory. + +- The naming convention is as follows: `_.log` + +Below is an example of a successful installation log: + +```log +2021-11-15 10:09:36 INFO Installation of Alteryx Server 2021.3.3.63061 +2021-11-15 10:09:36 INFO Installing Alteryx Server +2021-11-15 10:34:14 CHECK Alteryx Server installed successfully +2021-11-15 10:34:14 WARN Do not forget to configure system settings +2021-11-15 10:34:14 INFO Installing Predictive Tools +2021-11-15 10:36:45 CHECK Predictive Tools installed successfully +2021-11-15 10:36:45 INFO Installing Intelligence Suite +2021-11-15 10:49:36 CHECK Intelligence Suite installed successfully +2021-11-15 10:49:36 INFO Activating Alteryx license +2021-11-15 10:49:36 INFO Checking licensing system connectivity +2021-11-15 10:49:54 CHECK 3 licenses were successfully activated +2021-11-15 10:49:54 CHECK Alteryx Server 2021.3.3.63061 installed successfully +``` + ## Dependencies This module depends on the usage of functions provided by two PowerShell modules: -1. [PowerShell Tool Kit (PSTK) module (version 1.2.4)](https://www.powershellgallery.com/packages/PSTK) -2. [Alteryx PowerShell (PSAYX) module (version 1.0.0)](https://www.powershellgallery.com/packages/PSAYX) +1. PowerShell Tool Kit ([PSTK]) module (version 1.2.5) +2. Alteryx PowerShell ([PSAYX]) module (version 1.0.1) + +## Compatibility + +Below are listed the compatible versions for each of the release. + +Only the first version supported is listed. Later releases should also be compatible as long as no breaking change has been introduced. Please refer to the [Alteryx release notes](https://help.alteryx.com/release-notes) for more information. + +| `alteryx-deploy` | Alteryx | PowerShell | [PSTK] | [PSAYX] | +| ---------------- | -------- | ---------- | ------ | ------- | +| [1.0.0] | [2021.3] | 5.0 | 1.2.4 | 1.0.0 | +| [1.1.0] | [2021.3] | 5.0 | 1.2.5 | 1.0.1 | + +## Known issues + +### Access to the cloud file is denied + +This error can occur during the backup of the application when [OneDrive](https://docs.microsoft.com/en-us/onedrive/one-drive-sync) is installed and is synchronising the temporary backup files while the script attempts to remove them (see [PowerShell issue #9246](https://github.com/PowerShell/PowerShell/issues/9246) for more information). + +This has no impact on the backup process and only affects temporary files used to generate the backup archive. + +> 2021-11-21 02:12:55 INFO Remove staging backup folder +> +> 2021-11-21 02:12:55 ERROR Access to the cloud file is denied + +It can be prevented by configuring a temporary directory (`TempDirectory`) that is not synchronised by OneDrive. Temporary files can also be removed manually. + + +[PSTK]: https://www.powershellgallery.com/packages/PSTK +[PSAYX]: https://www.powershellgallery.com/packages/PSAYX +[1.0.0]:https://github.com/Akaizoku/alteryx-deploy/releases/1.0.0 +[1.1.0]:https://github.com/Akaizoku/alteryx-deploy/releases/1.1.0 +[2021.3]:https://help.alteryx.com/release-notes/server/server-20213-release-notes