From c1710062ae059addb1532fbb38ed4d220ce8859b Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Fri, 6 Dec 2019 19:29:17 +0100 Subject: [PATCH] Improve installation/updates for Framework and Plugins Fixes #23 Fixes #28 Fixes #29 --- lib/core/framework/Copy-ItemSecure.psm1 | 29 +++++ .../Get-IcingaFrameworkServiceBinary.psm1 | 35 +++-- .../Get-IcingaPowerShellModuleArchive.psm1 | 58 +++++++++ .../Install-IcingaFrameworkPlugins.psm1 | 90 +++---------- .../Install-IcingaFrameworkService.psm1 | 35 ++++- .../Install-IcingaFrameworkUpdate.psm1 | 122 ++++++------------ lib/core/framework/Remove-ItemSecure.psm1 | 28 ++++ .../tools/New-IcingaTemporaryDirectory.psm1 | 16 +++ 8 files changed, 242 insertions(+), 171 deletions(-) create mode 100644 lib/core/framework/Copy-ItemSecure.psm1 create mode 100644 lib/core/framework/Get-IcingaPowerShellModuleArchive.psm1 create mode 100644 lib/core/framework/Remove-ItemSecure.psm1 create mode 100644 lib/core/tools/New-IcingaTemporaryDirectory.psm1 diff --git a/lib/core/framework/Copy-ItemSecure.psm1 b/lib/core/framework/Copy-ItemSecure.psm1 new file mode 100644 index 0000000..9641a29 --- /dev/null +++ b/lib/core/framework/Copy-ItemSecure.psm1 @@ -0,0 +1,29 @@ +function Copy-ItemSecure() +{ + param( + [string]$Path, + [string]$Destination, + [switch]$Recurse, + [switch]$Force + ); + + if ((Test-Path $Path) -eq $FALSE) { + return $FALSE; + } + + try { + if ($Recurse -And $Force) { + Copy-Item -Path $Path -Destination $Destination -Recurse -Force; + } elseif ($Recurse -And -Not $Force) { + Copy-Item -Path $Path -Destination $Destination -Recurse; + } elseif (-Not $Recurse -And $Force) { + Copy-Item -Path $Path -Destination $Destination -Force; + } else { + Copy-Item -Path $Path -Destination $Destination; + } + return $TRUE; + } catch { + Write-Host ([string]::Format('Failed to copy items from path "{0}" to "{1}": {2}', $Path, $Destination, $_.Exception)) -ForegroundColor Red; + } + return $FALSE; +} diff --git a/lib/core/framework/Get-IcingaFrameworkServiceBinary.psm1 b/lib/core/framework/Get-IcingaFrameworkServiceBinary.psm1 index 415845d..96552b8 100644 --- a/lib/core/framework/Get-IcingaFrameworkServiceBinary.psm1 +++ b/lib/core/framework/Get-IcingaFrameworkServiceBinary.psm1 @@ -18,6 +18,11 @@ function Get-IcingaFrameworkServiceBinary() } } + if ([string]::IsNullOrEmpty($FrameworkServiceUrl)) { + Write-Host 'No Url to download the Icinga Service Binary from has been specified. Please try again.'; + return Get-IcingaFrameworkServiceBinary; + } + if ([string]::IsNullOrEmpty($ServiceDirectory)) { $ServiceDirectory = (Get-IcingaAgentInstallerAnswerInput -Prompt 'Please enter the path you wish to install the service to' -Default 'v' -DefaultInput 'C:\Program Files\icinga-framework-service\').answer; } @@ -26,29 +31,31 @@ function Get-IcingaFrameworkServiceBinary() New-Item -Path $ServiceDirectory -Force -ItemType Directory | Out-Null; } - $ZipArchive = Join-Path -Path $ServiceDirectory -ChildPath ($FrameworkServiceUrl.Split('/')[-1]); - $ServiceBin = Join-Path -Path $ServiceDirectory -ChildPath 'icinga-service.exe'; + $TmpDirectory = New-IcingaTemporaryDirectory; + $ZipArchive = Join-Path -Path $TmpDirectory -ChildPath ($FrameworkServiceUrl.Split('/')[-1]); + $TmpServiceBin = Join-Path -Path $TmpDirectory -ChildPath 'icinga-service.exe'; + $UpdateBin = Join-Path -Path $ServiceDirectory -ChildPath 'icinga-service.exe.update'; + $ServiceBin = Join-Path -Path $ServiceDirectory -ChildPath 'icinga-service.exe'; - Invoke-WebRequest -Uri $FrameworkServiceUrl -UseBasicParsing -OutFile $ZipArchive; - - if ((Test-Path $ServiceBin)) { - Write-Host 'Icinga Service Binary already present. Skipping extrating'; - - return @{ - 'FrameworkServiceUrl' = $FrameworkServiceUrl; - 'ServiceDirectory' = $ServiceDirectory; - 'ServiceBin' = $ServiceBin; - }; + try { + Invoke-WebRequest -Uri $FrameworkServiceUrl -UseBasicParsing -OutFile $ZipArchive; + } catch { + Write-Host ([string]::Format('Failed to download the Icinga Service Binary from "{0}". Please try again.', $FrameworkServiceUrl)); + return Get-IcingaFrameworkServiceBinary; } - if ((Expand-IcingaZipArchive -Path $ZipArchive -Destination $ServiceDirectory) -eq $FALSE) { + if ((Expand-IcingaZipArchive -Path $ZipArchive -Destination $TmpDirectory) -eq $FALSE) { throw 'Failed to expand the downloaded ZIP archive'; } - if ((Test-IcingaZipBinaryChecksum -Path $ServiceBin) -eq $FALSE) { + if ((Test-IcingaZipBinaryChecksum -Path $TmpServiceBin) -eq $FALSE) { throw 'The checksum of the downloaded file and the required MD5 hash are not matching'; } + Copy-ItemSecure -Path $TmpServiceBin -Destination $UpdateBin -Force | Out-Null; + Start-Sleep -Seconds 1; + Remove-ItemSecure -Path $TmpDirectory -Recurse -Force | Out-Null; + return @{ 'FrameworkServiceUrl' = $FrameworkServiceUrl; 'ServiceDirectory' = $ServiceDirectory; diff --git a/lib/core/framework/Get-IcingaPowerShellModuleArchive.psm1 b/lib/core/framework/Get-IcingaPowerShellModuleArchive.psm1 new file mode 100644 index 0000000..20aae88 --- /dev/null +++ b/lib/core/framework/Get-IcingaPowerShellModuleArchive.psm1 @@ -0,0 +1,58 @@ +function Get-IcingaPowerShellModuleArchive() +{ + param( + [string]$DownloadUrl = '', + [string]$ModuleName = '', + [string]$Repository = '' + ); + + $ProgressPreference = "SilentlyContinue"; + $Tag = 'master'; + + if ([string]::IsNullOrEmpty($DownloadUrl)) { + if ((Get-IcingaAgentInstallerAnswerInput -Prompt ([string]::Format('Do you provide a custom repository for "{0}"?', $ModuleName)) -Default 'n').result -eq 1) { + $branch = (Get-IcingaAgentInstallerAnswerInput -Prompt 'Which version to you want to install? (snapshot/stable)' -Default 'v' -DefaultInput 'stable').answer + if ($branch.ToLower() -eq 'snapshot') { + $DownloadUrl = [string]::Format('https://github.com/Icinga/{0}/archive/master.zip', $Repository); + } else { + $LatestRelease = (Invoke-WebRequest -Uri 'https://github.com/Icinga/icinga-powershell-framework/releases/latest' -UseBasicParsing).BaseResponse.ResponseUri.AbsoluteUri; + $DownloadUrl = $LatestRelease.Replace('/releases/tag/', '/archive/'); + $Tag = $DownloadUrl.Split('/')[-1]; + $DownloadUrl = [string]::Format('{0}/{1}.zip', $DownloadUrl, $Tag); + + $CurrentVersion = Get-IcingaPowerShellModuleVersion $Repository; + + if ($null -ne $CurrentVersion -And $CurrentVersion -eq $Tag) { + Write-Host ([string]::Format('Your "{0}" is already up-to-date', $ModuleName)); + return; + } + } + } else { + $DownloadUrl = (Get-IcingaAgentInstallerAnswerInput -Prompt ([string]::Format('Please enter the full Url to your "{0}" Zip-Archive', $ModuleName)) -Default 'v').answer; + } + } + + try { + $DownloadDirectory = New-IcingaTemporaryDirectory; + $DownloadDestination = (Join-Path -Path $DownloadDirectory -ChildPath ([string]::Format('{0}.zip', $Repository))); + Write-Host ([string]::Format('Downloading "{0}" into "{1}"', $ModuleName, $DownloadDirectory)); + + Invoke-WebRequest -UseBasicParsing -Uri $DownloadUrl -OutFile $DownloadDestination; + } catch { + Write-Host ([string]::Format('Failed to download "{0}" into "{1}". Starting cleanup process', $ModuleName, $DownloadDirectory)); + Start-Sleep -Seconds 2; + Remove-Item -Path $DownloadDirectory -Recurse -Force; + + Write-Host 'Starting to re-run the download wizard'; + + return Get-IcingaPowerShellModuleArchive -ModuleName $ModuleName -Repository $Repository; + } + + return @{ + 'DownloadUrl' = $DownloadUrl; + 'Version' = $Tag; + 'Directory' = $DownloadDirectory; + 'Archive' = $DownloadDestination; + 'ModuleRoot' = (Get-IcingaFrameworkRootPath); + }; +} diff --git a/lib/core/framework/Install-IcingaFrameworkPlugins.psm1 b/lib/core/framework/Install-IcingaFrameworkPlugins.psm1 index 7a6cc9c..ed2e2ad 100644 --- a/lib/core/framework/Install-IcingaFrameworkPlugins.psm1 +++ b/lib/core/framework/Install-IcingaFrameworkPlugins.psm1 @@ -4,88 +4,34 @@ function Install-IcingaFrameworkPlugins() [string]$PluginsUrl ); - $ProgressPreference = "SilentlyContinue"; - $Tag = 'Unknown'; + $RepositoryName = 'icinga-powershell-plugins'; + $Archive = Get-IcingaPowerShellModuleArchive -DownloadUrl $PluginsUrl -ModuleName 'Icinga Plugins' -Repository $RepositoryName; - if ([string]::IsNullOrEmpty($PluginsUrl)) { - if ((Get-IcingaAgentInstallerAnswerInput -Prompt 'Do you provide a custom repository for the Icinga Plugins?' -Default 'n').result -eq 1) { - $branch = (Get-IcingaAgentInstallerAnswerInput 'Which version to you want to install? (snapshot/stable)' -Default 'v' -DefaultInput 'stable').answer - if ($branch.ToLower() -eq 'snapshot') { - $PluginsUrl = 'https://github.com/Icinga/icinga-powershell-plugins/archive/master.zip'; - } else { - $LatestRelease = (Invoke-WebRequest -Uri 'https://github.com/Icinga/icinga-powershell-plugins/releases/latest' -UseBasicParsing).BaseResponse.ResponseUri.AbsoluteUri; - $PluginsUrl = $LatestRelease.Replace('/releases/tag/', '/archive/'); - $Tag = $PluginsUrl.Split('/')[-1]; - $PluginsUrl = [string]::Format('{0}/{1}.zip', $PluginsUrl, $Tag); + Write-Host ([string]::Format('Installing module into "{0}"', ($Archive.Directory))); + Expand-IcingaZipArchive -Path $Archive.Archive -Destination $Archive.Directory | Out-Null; - $CurrentVersion = Get-IcingaPowerShellModuleVersion 'icinga-powershell-plugins'; - - if ($null -ne $CurrentVersion -And $CurrentVersion -eq $Tag) { - Write-Host 'Your Icinga Plugins are already up-to-date'; - return @{ - 'PluginUrl' = $PluginsUrl - }; - } - } - } else { - $PluginsUrl = (Get-IcingaAgentInstallerAnswerInput -Prompt 'Please enter the full path to your Icinga Plugin repository' -Default 'v').answer; - } - } - - $ModuleDirectory = Get-IcingaFrameworkRootPath; - $DownloadPath = (Join-Path -Path $ENv:TEMP -ChildPath 'icinga-powershell-plugins.zip'); - Write-Host ([string]::Format('Downloading Icinga Plugins into "{0}"', $DownloadPath)); - - Invoke-WebRequest -UseBasicParsing -Uri $PluginsUrl -OutFile $DownloadPath; - - Write-Host ([string]::Format('Installing plugins into "{0}"', ($ModuleDirectory))); - Expand-IcingaZipArchive -Path $DownloadPath -Destination $ModuleDirectory | Out-Null; - - $FolderContent = Get-ChildItem -Path $ModuleDirectory; - $Extracted = ''; + $FolderContent = Get-ChildItem -Path $Archive.Directory; + $ModuleContent = $Archive.Directory; foreach ($entry in $FolderContent) { - if ($entry -eq 'icinga-powershell-plugins') { - # Skip the plugins directory directly - continue; - } - if ($entry -like 'icinga-powershell-plugins-*') { - $Extracted = $entry; + if ($entry -like ([string]::Format('{0}*', $RepositoryName))) { + $ModuleContent = Join-Path -Path $ModuleContent -ChildPath $entry; + break; } } - if ([string]::IsNullOrEmpty($Extracted)) { - Write-Host 'No update package could be found.' - return @{ - 'PluginUrl' = $PluginsUrl - }; - } + Write-Host ([string]::Format('Using content of folder "{0}" for updates', $ModuleContent)); - $NewDirectory = (Join-Path -Path $ModuleDirectory -ChildPath 'icinga-powershell-plugins'); - $ExtractDir = (Join-Path -Path $ModuleDirectory -ChildPath $Extracted); - $BackupDir = (Join-Path -Path $ExtractDir -ChildPath 'previous'); - $OldBackupDir = (Join-Path -Path $NewDirectory -ChildPath 'previous'); + $PluginDirectory = (Join-Path -Path $Archive.ModuleRoot -ChildPath $RepositoryName); - if ((Test-Path $NewDirectory)) { - Write-Host 'Creating backup directory'; - if ((Test-Path $OldBackupDir)) { - Write-Host 'Importing old backups into new module version...'; - Move-Item -Path $OldBackupDir -Destination $ExtractDir; - } else { - Write-Host 'No previous backups found. Creating new backup space'; - if ((Test-Path $BackupDir) -eq $FALSE) { - New-Item -Path $BackupDir -ItemType Container | Out-Null; - } - } - Write-Host 'Moving old module into backup directory'; - Move-Item -Path $NewDirectory -Destination (Join-Path -Path $BackupDir -ChildPath (Get-Date -Format "MM-dd-yyyy-HH-mm-ffff")); - } + Write-Host 'Copying files to plugins'; + Copy-ItemSecure -Path (Join-Path -Path $ModuleContent -ChildPath '/*') -Destination $PluginDirectory -Recurse -Force | Out-Null; - Write-Host ([string]::Format('Installing new module version "{0}"', $Tag)); - Start-Sleep -Seconds 2; - Move-Item -Path (Join-Path -Path $ModuleDirectory -ChildPath $Extracted) -Destination $NewDirectory; + Write-Host 'Cleaning temporary content'; + Start-Sleep -Seconds 1; + Remove-ItemSecure -Path $Archive.Directory -Recurse -Force | Out-Null; - Unblock-IcingaPowerShellFiles -Path $NewDirectory; + Unblock-IcingaPowerShellFiles -Path $PluginDirectory; # In case the plugins are not installed before, load the framework again to # include the plugins Use-Icinga; @@ -93,6 +39,6 @@ function Install-IcingaFrameworkPlugins() Write-Host 'Icinga Plugin update has been completed'; return @{ - 'PluginUrl' = $PluginsUrl + 'PluginUrl' = $Archive.DownloadUrl }; } diff --git a/lib/core/framework/Install-IcingaFrameworkService.psm1 b/lib/core/framework/Install-IcingaFrameworkService.psm1 index 8c2a409..dd67ec1 100644 --- a/lib/core/framework/Install-IcingaFrameworkService.psm1 +++ b/lib/core/framework/Install-IcingaFrameworkService.psm1 @@ -11,6 +11,25 @@ function Install-IcingaFrameworkService() return; } + $UpdateFile = [string]::Format('{0}.update', $Path); + + $ServiceStatus = (Get-Service 'icingapowershell' -ErrorAction SilentlyContinue).Status; + + if ((Test-Path $UpdateFile)) { + + Write-Host 'Updating Icinga PowerShell Service binary'; + + if ($ServiceStatus -eq 'Running') { + Write-Host 'Stopping Icinga PowerShell service'; + Stop-IcingaService 'icingapowershell'; + Start-Sleep -Seconds 1; + } + + Remove-ItemSecure -Path $Path -Force | Out-Null; + Copy-ItemSecure -Path $UpdateFile -Destination $Path -Force | Out-Null; + Remove-ItemSecure -Path $UpdateFile -Force | Out-Null; + } + if ((Test-Path $Path) -eq $FALSE) { throw 'Please specify the path directly to the service binary'; } @@ -21,10 +40,14 @@ function Install-IcingaFrameworkService() (Get-IcingaPowerShellModuleFile) ); - $ServiceCreation = Start-IcingaProcess -Executable 'sc.exe' -Arguments ([string]::Format('create icingapowershell binPath= "{0}" DisplayName= "Icinga PowerShell Service" start= auto', $Path)); + if ($null -eq $ServiceStatus) { + $ServiceCreation = Start-IcingaProcess -Executable 'sc.exe' -Arguments ([string]::Format('create icingapowershell binPath= "{0}" DisplayName= "Icinga PowerShell Service" start= auto', $Path)); - if ($ServiceCreation.ExitCode -ne 0) { - throw ([string]::Format('Failed to install Icinga PowerShell Service: {0}{1}', $ServiceCreation.Message, $ServiceCreation.Error)); + if ($ServiceCreation.ExitCode -ne 0) { + throw ([string]::Format('Failed to install Icinga PowerShell Service: {0}{1}', $ServiceCreation.Message, $ServiceCreation.Error)); + } + } else { + Write-Host 'The Icinga PowerShell Service is already installed'; } # This is just a hotfix to ensure we setup the service properly before assigning it to @@ -36,5 +59,11 @@ function Install-IcingaFrameworkService() Start-Sleep -Seconds 1; Stop-IcingaService 'icingapowershell'; + if ($ServiceStatus -eq 'Running') { + Write-Host 'Starting Icinga PowerShell service'; + Start-IcingaService 'icingapowershell'; + Start-Sleep -Seconds 1; + } + return (Set-IcingaAgentServiceUser -User $User -Password $Password -Service 'icingapowershell'); } diff --git a/lib/core/framework/Install-IcingaFrameworkUpdate.psm1 b/lib/core/framework/Install-IcingaFrameworkUpdate.psm1 index cb29538..cc9b0ca 100644 --- a/lib/core/framework/Install-IcingaFrameworkUpdate.psm1 +++ b/lib/core/framework/Install-IcingaFrameworkUpdate.psm1 @@ -4,111 +4,69 @@ function Install-IcingaFrameworkUpdate() [string]$FrameworkUrl ); - $ProgressPreference = "SilentlyContinue"; - $Tag = 'Unknown'; + $RepositoryName = 'icinga-powershell-framework'; + $Archive = Get-IcingaPowerShellModuleArchive -DownloadUrl $FrameworkUrl -ModuleName 'Icinga Framework' -Repository $RepositoryName; - if ([string]::IsNullOrEmpty($FrameworkUrl)) { - if ((Get-IcingaAgentInstallerAnswerInput -Prompt 'Do you provide a custom repository of the framework?' -Default 'n').result -eq 1) { - $branch = (Get-IcingaAgentInstallerAnswerInput -Prompt 'Which version to you want to install? (snapshot/stable)' -Default 'v' -DefaultInput 'stable').answer - if ($branch.ToLower() -eq 'snapshot') { - $FrameworkUrl = 'https://github.com/Icinga/icinga-powershell-framework/archive/master.zip'; - } else { - $LatestRelease = (Invoke-WebRequest -Uri 'https://github.com/Icinga/icinga-powershell-framework/releases/latest' -UseBasicParsing).BaseResponse.ResponseUri.AbsoluteUri; - $FrameworkUrl = $LatestRelease.Replace('/releases/tag/', '/archive/'); - $Tag = $FrameworkUrl.Split('/')[-1]; - $FrameworkUrl = [string]::Format('{0}/{1}.zip', $FrameworkUrl, $Tag); + Write-Host ([string]::Format('Installing module into "{0}"', ($Archive.Directory))); + Expand-IcingaZipArchive -Path $Archive.Archive -Destination $Archive.Directory | Out-Null; - $CurrentVersion = Get-IcingaPowerShellModuleVersion 'icinga-powershell-framework'; - - if ($null -ne $CurrentVersion -And $CurrentVersion -eq $Tag) { - Write-Host 'Your Icinga Framework is already up-to-date'; - return; - } - } - } else { - $FrameworkUrl = (Get-IcingaAgentInstallerAnswerInput -Prompt 'Please enter the full path to your icinga framework repository' -Default 'v').answer; - } - } - - $ModuleDirectory = Get-IcingaFrameworkRootPath; - $DownloadPath = (Join-Path -Path $ENv:TEMP -ChildPath 'icinga-powershell-framework.zip'); - Write-Host ([string]::Format('Downloading Icinga Framework into "{0}"', $DownloadPath)); - - Invoke-WebRequest -UseBasicParsing -Uri $FrameworkUrl -OutFile $DownloadPath; - - Write-Host ([string]::Format('Installing module into "{0}"', ($ModuleDirectory))); - Expand-IcingaZipArchive -Path $DownloadPath -Destination $ModuleDirectory | Out-Null; - - $FolderContent = Get-ChildItem -Path $ModuleDirectory; - $Extracted = ''; + $FolderContent = Get-ChildItem -Path $Archive.Directory; + $ModuleContent = $Archive.Directory; foreach ($entry in $FolderContent) { - if ($entry -eq 'icinga-powershell-framework') { - # Skip the framework directory directly - continue; - } - if ($entry -like 'icinga-powershell-framework-*') { - $Extracted = $entry; + if ($entry -like ([string]::Format('{0}*', $RepositoryName))) { + $ModuleContent = Join-Path -Path $ModuleContent -ChildPath $entry; + break; } } - if ([string]::IsNullOrEmpty($Extracted)) { - Write-Host 'No update package could be found.' - return; - } + Write-Host ([string]::Format('Using content of folder "{0}" for updates', $ModuleContent)); $ServiceStatus = (Get-Service 'icingapowershell' -ErrorAction SilentlyContinue).Status; if ($ServiceStatus -eq 'Running') { + Write-Host 'Stopping Icinga PowerShell service'; Stop-IcingaService 'icingapowershell'; Start-Sleep -Seconds 1; } - $NewDirectory = (Join-Path -Path $ModuleDirectory -ChildPath 'icinga-powershell-framework'); - $ExtractDir = (Join-Path -Path $ModuleDirectory -ChildPath $Extracted); - $BackupDir = (Join-Path -Path $ExtractDir -ChildPath 'previous'); - $OldBackupDir = (Join-Path -Path $NewDirectory -ChildPath 'previous'); + $ModuleDirectory = (Join-Path -Path $Archive.ModuleRoot -ChildPath $RepositoryName); - if ((Test-Path $NewDirectory)) { - if ((Test-Path (Join-Path -Path $NewDirectory -ChildPath 'cache'))) { - Write-Host 'Importing cache into new module version...'; - Copy-Item -Path (Join-Path -Path $NewDirectory -ChildPath 'cache') -Destination $ExtractDir -Force -Recurse; - } - if ((Test-Path (Join-Path -Path $NewDirectory -ChildPath 'custom'))) { - Write-Host 'Importing custom modules into new module version...'; - Copy-Item -Path (Join-Path -Path $NewDirectory -ChildPath 'custom') -Destination $ExtractDir -Force -Recurse; - } - if ((Test-Path (Join-Path -Path $NewDirectory -ChildPath 'config'))) { - Write-Host 'Importing config into new module version...'; - Copy-Item -Path (Join-Path -Path $NewDirectory -ChildPath 'config') -Destination $ExtractDir -Force -Recurse; - } - Write-Host 'Creating backup directory'; - if ((Test-Path $OldBackupDir)) { - Write-Host 'Importing old backups into new module version...'; - Move-Item -Path $OldBackupDir -Destination $ExtractDir; - } else { - Write-Host 'No previous backups found. Creating new backup space'; - if ((Test-Path $BackupDir) -eq $FALSE) { - New-Item -Path $BackupDir -ItemType Container | Out-Null; - } - } - Write-Host 'Moving old module into backup directory'; - Move-Item -Path $NewDirectory -Destination (Join-Path -Path $BackupDir -ChildPath (Get-Date -Format "MM-dd-yyyy-HH-mm-ffff")); + if ((Test-Path $ModuleDirectory) -eq $FALSE) { + Write-Host 'Failed to update the component. Module Root-Directory was not found'; + return; } - Write-Host ([string]::Format('Installing new module version "{0}"', $Tag)); - Start-Sleep -Seconds 2; - Move-Item -Path (Join-Path -Path $ModuleDirectory -ChildPath $Extracted) -Destination $NewDirectory; + $Files = Get-ChildItem $ModuleDirectory -File '*'; - Unblock-IcingaPowerShellFiles -Path $NewDirectory; - # Fix new permissions for cache folder - Set-IcingaAcl -Directory (Get-IcingaCacheDir); + Write-Host 'Removing files from framework'; + + foreach ($ModuleFile in $Files) { + Remove-ItemSecure -Path $ModuleFile -Force | Out-Null; + } + + Remove-ItemSecure -Path (Join-Path $ModuleDirectory -ChildPath 'doc') -Recurse -Force | Out-Null; + Remove-ItemSecure -Path (Join-Path $ModuleDirectory -ChildPath 'lib') -Recurse -Force | Out-Null; + Remove-ItemSecure -Path (Join-Path $ModuleDirectory -ChildPath 'manifests') -Recurse -Force | Out-Null; + + Write-Host 'Copying new files to framework'; + Copy-ItemSecure -Path (Join-Path $ModuleContent -ChildPath 'doc') -Destination $ModuleDirectory -Recurse -Force | Out-Null; + Copy-ItemSecure -Path (Join-Path $ModuleContent -ChildPath 'lib') -Destination $ModuleDirectory -Recurse -Force | Out-Null; + Copy-ItemSecure -Path (Join-Path $ModuleContent -ChildPath 'manifests') -Destination $ModuleDirectory -Recurse -Force | Out-Null; + Copy-ItemSecure -Path (Join-Path -Path $ModuleContent -ChildPath '/*') -Destination $ModuleDirectory -Recurse -Force | Out-Null; + + Unblock-IcingaPowerShellFiles -Path $ModuleDirectory; + + Write-Host 'Cleaning temporary content'; + Start-Sleep -Seconds 1; + Remove-ItemSecure -Path $Archive.Directory -Recurse -Force | Out-Null; + + Write-Host 'Framework update has been completed. Please start a new PowerShell instance now to complete the update'; Test-IcingaAgent; if ($ServiceStatus -eq 'Running') { + Write-Host 'Starting Icinga PowerShell service'; Start-IcingaService 'icingapowershell'; } - - Write-Host 'Framework update has been completed'; } diff --git a/lib/core/framework/Remove-ItemSecure.psm1 b/lib/core/framework/Remove-ItemSecure.psm1 new file mode 100644 index 0000000..6c97c90 --- /dev/null +++ b/lib/core/framework/Remove-ItemSecure.psm1 @@ -0,0 +1,28 @@ +function Remove-ItemSecure() +{ + param( + [string]$Path, + [switch]$Recurse, + [switch]$Force + ) + + if ((Test-Path $Path) -eq $FALSE) { + return $FALSE; + } + + try { + if ($Recurse -And $Force) { + Remove-Item -Path $Path -Recurse -Force; + } elseif ($Recurse -And -Not $Force) { + Remove-Item -Path $Path -Recurse; + } elseif (-Not $Recurse -And $Force) { + Remove-Item -Path $Path -Force; + } else { + Remove-Item -Path $Path; + } + return $TRUE; + } catch { + Write-Host ([string]::Format('Failed to remove items from path "{0}": {1}', $Path, $_.Exception)) -ForegroundColor Red; + } + return $FALSE; +} diff --git a/lib/core/tools/New-IcingaTemporaryDirectory.psm1 b/lib/core/tools/New-IcingaTemporaryDirectory.psm1 new file mode 100644 index 0000000..6a64187 --- /dev/null +++ b/lib/core/tools/New-IcingaTemporaryDirectory.psm1 @@ -0,0 +1,16 @@ +function New-IcingaTemporaryDirectory() +{ + [string]$TmpDirectory = ''; + [string]$DirectoryPath = ''; + + while ($TRUE) { + $TmpDirectory = [string]::Format('tmp_icinga{0}.d', (Get-Random)); + $DirectoryPath = Join-Path $Env:TMP -ChildPath $TmpDirectory; + + if ((Test-Path $DirectoryPath) -eq $FALSE) { + break; + } + } + + return (New-Item -Path $DirectoryPath -ItemType Directory); +}