diff --git a/Deploy-Alteryx.ps1 b/Deploy-Alteryx.ps1 index bca6677..4b66d64 100644 --- a/Deploy-Alteryx.ps1 +++ b/Deploy-Alteryx.ps1 @@ -2,22 +2,23 @@ #Requires -RunAsAdministrator <# - .SYNOPSIS - Deploy Alteryx + .SYNOPSIS + Deploy Alteryx - .DESCRIPTION - Deploy and configure Alteryx + .DESCRIPTION + Deploy and configure Alteryx - .PARAMETER Action - The action parameter corresponds to the operation to perform. + .PARAMETER Action + The action parameter corresponds to the operation to perform. + + Eleven options are available: - Eleven options are available: - - activate: activate the Alteryx application license - backup: backup the Alteryx application database - configure: configure the Alteryx application - deactivate: deactivate the Alteryx application license - install: install the Alteryx application + - repair: repair the Alteryx application database - patch: patch upgrade the Alteryx application - restart: restart the Alteryx application - restore: restore a backup of the Alteryx application database @@ -27,29 +28,29 @@ - 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. + .PARAMETER Unattended + The unattended switch define if the script should run in silent mode without any user interaction. .NOTES File name: Deploy-Alteryx.ps1 Author: Florian Carrier Creation date: 2021-06-13 - Last modified: 2022-11-25 + Last modified: 2022-04-27 Dependencies: - PowerShell Tool Kit (PSTK) - Alteryx PowerShell Module (PSAYX) - .LINK - https://github.com/Akaizoku/alteryx-deploy + .LINK + https://github.com/Akaizoku/alteryx-deploy - .LINK - https://www.powershellgallery.com/packages/PSTK + .LINK + https://www.powershellgallery.com/packages/PSTK - .LINK - https://www.powershellgallery.com/packages/PSAYX + .LINK + https://www.powershellgallery.com/packages/PSAYX #> [CmdletBinding ( - SupportsShouldProcess = $true + SupportsShouldProcess = $true )] # Static parameters @@ -62,6 +63,9 @@ Param ( [ValidateSet ( "activate", "backup", + "deactivate", + "install", + "repair", "configure", "deactivate", "install", @@ -105,10 +109,10 @@ Param ( [System.String] $Product = "Server", [Parameter ( - Position = 5, - Mandatory = $false, - HelpMessage = "License key(s)" - )] + 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", @@ -116,140 +120,141 @@ Param ( )] [System.String[]] $LicenseKey, - [Parameter ( - HelpMessage = "Run script in non-interactive mode" - )] - [Switch] - $Unattended + [Parameter ( + HelpMessage = "Run script in non-interactive mode" + )] + [Switch] + $Unattended ) Begin { - # ---------------------------------------------------------------------------- - # * Global preferences - # ---------------------------------------------------------------------------- - $ErrorActionPreference = "Stop" - $ProgressPreference = "Continue" + # ---------------------------------------------------------------------------- + # * Global preferences + # ---------------------------------------------------------------------------- + $ErrorActionPreference = "Stop" + $ProgressPreference = "Continue" - # ---------------------------------------------------------------------------- - # * Global variables - # ---------------------------------------------------------------------------- - # General - $ISOTimeStamp = Get-Date -Format "yyyyMMdd_HHmmss" + # ---------------------------------------------------------------------------- + # * Global variables + # ---------------------------------------------------------------------------- + # General + $ISOTimeStamp = Get-Date -Format "yyyyMMdd_HHmmss" - # Configuration - $LibDirectory = Join-Path -Path $PSScriptRoot -ChildPath "lib" - $ConfDirectory = Join-Path -Path $PSScriptRoot -ChildPath "conf" - $DefaultProperties = "default.ini" - $CustomProperties = "custom.ini" + # Configuration + $LibDirectory = Join-Path -Path $PSScriptRoot -ChildPath "lib" + $ConfDirectory = Join-Path -Path $PSScriptRoot -ChildPath "conf" + $DefaultProperties = "default.ini" + $CustomProperties = "custom.ini" - # ---------------------------------------------------------------------------- - # * Modules - # ---------------------------------------------------------------------------- - # Dependencies + # ---------------------------------------------------------------------------- + # * Modules + # ---------------------------------------------------------------------------- + # Dependencies $Modules = [Ordered]@{ - "PSTK" = "1.2.4" - "PSAYX" = "1.0.1" + "PSTK" = "1.2.4" + "PSAYX" = "1.0.1" } # 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 - $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." + # Check if package is available locally + Import-Module -Name (Join-Path -Path $LibDirectory -ChildPath $Module.Name) -MinimumVersion $Module.Value -ErrorAction "Stop" -Force + $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 + # Otherwise check if module is installed Import-Module -Name $Module.Name -MinimumVersion $Module.Value -ErrorAction "Stop" -Force - $ModuleVersion = (Get-Module -Name $Module.Name).Version - Write-Log -Type "CHECK" -Object "The $($Module.Name) module (v$ModuleVersion) 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" } } } - # ---------------------------------------------------------------------------- - # * Script configuration - # ---------------------------------------------------------------------------- - # General settings - $Properties = Get-Properties -File $DefaultProperties -Directory $ConfDirectory -Custom $CustomProperties - # Resolve relative paths - Write-Log -Type "DEBUG" -Message "Script structure check" - $Properties = Get-Path -PathToResolve $Properties.RelativePaths -Hashtable $Properties -Root $PSScriptRoot + # ---------------------------------------------------------------------------- + # * Script configuration + # ---------------------------------------------------------------------------- + # General settings + $Properties = Get-Properties -File $DefaultProperties -Directory $ConfDirectory -Custom $CustomProperties + # Resolve relative paths + Write-Log -Type "DEBUG" -Message "Script structure check" + $Properties = Get-Path -PathToResolve $Properties.RelativePaths -Hashtable $Properties -Root $PSScriptRoot - # Transcript - $FormattedAction = Format-String -String $Action -Format "TitleCase" - $Transcript = Join-Path -Path $Properties.LogDirectory -ChildPath "${ISOTimeStamp}_${FormattedAction}-Alteryx.log" - Start-Script -Transcript $Transcript + # Transcript + $FormattedAction = Format-String -String $Action -Format "TitleCase" + $Transcript = Join-Path -Path $Properties.LogDirectory -ChildPath "${ISOTimeStamp}_${FormattedAction}-Alteryx.log" + Start-Script -Transcript $Transcript - # Log command line - Write-Log -Type "DEBUG" -Message $PSCmdlet.MyInvocation.Line + # Log command line + Write-Log -Type "DEBUG" -Message $PSCmdlet.MyInvocation.Line - # ------------------------------------------------------------------------------ - # * Checks - # ------------------------------------------------------------------------------ - # Ensure shell is running as 64 bit process - if ([Environment]::Is64BitProcess -eq $false) { - Write-Log -Type "ERROR" -Message "PowerShell is running as a 32-bit process" -ExitCode 1 - } + # ------------------------------------------------------------------------------ + # * Checks + # ------------------------------------------------------------------------------ + # Ensure shell is running as 64 bit process + if ([Environment]::Is64BitProcess -eq $false) { + Write-Log -Type "ERROR" -Message "PowerShell is running as a 32-bit process" -ExitCode 1 + } - # ---------------------------------------------------------------------------- - # * Functions - # ---------------------------------------------------------------------------- - # Load PowerShell functions - $Functions = Get-ChildItem -Path $Properties.PSDirectory - foreach ($Function in $Functions) { - Write-Log -Type "DEBUG" -Message "Import $($Function.Name)" - try { . $Function.FullName } - catch { Write-Error -Message "Failed to import function $($Function.FullName): $PSItem" } - } + # ---------------------------------------------------------------------------- + # * Functions + # ---------------------------------------------------------------------------- + # Load PowerShell functions + $Functions = Get-ChildItem -Path $Properties.PSDirectory + foreach ($Function in $Functions) { + Write-Log -Type "DEBUG" -Message "Import $($Function.Name)" + try { . $Function.FullName } + catch { Write-Error -Message "Failed to import function $($Function.FullName): $PSItem" } + } - # ---------------------------------------------------------------------------- - # * Variables - # ---------------------------------------------------------------------------- - # (Re)load environment variables - # Write-Log -Type "DEBUG" -Message "Load environment variables" - # $EnvironmentVariables = @() - # foreach ($EnvironmentVariable in $EnvironmentVariables) { - # Sync-EnvironmentVariable -Name $EnvironmentVariable -Scope $Properties.EnvironmentVariableScope | Out-Null - # } + # ---------------------------------------------------------------------------- + # * Variables + # ---------------------------------------------------------------------------- + # (Re)load environment variables + Write-Log -Type "DEBUG" -Message "Load environment variables" + $EnvironmentVariables = @() + foreach ($EnvironmentVariable in $EnvironmentVariables) { + Sync-EnvironmentVariable -Name $EnvironmentVariable -Scope $Properties.EnvironmentVariableScope | Out-Null + } - # ---------------------------------------------------------------------------- - # * Options - # ---------------------------------------------------------------------------- - # Installation properties - $ValidateSet = @( - "Server" - "PredictiveTools" - "IntelligenceSuite" - "DataPackages" - ) - $InstallationProperties = Get-Properties -File $Properties.InstallationOptions -Directory $Properties.ConfDirectory -ValidateSet $ValidateSet - $InstallationProperties.Add("Product", $Product) - # Optional parameters - if ($PSBoundParameters.ContainsKey("Version")) { - $Properties.Version = $Version - } - if ($PSBoundParameters.ContainsKey("BackupPath")) { - $Properties.Add("BackupPath", $BackupPath) - } + # ---------------------------------------------------------------------------- + # * Options + # ---------------------------------------------------------------------------- + # Installation properties + $ValidateSet = @( + "Server" + "PredictiveTools" + "IntelligenceSuite" + "DataPackages" + ) + $InstallationProperties = Get-Properties -File $Properties.InstallationOptions -Directory $Properties.ConfDirectory -ValidateSet $ValidateSet + $InstallationProperties.Add("Product", $Product) + # Optional parameters + if ($PSBoundParameters.ContainsKey("Version")) { + $Properties.Version = $Version + } + 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)) - } + $Properties.Add("LicenseKey", @($LicenseKey)) + } } Process { - # Check operation to perform - switch ($Action) { + # Check operation to perform + switch ($Action) { "activate" { Invoke-ActivateAlteryx -Properties $Properties -Unattended:$Unattended } "backup" { Invoke-BackupAlteryx -Properties $Properties -Unattended:$Unattended } "configure" { Set-Configuration -Properties $Properties -Unattended:$Unattended } "deactivate" { Invoke-DeactivateAlteryx -Properties $Properties -Unattended:$Unattended } "install" { Install-Alteryx -Properties $Properties -InstallationProperties $InstallationProperties -Unattended:$Unattended } + "repair" { Repair-Alteryx -Properties $Properties -Unattended:$Unattended } "patch" { Invoke-PatchAlteryx -Properties $Properties -Unattended:$Unattended } "restart" { Invoke-RestartAlteryx -Properties $Properties -Unattended:$Unattended } "restore" { Invoke-RestoreAlteryx -Properties $Properties -Unattended:$Unattended } @@ -259,10 +264,10 @@ Process { "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 } - } + } } End { - # Stop script and transcript - Stop-Script -ExitCode 0 + # Stop script and transcript + Stop-Script -ExitCode 0 } \ No newline at end of file diff --git a/README.md b/README.md index f9f0aa4..d3f3a52 100644 --- a/README.md +++ b/README.md @@ -96,7 +96,7 @@ Alteryx installation files must be made available in the source directory (defau You can download them from . -Please refer to [Alteryx system requirements](https://help.alteryx.com/20213/server/system-requirements) for minimum machine requirements. +Please refer to [Alteryx system requirements](https://help.alteryx.com/current/server/system-requirements) for minimum machine requirements. ## Configuration @@ -215,7 +215,7 @@ Below are the steps to install the Alteryx application. .\Deploy-Alteryx.ps1 -Action "install" ``` -1. Install Alteryx Server (or Designer if specified with the `-Product` parameter; +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). @@ -229,7 +229,7 @@ Below are the steps to upgrade the Alteryx application. ``` 1. Backup Alteryx database and configuration files; -2. Upgrade Alteryx Server (or Designer if specified with the `-Product` parameter; +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); @@ -243,7 +243,7 @@ Below are the steps to uninstall the Alteryx application. .\Deploy-Alteryx.ps1 -Action "uninstall" ``` -1. Uninstall Alteryx Server (or Designer if specified with the `-Product` parameter. +1. Uninstall Alteryx Server (or Designer if specified with the `-Product` parameter). **Warnings:** @@ -258,7 +258,7 @@ Below are the steps to activate (license) the Alteryx application. .\Deploy-Alteryx.ps1 -Action "activate" ``` -1. Check licensing system connectivity (); +1. Check licensing system connectivity ([whitelist.alteryx.com]); 2. Check license file path; 3. Activate Alteryx licenses. @@ -270,7 +270,7 @@ Below are the steps to deactivate (license) the Alteryx application. .\Deploy-Alteryx.ps1 -Action "deactivate" ``` -1. Check licensing system connectivity (); +1. Check licensing system connectivity ([whitelist.alteryx.com]); 2. Check license file path; 3. Deactivate Alteryx licenses. @@ -393,6 +393,10 @@ Only the first version supported is listed. Later releases should also be compat ## Known issues +Below are listed known issues that might occur depending on your environment. + +Please report any new problem using the [GitHub repository issue page](https://github.com/Akaizoku/alteryx-deploy/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). @@ -413,3 +417,4 @@ It can be prevented by configuring a temporary directory (`TempDirectory`) that [1.1.1]:https://github.com/Akaizoku/alteryx-deploy/releases/1.1.1 [1.1.2]:https://github.com/Akaizoku/alteryx-deploy/releases/1.1.2 [2021.3]:https://help.alteryx.com/release-notes/server/server-20213-release-notes +[whitelist.alteryx.com]:(whitelist.alteryx.com) diff --git a/conf/default.ini b/conf/default.ini index ee86e39..248f9d3 100644 --- a/conf/default.ini +++ b/conf/default.ini @@ -19,7 +19,7 @@ SrcDirectory = C:\Sources # Alteryx installation directory InstallationPath = C:\Program Files\Alteryx # Backup directory -BackupDirectory = C:\Program Files\Alteryx\Backup +BackupDirectory = C:\ProgramData\Alteryx\Backup # Predictive Tools directory RDirectory = RInstaller # Data packages installation directory @@ -35,7 +35,7 @@ InstallationOptions = install.ini # Installation language Language = English # Version -Version = 2021.3.3.63061 +Version = 2021.4.2.02731 # SSL/TLS EnableSSL = false # InstallAware log @@ -56,6 +56,7 @@ LicenseEmail = [Ports] HTTPPort = 80 HTTPSPort = 443 +MongoDBPort = 27018 [Checks] RelativePaths = ConfDirectory, PSDirectory, TempDirectory, LogDirectory, ResDirectory diff --git a/powershell/Install-Alteryx.ps1 b/powershell/Install-Alteryx.ps1 index 677cfd7..3e63892 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-12-08 + Last modified: 2022-04-19 .LINK https://www.powershellgallery.com/packages/PSAYX @@ -54,6 +54,8 @@ function Install-Alteryx { Begin { # Get global preference variables Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState + # Log function call + Write-Log -Type "DEBUG" -Message $MyInvocation.ScriptName # Variables $ISOTimeStamp = Get-Date -Format "yyyyMMdd_HHmmss" $Tags = [Ordered]@{"Version" = $Properties.Version} @@ -82,6 +84,12 @@ 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-Object -Path $ServerPath -NotFound) { + # Workaround for files not following naming convention due to duplicate pipeline runs + $Workaround = [Ordered]@{"Version" = [System.String]::Concat($Properties.Version, "_1")} + $ServerFileName = Set-Tags -String $ServerInstaller -Tags (Resolve-Tags -Tags $Workaround -Prefix "<" -Suffix ">") + $ServerPath = Join-Path -Path $Properties.SrcDirectory -ChildPath $ServerFileName + } Write-Log -Type "INFO" -Message "Installing Alteryx $($InstallationProperties.Product)" if ($PSCmdlet.ShouldProcess($ServerPath, "Install")) { if (Test-Path -Path $ServerPath) { @@ -160,6 +168,12 @@ 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-Object -Path $AISPath -NotFound) { + # Workaround for files not following naming convention due to duplicate pipeline runs + $Workaround = [Ordered]@{"Version" = [System.String]::Concat($Properties.Version, "_1")} + $AISFileName = Set-Tags -String $AISInstaller -Tags (Resolve-Tags -Tags $Workaround -Prefix "<" -Suffix ">") + $AISPath = Join-Path -Path $Properties.SrcDirectory -ChildPath $AISFileName + } Write-Log -Type "INFO" -Message "Installing Intelligence Suite" if ($PSCmdlet.ShouldProcess($AISPath, "Install")) { if (Test-Path -Path $AISPath) { diff --git a/powershell/Invoke-ActivateAlteryx.ps1 b/powershell/Invoke-ActivateAlteryx.ps1 index ef657f1..aca5aea 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-12-09 + Last modified: 2022-04-19 .LINK https://www.powershellgallery.com/packages/PSAYX @@ -45,6 +45,8 @@ function Invoke-ActivateAlteryx { Begin { # Get global preference variables Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState + # Log function call + Write-Log -Type "DEBUG" -Message $MyInvocation.ScriptName # License utility $LicenseUtility = Get-AlteryxUtility -Utility "License" -Path $Properties.InstallationPath } diff --git a/powershell/Invoke-BackupAlteryx.ps1 b/powershell/Invoke-BackupAlteryx.ps1 index c98bc47..6b72518 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-22 + Last modified: 2022-04-19 #> [CmdletBinding ( SupportsShouldProcess = $true @@ -33,6 +33,8 @@ function Invoke-BackupAlteryx { Begin { # Get global preference vrariables Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState + # Log function call + Write-Log -Type "DEBUG" -Message $MyInvocation.ScriptName # Variables $ISOTimeStamp = Get-Date -Format "yyyyMMdd_HHmmss" $BackupPath = Join-Path -Path $Properties.BackupDirectory -ChildPath "${ISOTimeStamp}_Alteryx_Server_$($Properties.Version).zip" @@ -53,7 +55,7 @@ function Invoke-BackupAlteryx { } } # Configuration files - $ConfigurationFiles = [Ordered]@{ + $XMLConfigurationFiles = [Ordered]@{ "RunTimeSettings" = "RuntimeSettings.xml" "SystemAlias" = "Engine\SystemAlias.xml" "SystemConnections" = "Engine\SystemConnections.xml" @@ -103,16 +105,27 @@ function Invoke-BackupAlteryx { if ($Backup.Configuration -eq $true) { Write-Log -Type "INFO" -Message "Backup configuration files" if ($PSCmdlet.ShouldProcess("Configuration files", "Back-up")) { + # XML configuration files $ProgramData = Join-Path -Path ([Environment]::GetEnvironmentVariable("ProgramData")) -ChildPath "Alteryx" - foreach ($ConfigurationFile in $ConfigurationFiles.GetEnumerator()) { - $FilePath = Join-Path -Path $ProgramData -ChildPath $ConfigurationFile.Value + foreach ($XMLConfigurationFile in $XMLConfigurationFiles.GetEnumerator()) { + $FilePath = Join-Path -Path $ProgramData -ChildPath $XMLConfigurationFile.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 "WARN" -Message "$($XMLConfigurationFile.Name) configuration file could not be found" Write-Log -Type "DEBUG" -Message $FilePath } } + # Extra configuration files + $ConfigurationFiles = Get-Object -Path (Join-Path -Path $Properties.InstallationPath -ChildPath "bin\server\config") -ChildItem -Type "File" + foreach ($ConfigurationFile in $ConfigurationFiles) { + if (Test-Object -Path $ConfigurationFile.FullName) { + Copy-Object -Path $ConfigurationFile.FullName -Destination "$TempBackupPath\Config" -Force + } else { + Write-Log -Type "WARN" -Message "$($ConfigurationFile.BaseName) configuration file could not be found" + Write-Log -Type "DEBUG" -Message $ConfigurationFile.FullName + } + } } } # ---------------------------------------------------------------------------- diff --git a/powershell/Invoke-DeactivateAlteryx.ps1 b/powershell/Invoke-DeactivateAlteryx.ps1 index 18c117d..3216c89 100644 --- a/powershell/Invoke-DeactivateAlteryx.ps1 +++ b/powershell/Invoke-DeactivateAlteryx.ps1 @@ -50,6 +50,8 @@ function Invoke-DeactivateAlteryx { Begin { # Get global preference variables Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState + # Log function call + Write-Log -Type "DEBUG" -Message $MyInvocation.ScriptName # License utility $LicenseUtility = Get-AlteryxUtility -Utility "License" -Path $Properties.InstallationPath } diff --git a/powershell/Invoke-RestartAlteryx.ps1 b/powershell/Invoke-RestartAlteryx.ps1 index d82e9b0..e3a8d3d 100644 --- a/powershell/Invoke-RestartAlteryx.ps1 +++ b/powershell/Invoke-RestartAlteryx.ps1 @@ -10,7 +10,7 @@ function Invoke-RestartAlteryx { File name: Invoke-RestartAlteryx.ps1 Author: Florian Carrier Creation date: 2021-08-27 - Last modified: 2021-08-30 + Last modified: 2022-04-19 #> [CmdletBinding ()] Param ( @@ -31,6 +31,8 @@ function Invoke-RestartAlteryx { Begin { # Get global preference vrariables Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState + # Log function call + Write-Log -Type "DEBUG" -Message $MyInvocation.ScriptName } Process { Write-Log -Type "CHECK" -Message "Restarting Alteryx Service" diff --git a/powershell/Invoke-RestoreAlteryx.ps1 b/powershell/Invoke-RestoreAlteryx.ps1 index aeef961..af91c12 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-12-10 + Last modified: 2022-04-19 Comment: User configuration files are out of scope of this procedure: - %APPDATA%\Alteryx\Engine\UserConnections.xml - %APPDATA%\Alteryx\Engine\UserAlias.xml @@ -39,6 +39,8 @@ function Invoke-RestoreAlteryx { Begin { # Get global preference vrariables Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState + # Log function call + Write-Log -Type "DEBUG" -Message $MyInvocation.ScriptName # Variables $ServicePath = Join-Path -Path $Properties.InstallationPath -ChildPath "bin\AlteryxService.exe" $Staging = $false @@ -122,6 +124,7 @@ function Invoke-RestoreAlteryx { # Restore configuration files if ($Restore.Configuration -eq $true) { Write-Log -Type "INFO" -Message "Restore configuration files" + # TODO restore extra configuration files if ($PSCmdlet.ShouldProcess("Configuration files", "Restore")) { $BackupConfigurationFiles = Get-Object -Path $BackupPath -ChildItem -Filter "*.xml" foreach ($ConfigurationFile in $ConfigurationFiles.GetEnumerator()) { diff --git a/powershell/Invoke-StartAlteryx.ps1 b/powershell/Invoke-StartAlteryx.ps1 index 7bff17d..01717c1 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-11-21 + Last modified: 2022-04-19 #> [CmdletBinding ( SupportsShouldProcess = $true @@ -33,6 +33,8 @@ function Invoke-StartAlteryx { Begin { # Get global preference vrariables Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState + # Log function call + Write-Log -Type "DEBUG" -Message $MyInvocation.ScriptName # Variables $ServiceName = "AlteryxService" # Retrieve Alteryx Service utility path diff --git a/powershell/Invoke-StopAlteryx.ps1 b/powershell/Invoke-StopAlteryx.ps1 index 503236e..6a34dcc 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-11-20 + Last modified: 2022-04-19 #> [CmdletBinding ( SupportsShouldProcess = $true @@ -33,6 +33,8 @@ function Invoke-StopAlteryx { Begin { # Get global preference vrariables Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState + # Log function call + Write-Log -Type "DEBUG" -Message $MyInvocation.ScriptName # Variables $ServiceName = "AlteryxService" # Retrieve Alteryx Service utility path diff --git a/powershell/Repair-Alteryx.ps1 b/powershell/Repair-Alteryx.ps1 new file mode 100644 index 0000000..bd75f20 --- /dev/null +++ b/powershell/Repair-Alteryx.ps1 @@ -0,0 +1,87 @@ +function Repair-Alteryx { + <# + .SYNOPSIS + Repair Alteryx + + .DESCRIPTION + Perform maintenance operation to repair or optimise Alteryx by rebuilding database indexes + + .NOTES + File name: Repair-Alteryx.ps1 + Author: Florian Carrier + Creation date: 2022-04-22 + Last modified: 2022-04-27 + #> + [CmdletBinding ( + SupportsShouldProcess = $true + )] + Param ( + [Parameter ( + Position = 1, + Mandatory = $true, + HelpMessage = "Script properties" + )] + [ValidateNotNullOrEmpty ()] + [System.Collections.Specialized.OrderedDictionary] + $Properties, + [Parameter ( + HelpMessage = "Non-interactive mode" + )] + [Switch] + $Unattended + ) + Begin { + # Get global preference vrariables + Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState + # Log function call + Write-Log -Type "DEBUG" -Message $MyInvocation.ScriptName + # Check version + if (Compare-Version -Version $Properties.Version -Operator "lt" -Reference "2020.1") { + $Utility = "CloudCmd" + } elseif (Compare-Version -Version $Properties.Version -Operator "lt" -Reference "2022.1") { + $Utility = "ServerHost" + } else { + Write-Log -Type "WARN" -Message "No repair steps are available for version 2022.1 and above" -ExitCode 0 + } + # Default command arguments + $Command = "--rebuild -mongoconnection:mongodb://user:@:/AlteryxGallery?connectTimeoutMS=25000 -luceneconnection:mongodb://user:@:/AlteryxGallery_Lucene?connectTimeoutMS=25000 -searchProvider:Lucene" + } + Process { + Write-Log -Type "INFO" -Message "Starting repair of Alteryx $($InstallationProperties.Product) $($Properties.Version)" + $Path = Get-AlteryxUtility -Utility $Utility + # Retrieve database password + $Passwords = Get-AlteryxEMongoPassword + if ($Passwords -match "Non-Admin:\s(?\w+)") { + $Password = $Matches.Password + } else { + Write-Log -Type "ERROR" -Message "MongoDB database password could not be retrieved" -ExitCode 1 + } + # Define arguments + $Tags = [Ordered]@{ + "Hostname" = "localhost" + "Port" = $Properties.MongoDBPort + "Password" = $Password + } + $Arguments = Set-Tags -String $Command -Tags (Resolve-Tags -Tags $Tags -Prefix "<" -Suffix ">") + # Build command for debug + $DebugCommand = ("&", """$Path""", $Arguments) -join " " + Write-Log -Type "DEBUG" -Message $DebugCommand + # Run repair and return process + if ($PSCmdlet.ShouldProcess($Path, "rebuild")) { + if ($Unattended -eq $false){ + $Confirm = Confirm-Prompt -Prompt "Do you want to rebuild the MongoDB database indexes?" + } + if ($Confirm -Or $Unattended) { + $Repair = Start-Process -FilePath $Path -ArgumentList $Arguments -Verb "RunAs" -PassThru -Wait + } else { + Write-Log -Type "WARN" -Message "MongoDB database rebuild cancelled by user" -ExitCode 0 + } + } + Write-Log -Type "DEBUG" -Message $Repair + if ($Repair.ExitCode -eq 0) { + Write-Log -Type "CHECK" -Message "MongoDB database rebuild completed successfully" + } else { + Write-Log -Type "ERROR" -Message "MongoDB database rebuild failed" -ExitCode 1 + } + } +} \ No newline at end of file diff --git a/powershell/Show-Configuration.ps1 b/powershell/Show-Configuration.ps1 index fd5c828..ae48151 100644 --- a/powershell/Show-Configuration.ps1 +++ b/powershell/Show-Configuration.ps1 @@ -16,7 +16,7 @@ function Show-Configuration { File name: Show-Configuration.ps1 Author: Florian Carrier Creation date: 2021-07-08 - Last modified: 2021-09-06 + Last modified: 2022-04-19 #> [CmdletBinding ()] Param ( @@ -40,6 +40,8 @@ function Show-Configuration { Begin { # Get global preference variables Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState + # Log function call + Write-Log -Type "DEBUG" -Message $MyInvocation.ScriptName # Display colour $Colour = "Cyan" } diff --git a/powershell/Uninstall-Alteryx.ps1 b/powershell/Uninstall-Alteryx.ps1 index 1100a2c..215cb9f 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-21 + Last modified: 2022-04-19 .LINK https://www.powershellgallery.com/packages/PSAYX @@ -24,6 +24,9 @@ function Uninstall-Alteryx { .LINK https://help.alteryx.com/current/product-activation-and-licensing/use-command-line-options + .LINK + https://community.alteryx.com/t5/Alteryx-Designer-Knowledge-Base/Complete-Uninstall-of-Alteryx-Designer/ta-p/402897 + #> [CmdletBinding ( SupportsShouldProcess = $true @@ -54,6 +57,8 @@ function Uninstall-Alteryx { Begin { # Get global preference variables Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState + # Log function call + Write-Log -Type "DEBUG" -Message $MyInvocation.ScriptName # Variables $ISOTimeStamp = Get-Date -Format "yyyyMMdd_HHmmss" $Tags = [Ordered]@{"Version" = $Properties.Version} @@ -95,6 +100,8 @@ function Uninstall-Alteryx { Write-Log -Type "ERROR" -Message "Alteryx $($InstallationProperties.Product) executable file could not be located" -ExitCode 1 } } + # TODO remove leftover files + # TODO remove registry keys # TODO enable uninstall of standalone components Write-Log -Type "CHECK" -Message "Uninstallation of Alteryx $($InstallationProperties.Product) $Version successfull" } diff --git a/powershell/Update-Alteryx.ps1 b/powershell/Update-Alteryx.ps1 index 7a9343c..6b6f618 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-12-08 + Last modified: 2022-04-19 #> [CmdletBinding ( SupportsShouldProcess = $true @@ -41,14 +41,15 @@ function Update-Alteryx { Begin { # Get global preference vrariables Get-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState - # Retrieve Alteryx Service utility path - $AlteryxService = Get-AlteryxUtility -Utility "Service" -Path $Properties.InstallationPath + # Log function call + Write-Log -Type "DEBUG" -Message $MyInvocation.ScriptName # Clear error pipeline $Error.Clear() # Retrieve current version Write-Log -Type "DEBUG" -Object "Retrieving current version" if ($PSCmdlet.ShouldProcess("Alteryx version", "Retrieve")) { - $AlteryxVersion = Get-AlteryxVersion -Path $AlteryxService + # Check registry for installation path to avoid issues if directory has changed + $AlteryxVersion = Get-AlteryxVersion Write-Log -Type "DEBUG" -Object $AlteryxVersion $BackupVersion = Select-String -InputObject $AlteryxVersion -Pattern "\d+\.\d+.\d+(.\d+)?" | ForEach-Object { $PSItem.Matches.Value } } @@ -57,9 +58,29 @@ function Update-Alteryx { } Process { Write-Log -Type "CHECK" -Object "Starting Alteryx Server upgrade from $BackupVersion to $($Properties.Version)" + # Check installation path + $InstallationPath = Get-AlteryxInstallDirectory + if ($Properties.InstallationPath -ne $InstallationPath) { + # If new installation directory is specified + Write-Log -Type "WARN" -Message "New installation directory specified" + Write-Log -Type "INFO" -Message "Old directory: $InstallationPath" + Write-Log -Type "INFO" -Message "New directory: $($Properties.InstallationPath)" + if ($Unattended -eq $false) { + $Confirm = Confirm-Prompt -Prompt "Do you want to change the installation directory?" + } + if ($Confirm -Or $Unattended) { + $AlteryxService = Get-AlteryxUtility -Utility "Service" -Path $InstallationPath + } else { + Write-Log -Type "WARN" -Message "Upgrade cancelled by user" -ExitCode 0 + } + } else { + # Retrieve Alteryx Service utility path + $AlteryxService = Get-AlteryxUtility -Utility "Service" -Path $Properties.InstallationPath + } # Create back-up $BackUpProperties = Copy-OrderedHashtable -Hashtable $Properties - $BackUpProperties.Version = $BackupVersion + $BackUpProperties.Version = $BackupVersion + $BackupProperties.InstallationPath = $InstallationPath Invoke-BackupAlteryx -Properties $BackUpProperties -Unattended:$Unattended # Upgrade Install-Alteryx -Properties $Properties -InstallationProperties $InstallationProperties -Unattended:$Unattended