Adds repository management

This commit is contained in:
Lord Hepipud 2021-07-16 21:38:08 +02:00
parent b5661d7b1d
commit db2b7a745b
67 changed files with 3091 additions and 264 deletions

View file

@ -0,0 +1,17 @@
# Repository Manager
Starting with Icinga for Windows v1.6.0, we provide a full feature-set to manage repositories for all components which are developed for Icinga for Windows. This includes all resources like framework, plugins the service binary and the Icinga Agent itself.
Below you will find a detailed description for core areas of the repository management, explaining on how to work with repositories.
## Basic Usage
* [Add existing repositories](repositorymanager/01-Add-Existing-Repositories.md)
* [Sync repositories](repositorymanager/02-Sync-Repositories.md)
* [Enable/Disable/Remove Repositories](repositorymanager/03-Enable-Disable-Remove-Repositories.md)
* [Search Repository for Components](repositorymanager/04-Search-Repository-For-Components.md)
* [Lock/Unlock Components](repositorymanager/05-Lock-Unlock-Components.md)
* [Install Components](repositorymanager/06-Install-Components.md)
* [Create Own Repositories](repositorymanager/07-Create-Own-Repositories.md)
## Example Configurations

View file

@ -22,6 +22,7 @@ Released closed milestones can be found on [GitHub](https://github.com/Icinga/ic
* [#303](https://github.com/Icinga/icinga-powershell-framework/pull/303) Adds support to parse arrays to Icinga Check thresholds functions like `WarnOutOfRange` and adds two new functions `WarnDateTime` and `CritDateTime`, for easier comparing of time stamps.
* [#305](https://github.com/Icinga/icinga-powershell-framework/pull/305) Adds a new Cmdlet to test if functions with `Add-Type` are already present inside the current scope of the shell
* [#306](https://github.com/Icinga/icinga-powershell-framework/pull/306) Adds new Cmdlet `Exit-IcingaThrowCritical` to throw critical exit with a custom message, either by force or by using string filtering and adds storing of plugin exit codes internally
* [#310](https://github.com/Icinga/icinga-powershell-framework/pull/310) Adds repository management to install components very easily from one or multiple defined source locations
* [#314](https://github.com/Icinga/icinga-powershell-framework/pull/314) Adds support to configure on which address TCP sockets are created on, defaults to `loopback` interface
* [#316](https://github.com/Icinga/icinga-powershell-framework/pull/316) The reconfigure menu was previously present inside the Icinga Agent sub-menu and is now moved to the main installation menu for the Management Console
* [#318](https://github.com/Icinga/icinga-powershell-framework/pull/318) We always enforce the Icinga Framework Code caching now and ship a plain file to build the cache on first loading

View file

@ -32,8 +32,8 @@ if ($null -ne $IcingaService) {
return;
}
Uninstall-IcingaFrameworkService;
Install-IcingaFrameworkService -Path $IfWPath -User $IfWUser;
Uninstall-IcingaForWindowsService;
Install-IcingaForWindowsService -Path $IfWPath -User $IfWUser;
}
```

View file

@ -0,0 +1,44 @@
# Add Existing Repositories
The easiest way to extend the functionality of Icinga for Windows, is by installing new components. Components are delivered by repositories you can add to your environment. This includes external repositories but also internal ones.
Each repository inherits a file called `ifw.repo.json` on the root level, which contains all informations for available packages, versions and where they can be downloaded from.
**Note:** Each repository requires to use a unique name on the system. You can add multiple repositories, with different resources and components provided. The name has be unique and has no impact on the installation. It should be a short summary on where the repository is located.
## Adding Default Repositories
The best way to demonstrate on how to add new repositories, you can use the default Icinga for Windows repositories. To add an already existing repository, you can use `Add-IcingaRepository`
### Available Arguments
| Argument | Type | Description |
| --- |--- | --- |
| Name | String | The unique name of the repository. This name can only exist once on your system |
| RemotePath | String | The path pointing to the location on where the repository is located at. It can either point to the root directory of the folder containing the `ifw.repo.json` or directly to this file. Accepts web, local or network share path. |
### Icinga for Windows Stable
The URL pointing to the stable releases is `http://packages.icinga.com/IcingaForWindows/stable`.
```powershell
Add-IcingaRepository `
-Name 'Icinga Stable' `
-RemotePath 'http://packages.icinga.com/IcingaForWindows/stable';
```
### Icinga for Windows Snapshot
The URL pointing to the snapshot releases is `http://packages.icinga.com/IcingaForWindows/snapshot`.
```powershell
Add-IcingaRepository `
-Name 'Icinga Snapshot' `
-RemotePath 'http://packages.icinga.com/IcingaForWindows/snapshot';
```
## Using Repositories
Once you added one or more repositories, they will be connected to once you want to install or update your components. The available components and versions will be accessed on runtime, during installation/updates and files downloaded directly when required.
In case you can only access the internet or some internal repositories on certain times only, you can also [sync existing repositories](02-Sync-Repositories.md).

View file

@ -0,0 +1,142 @@
# Sync Repositories
In case you require local copies of repositories to frequently access them or to make a public repository available for systems unable to access public spaces, you can use `Sync-IcingaRepository`.
Like with [adding existing repositories](01-Add-Existing-Repositories.md), each synced repositories require a unique name you can set with `-Name`. The name will not interfere on how the sync works.
## Available Arguments
| Argument | Type | Description |
| --- |--- | --- |
| Name | String | The unique name of the repository. This name can only exist once on your system |
| Path | String | The location on where the files from the remote repository will be synced to. This can either be a local path, a network share or a Linux path, including user and hostname like `icinga@example.com:/vaw/www/icingarepo/`
| RemotePath | String | The path pointing to the location Icinga for Windows tries to lookup all your files. You can either replicate the `Path` variable for network shares for example, or use a web url which is made available based on `Path` to fetch and download files from. If left empty, it will default to the `Path` variable content |
| Source | String | The source from where the repository will be synced from. This can either be pointing directly to the `ifw.repo.json` or the root directory, as long as the file is fetch able from this point. A source can be a web, local or network share |
| UseSCP | Switch | If you set `Path` to a Linux path as mentioned in the first example, you will have to enable this switch to use SCP to copy files from the source to the Linux system. Requires `scp` and `ssh` being installed on the system |
| Force | Switch | This will force the creation of the repository, even if the name of the repository is already assigned. Should be used with caution |
| ForceTrust | Switch | By default repositories are validated with a hash, based on all files present inside the repository. If a repository is not providing a hash, it will be disabled after the sync for security reasons. In case the hash does not match with all files synced afterwards, the repository files will be deleted and the sync aborted. You can use this flag to ignore both states and always add the repository, regardless if the hash matches or the hash is not given |
## Sync Public Repository
You can use the sync command to clone an existing public repository for example and fetch all files to a local space.
### Local Disk Example
```powershell
Sync-IcingaRepository `
-Name 'Icinga Stable Local' `
-Path 'C:\icinga\icinga_stable' `
-Source 'http://packages.icinga.com/IcingaForWindows/stable';
```
This will sync all files from the public Icinga repository into `C:\icinga\icinga_stable`. As `RemotePath` is not set, it will default to `C:\icinga\icinga_stable` and all files will be fetched from this location.
### Shared Folder Example
```powershell
Sync-IcingaRepository `
-Name 'Icinga Stable Local' `
-Path 'C:\icinga\icinga_stable' `
-RemotePath '\\myhost.example.com\icingastable' `
-Source 'http://packages.icinga.com/IcingaForWindows/stable';
```
We can for example use file sharing, to make certain folders available in our network. This example will download all files into `C:\icinga\icinga_stable`, but tell Icinga for Windows to use your shared network drive `\\myhost.example.com\icingastable` to fetch them from.
You can now add the repository on different machines with
```powershell
Add-IcingaRepository `
-Name 'Icinga Stable Local' `
-RemotePath '\\myhost.example.com\icingastable';
```
Every file will then be fetched over this network share to the local machines.
### Linux Webserver Example
```powershell
Sync-IcingaRepository `
-Name 'Icinga Stable Internal Web' `
-Path 'icinga@icingarepo.example.com:/var/www/icingastable/' `
-RemotePath 'https://icingarepo.example.com/icingastable' `
-Source 'http://packages.icinga.com/IcingaForWindows/stable' `
-UseSCP;
```
In this example we will sync all files to a Linux machine at `/var/www/icingastable/`. If we are running a local Apache or Nginx, we can create a web resource for this path and make it available in our network. We have to use `-UseSCP`, to tell Icinga for Windows to copy them to the Linux machine over `scp`. Please note that both, `scp` and `ssh` have to be installed on the system.
On different machines, you can then use
```powershell
Add-IcingaRepository `
-Name 'Icinga Stable Internal Web' `
-RemotePath 'https://icingarepo.example.com/icingastable';
```
to make the repository available.
### Sync from a Sync Example
Last but not least we have the method to sync repositories from a sync source, allowing us to distribute all Icinga for Windows files around or network on different zones as example.
Clone the repository to a local path:
```powershell
Sync-IcingaRepository `
-Name 'Icinga Stable Local' `
-Path 'C:\icinga\icinga_stable' `
-Source 'http://packages.icinga.com/IcingaForWindows/stable';
```
Clone this repository to our internal web space:
```powershell
Sync-IcingaRepository `
-Name 'Icinga Stable Internal Web' `
-Path 'icinga@icingarepo.example.com:/var/www/icingastable/' `
-RemotePath 'https://icingarepo.example.com/icingastable' `
-Source 'C:\icinga\icinga_stable' `
-UseSCP;
```
## Update Sync Repositories
To update synced repositories, you can use `Update-IcingaRepository`. You can either update a specific repository by using the `-Name` argument or update all by leaving it empty.
### Available Arguments
| Argument | Type | Description |
| --- |--- | --- |
| Name | String | The name of the repository to update. Leave empty to update all configured repositories |
| ForceTrust | Switch | By default repositories are validated with a hash, based on all files present inside the repository. If a repository is not providing a hash, it will be disabled after the sync for security reasons. In case the hash does not match with all files synced afterwards, the repository files will be deleted and the sync aborted. You can use this flag to ignore both states and always add the repository, regardless if the hash matches or the hash is not given |
### Update All Repositories
Updating all synced repositories is very easy, with a simple command call:
```powershell
Update-IcingaRepository;
```
Once run, all files will be downloaded from the source and validated. In case validation fails or the source is not containing a repository hash, you can use `-ForceTrust` to ignore this and enable it regardless.
```powershell
Update-IcingaRepository -ForceTrust;
```
### Update Specific Repository
You can update a specific repository, by simply providing it's name:
```powershell
Update-IcingaRepository -Name 'Icinga Stable Internal Web';
```
Like other methods, `-ForceTrust` will work here as well.
## Updating Linux Repositories
There is no special mechanic required, as the entire configuration for the repository is stored inside the Icinga for Windows configuration.
For easier usage, it is however advised to use SSH keys, as otherwise each sync and update task will require you to enter your SSH password multiple times.

View file

@ -0,0 +1,33 @@
# Enable/Disable/Remove Repositories
Besides [adding](01-Add-Existing-Repositories.md) and [syncing])(02-Sync-Repositories.md) of repositories, you can also `enable`, `disable` and `remove` repositories from your local machine.
Please note that **removing** a repository will only remove the Icinga for Windows configuration and **not** the files on the disk. You have to do this step manually.
## Enabling Repositories
In case a repository is disabled, you can enable it with `Enable-IcingaRepository`.
```powershell
Enable-IcingaRepository -Name 'Icinga Stable Internal Web';
```
## Disabling Repositories
You can also disable enabled repositories with `Disable-IcingaRepository`.
```powershell
Disable-IcingaRepository -Name 'Icinga Stable Internal Web';
```
Please note that disabled Icinga repositories will be fully ignored during installation/update tasks and no files from these will be fetched.
## Removing Repositories
If you no longer require a certain repository, you can remove it with `Remove-IcingaRepository`.
```powershell
Remove-IcingaRepository -Name 'Icinga Stable Internal Web';
```
**Note:** This will only remove the repository from the configuration. All possible available files for sync runs or anything related will remain on the disk until you remove them manually.

View file

@ -0,0 +1,33 @@
# Search Repository For Components
Once you [added](01-Add-Existing-Repositories.md) and/or [synced])(02-Sync-Repositories.md) your repositories, you can search them for available components.
We can do this with the command `Search-IcingaRepository` and filter for a component `Name`, it's `Version` and if we want to include `Release` or `Snapshot` packages.
## List Everything available
At the beginning we can have a full search over all repositories and lookup all components made available by our repositories.
```powershell
Search-IcingaRepository -Name '*' -Release -Snapshot;
```
This will print all components including the version, the repository, the source of the repository and the component name.
**Note:** Disabled repositories are not included inside the search and results.
## List Certain Release Component
You can only include certain components for a release branch by using the `Name` and `Release` argument:
```powershell
Search-IcingaRepository -Name 'agent' -Release;
```
## Search For Specific Version
If you want to check if a certain `Release` version for a component is available inside your repositories, you can specify it with `Version`:
```powershell
Search-IcingaRepository -Name 'agent' -Version '2.12.5' -Release;
```

View file

@ -0,0 +1,38 @@
# Lock/Unlock Components
Sometimes you might require to `lock` certain components to a specific version. This means regardless of any version available, this component will not be updated or touched, unless the version it is locked to is not yet installed.
A lock will override the version suggested by any repository or the user input and always force the version specified.
If for example you lock the [Icinga Plugins](https://icinga.com/docs/icinga-for-windows/latest/plugins/doc/01-Introduction/) to version 1.6.0, they will not get upgraded to any other version.
## Locking Commponents
You can lock any Icinga component with `Lock-IcingaComponent` by simply providing the name of the component and the target version.
For example we can look our plugins to version 1.6.0:
```powershell
Lock-IcingaComponent `
-Name 'plugins' `
-Version '1.6.0';
```
Now the only version being installed for the plugins is 1.6.0, while all other versions are skipped. You can directly replace the lock for a different version later on, like 1.6.1:
```powershell
Lock-IcingaComponent `
-Name 'plugins' `
-Version '1.6.1';
```
## Unlocking Components
You can release a lock for a component by using `Unlock-IcingaComponent`. Unlike the locking mechanism, you only require to specify the component name for unlocking it, as each component only accepts one version lock at the time.
```powershell
Unlock-IcingaComponent `
-Name 'plugins';
```
Once the lock is removed, updates will be applied again for this component.

View file

@ -0,0 +1,60 @@
# Install Components
Once you [added](01-Add-Existing-Repositories.md) and/or [synced])(02-Sync-Repositories.md) your repositories and configured - if required - your [locks](05-Lock-Unlock-Components.md), we can start installing components.
For this we will use `Install-IcingaComponent`.
**Note:** When the install component is looking up available versions, *all* defined repositories will be searched and the latest version available used by default. If a specific version is set, it will stop once this version is found in one of the repositories and go with this package.
## Available Arguments
| Argument | Type | Description |
| --- |--- | --- |
| Name | String | The name of the component you want to install |
| Version | String | Specifies to install a specific version of the component, instead of the latest one found. Is ignored in case you added a [lock](05-Lock-Unlock-Components.md) to this component |
| Release | Switch | Includes release versions only if set. If neither Release nor Snapshot is defined, it will enforce release |
| Snapshot | Switch | Includes snapshots versions only if set. If neither Release nor Snapshot is defined, it will enforce release |
| Confirm | Switch | Skips the message asking you if you want to install this component |
| Force | Switch | In case the same version is already installed, it will be skipped by default. Use this switch to install the same version again |
## Install Release Components
You can install release components either by adding the `-Release` switch or by not adding `-Release` and `-Snapshot` at all, to enforce release versions. If no version is specified, the latest version found will be used. Use `-Confirm` in addition to skip the dialog requiring an approval to install it.
```powershell
Install-IcingaComponent `
-Name 'agent' `
-Confirm;
```
## Install Specific Component Version
If your repository contains multiple versions, you can specify which version will be installed:
```powershell
Install-IcingaComponent `
-Name 'agent' `
-Version '2.11.2' `
-Confirm;
```
## Reinstall Installed Component
If a component with a specific version is already installed, you can use `-Force` to re-install it.
```powershell
Install-IcingaComponent `
-Name 'agent' `
-Version '2.11.5' `
-Confirm `
-Force;
```
This also works for auto detected latest versions:
```powershell
Install-IcingaComponent `
-Name 'agent' `
-Confirm `
-Force;
```

View file

@ -0,0 +1,50 @@
# Create Own Repositories
Besides [adding](01-Add-Existing-Repositories.md) and/or [syncing])(02-Sync-Repositories.md) already existing repositories, you can create entire new ones from scratch with `New-IcingaRepository`.
## Preparing Repositories
To prepare your new repository, you will simply require an `empty` folder somewhere on your local Windows machine or accessible network share. For example we can create a new folder directly under `C:`, like `C:\icinga_repositories\custom`.
Now after having an `empty` folder, copy all files you want to add to this repository there. This includes the `.zip` files for Icinga for Windows components, the Icinga Agents `.msi` files and the Icinga for Windows `Service` `.zip` files which include the `.exe` and the `.md5` hash file.
## Initialize The Repository
Now as the folder is prepared and all files are placed inside, we can run `New-IcingaRepository` with our configuration.
### Available Arguments
| Argument | Type | Description |
| --- |--- | --- |
| Name | String | The name of the repository to add. Only for local references required. |
| Path | String | The location of the path you prepared in the first step in which all files are inside, for creating your repository |
| RemotePath | String | Will add the remote path for later adding of this repository to another system. Only suitable for network shares and is optional |
| Force | Switch | In case a repository with the given name is already present, it will be overwritten |
### Create Our Repository
As we now understand on which arguments are available, we can now use `New-IcingaRepository` to create your repository:
```powershell
New-IcingaRepository `
-Name 'My Local Repo' `
-Path 'C:\icinga_repositories\custom';
```
Depending on the amount of files inside, every single one will be analyzed for their component name and version and a new repo file `ifw.repo.json` is created. From the local Windows machine, you can also use this repository to install components from, as it will be added automatically.
### Sync Own Repositories
Now as we created our own repository with own files we checked, we can use the `Sync-IcingaRepository` Cmdlet to either sync from this machine to another location or ir vice-versa, depending on your configuration.
You can read more about this on the [sync repositories](02-Sync-Repositories.md) section.
#### Example
```powershell
Sync-IcingaRepository `
-Name 'My Local Repo Sync' `
-Path 'icinga@icingarepo.example.com:/var/www/icingacustom/' `
-RemotePath 'https://icingarepo.example.com/icingacustom' `
-Source 'C:\icinga_repositories\custom' `
-UseSCP;
```

View file

@ -7,9 +7,9 @@
.FUNCTIONALITY
Installs the Icinga PowerShell Services as a Windows service
.EXAMPLE
PS>Install-IcingaFrameworkService -Path C:\Program Files\icinga-service\icinga-service.exe;
PS>Install-IcingaForWindowsService -Path C:\Program Files\icinga-service\icinga-service.exe;
.EXAMPLE
PS>Install-IcingaFrameworkService -Path C:\Program Files\icinga-service\icinga-service.exe -User 'NT Authority\NetworkService';
PS>Install-IcingaForWindowsService -Path C:\Program Files\icinga-service\icinga-service.exe -User 'NT Authority\NetworkService';
.PARAMETER Path
The location on where the service binary executable is found
.PARAMETER User
@ -24,7 +24,7 @@
https://github.com/Icinga/icinga-powershell-framework
#>
function Install-IcingaFrameworkService()
function Install-IcingaForWindowsService()
{
param(
$Path,
@ -93,3 +93,5 @@ function Install-IcingaFrameworkService()
return (Set-IcingaAgentServiceUser -User $User -Password $Password -Service 'icingapowershell');
}
Set-Alias -Name 'Install-IcingaFrameworkService' -Value 'Install-IcingaForWindowsService';

View file

@ -48,7 +48,7 @@ function Uninstall-IcingaForWindows()
Write-IcingaConsoleNotice 'Uninstalling Icinga Agent';
Uninstall-IcingaAgent -RemoveDataFolder | Out-Null;
Write-IcingaConsoleNotice 'Uninstalling Icinga for Windows service';
Uninstall-IcingaFrameworkService | Out-Null;
Uninstall-IcingaForWindowsService | Out-Null;
$HasErrors = $FALSE;

View file

@ -0,0 +1,73 @@
<#
.SYNOPSIS
Uninstalls the Icinga PowerShell Service as a Windows Service
.DESCRIPTION
Uninstalls the Icinga PowerShell Service as a Windows Service. The service binary
will be left on the system.
.FUNCTIONALITY
Uninstalls the Icinga PowerShell Service as a Windows Service
.EXAMPLE
PS>Uninstall-IcingaForWindowsService;
.INPUTS
System.String
.OUTPUTS
System.Object
.LINK
https://github.com/Icinga/icinga-powershell-framework
#>
function Uninstall-IcingaForWindowsService()
{
param (
[switch]$RemoveFiles = $FALSE
);
$ServiceData = Get-IcingaForWindowsServiceData;
Stop-IcingaService 'icingapowershell';
Start-Sleep -Seconds 1;
$ServiceCreation = Start-IcingaProcess -Executable 'sc.exe' -Arguments 'delete icingapowershell';
switch ($ServiceCreation.ExitCode) {
0 {
Write-IcingaConsoleNotice 'Icinga PowerShell Service was successfully removed';
}
1060 {
Write-IcingaConsoleWarning 'The Icinga PowerShell Service is not installed';
}
Default {
throw ([string]::Format('Failed to install Icinga PowerShell Service: {0}{1}', $ServiceCreation.Message, $ServiceCreation.Error));
}
}
if ($RemoveFiles -eq $FALSE) {
return $TRUE;
}
if ([string]::IsNullOrEmpty($ServiceData.Directory) -Or (Test-Path $ServiceData.Directory) -eq $FALSE) {
return $TRUE;
}
$ServiceFolderContent = Get-ChildItem -Path $ServiceData.Directory;
foreach ($entry in $ServiceFolderContent) {
if ($entry.Name -eq 'icinga-service.exe' -Or $entry.Name -eq 'icinga-service.exe.md5' -Or $entry.Name -eq 'icinga-service.exe.update') {
Remove-Item $entry.FullName -Force;
Write-IcingaConsoleNotice 'Removing file "{0}"' -Objects $entry.FullName;
}
}
$ServiceFolderContent = Get-ChildItem -Path $ServiceData.Directory;
if ($ServiceFolderContent.Count -eq 0) {
Remove-Item $ServiceData.Directory;
Write-IcingaConsoleNotice 'Removing directory "{0}"' -Objects $ServiceData.Directory;
} else {
Write-IcingaConsoleWarning 'Unable to remove folder "{0}", because there are still files inside.' -Objects $ServiceData.Directory;
}
return $TRUE;
}
Set-Alias -Name 'Uninstall-IcingaFrameworkService' -Value 'Uninstall-IcingaForWindowsService';

View file

@ -1,37 +0,0 @@
<#
.SYNOPSIS
Uninstalls the Icinga PowerShell Service as a Windows Service
.DESCRIPTION
Uninstalls the Icinga PowerShell Service as a Windows Service. The service binary
will be left on the system.
.FUNCTIONALITY
Uninstalls the Icinga PowerShell Service as a Windows Service
.EXAMPLE
PS>Uninstall-IcingaFrameworkService;
.INPUTS
System.String
.OUTPUTS
System.Object
.LINK
https://github.com/Icinga/icinga-powershell-framework
#>
function Uninstall-IcingaFrameworkService()
{
Stop-IcingaService 'icingapowershell';
Start-Sleep -Seconds 1;
$ServiceCreation = Start-IcingaProcess -Executable 'sc.exe' -Arguments 'delete icingapowershell';
switch ($ServiceCreation.ExitCode) {
0 {
Write-IcingaConsoleNotice 'Icinga PowerShell Service was successfully removed';
}
1060 {
Write-IcingaConsoleWarning 'The Icinga PowerShell Service is not installed';
}
Default {
throw ([string]::Format('Failed to install Icinga PowerShell Service: {0}{1}', $ServiceCreation.Message, $ServiceCreation.Error));
}
}
}

View file

@ -18,6 +18,13 @@ function Get-IcingaAgentInstallation()
}
}
$IcingaService = Get-IcingaServices -Service 'icinga2';
$ServiceUser = 'NT AUTHORITY\NetworkService';
if ($null -ne $IcingaService) {
$ServiceUser = $IcingaService.icinga2.configuration.ServiceUser;
}
if ($null -eq $IcingaData) {
return @{
'Installed' = $FALSE;
@ -26,6 +33,7 @@ function Get-IcingaAgentInstallation()
'Architecture' = $architecture;
'Uninstaller' = '';
'InstallDate' = '';
'User' = $ServiceUser;
};
}
@ -36,5 +44,6 @@ function Get-IcingaAgentInstallation()
'Architecture' = $architecture;
'Uninstaller' = $IcingaData.UninstallString.Replace("MsiExec.exe ", "");
'InstallDate' = $IcingaData.InstallDate;
'User' = $ServiceUser;
};
}

View file

@ -724,7 +724,7 @@ function Start-IcingaAgentInstallWizard()
Set-IcingaAgentNodeName -Hostname $Hostname;
Set-IcingaAgentServiceUser -User $ServiceUser -Password $ServicePass -SetPermission | Out-Null;
if ($InstallFrameworkService) {
Install-IcingaFrameworkService -Path $ServiceBin -User $ServiceUser -Password $ServicePass | Out-Null;
Install-IcingaForWindowsService -Path $ServiceBin -User $ServiceUser -Password $ServicePass | Out-Null;
}
Register-IcingaBackgroundDaemon -Command 'Start-IcingaServiceCheckDaemon';
Install-IcingaAgentBaseFeatures;

View file

@ -1,6 +1,6 @@
function Set-IcingaAgentServiceUser()
{
param(
param (
[string]$User,
[securestring]$Password,
[string]$Service = 'icinga2',

View file

@ -103,10 +103,14 @@ function Install-Icinga()
'Help' = 'Allows you to install Icinga for Windows with all required components and options.'
},
@{
'Caption' = 'Update environment';
'Command' = '';
'Help' = 'Allows you to modify your current Icinga for Windows installation.';
'Disabled' = $TRUE;
'Caption' = 'Install Components';
'Command' = 'Show-IcingaForWindowsMenuInstallComponents';
'Help' = 'Allows you to install new components for Icinga for Windows from your repositories.';
},
@{
'Caption' = 'Update environment';
'Command' = 'Show-IcingaForWindowsMenuUpdateComponents';
'Help' = 'Allows you to modify your current Icinga for Windows installation.';
},
@{
'Caption' = 'Manage environment';

View file

@ -21,18 +21,17 @@ function Start-IcingaForWindowsInstallation()
# Icinga Agent
$AgentVersion = Get-IcingaForWindowsInstallerValuesFromStep -InstallerStep 'Show-IcingaForWindowsInstallationMenuEnterIcingaAgentVersion';
$AgentPackageType = Get-IcingaForWindowsInstallerStepSelection -InstallerStep 'Show-IcingaForWindowsInstallerMenuSelectIcingaAgentSource';
$InstallIcingaAgent = Get-IcingaForWindowsInstallerStepSelection -InstallerStep 'Show-IcingaForWindowsInstallerMenuSelectInstallIcingaAgent';
$AgentInstallDir = Get-IcingaForWindowsInstallerValuesFromStep -InstallerStep 'Show-IcingaForWindowsInstallationMenuEnterIcingaAgentDirectory';
$ServiceUser = Get-IcingaForWindowsInstallerValuesFromStep -InstallerStep 'Show-IcingaForWindowsInstallationMenuEnterIcingaAgentUser';
$ServicePassword = Get-IcingaForWindowsInstallerValuesFromStep -InstallerStep 'Show-IcingaForWindowsInstallationMenuEnterIcingaAgentServicePassword';
# Icinga for Windows Service
$WindowsServiceType = Get-IcingaForWindowsInstallerStepSelection -InstallerStep 'Show-IcingaForWindowsInstallerMenuSelectWindowsServiceSource';
$InstallPSService = Get-IcingaForWindowsInstallerStepSelection -InstallerStep 'Show-IcingaForWindowsInstallerMenuSelectInstallIcingaForWindowsService';
$WindowsServiceDir = Get-IcingaForWindowsInstallerValuesFromStep -InstallerStep 'Show-IcingaForWindowsInstallationMenuEnterWindowsServiceDirectory';
# Icinga for Windows Plugins
$WindowsPluginsType = Get-IcingaForWindowsInstallerStepSelection -InstallerStep 'Show-IcingaForWindowsInstallerMenuSelectIcingaPluginsSource';
$WindowsPluginsPackage = Get-IcingaForWindowsInstallerValuesFromStep -InstallerStep 'Show-IcingaForWindowsInstallerMenuEnterPluginsPackageSource';
$InstallPluginChoice = Get-IcingaForWindowsInstallerStepSelection -InstallerStep 'Show-IcingaForWindowsInstallerMenuSelectInstallIcingaPlugins';
# Global Zones
$GlobalZonesType = Get-IcingaForWindowsInstallerStepSelection -InstallerStep 'Show-IcingaForWindowsInstallerMenuSelectGlobalZones';
@ -43,10 +42,15 @@ function Start-IcingaForWindowsInstallation()
$IcingaEndpoints = Get-IcingaForWindowsInstallerValuesFromStep -InstallerStep 'Show-IcingaForWindowsInstallerMenuEnterIcingaParentNodes';
$IcingaPort = Get-IcingaForWindowsInstallerValuesFromStep -InstallerStep 'Show-IcingaForWindowsInstallationMenuEnterIcingaPort';
# Repository
$IcingaStableRepo = Get-IcingaForWindowsInstallerValuesFromStep -InstallerStep 'Show-IcingaForWindowsInstallationMenuStableRepository';
# JEA Profile
$InstallJEAProfile = Get-IcingaForWindowsInstallerStepSelection -InstallerStep 'Show-IcingaForWindowsInstallerMenuSelectInstallJEAProfile';
$Hostname = '';
$GlobalZones = @();
$IcingaParentAddresses = @();
$AgentPackageSource = ''
$ServicePackageSource = ''
$ServiceSourceGitHub = $FALSE;
$InstallAgent = $TRUE;
@ -55,6 +59,10 @@ function Start-IcingaForWindowsInstallation()
$PluginPackageRelease = $FALSE;
$PluginPackageSnapshot = $FALSE;
if ([string]::IsNullOrEmpty($IcingaStableRepo) -eq $FALSE) {
Add-IcingaRepository -Name 'Icinga Stable' -RemotePath $IcingaStableRepo;
}
foreach ($endpoint in $IcingaEndpoints) {
$EndpointAddress = Get-IcingaForWindowsInstallerValuesFromStep -InstallerStep 'Show-IcingaForWindowsInstallerMenuEnterIcingaParentAddresses' -Parent $endpoint;
@ -114,58 +122,39 @@ function Start-IcingaForWindowsInstallation()
}
}
switch ($AgentPackageType) {
switch ($InstallIcingaAgent) {
'0' {
# Install Icinga Agent from packages.icinga.com
$AgentPackageSource = ' https://packages.icinga.com/windows';
$InstallAgent = $TRUE;
break;
};
'1' {
# Install Icinga Agent from custom source
$AgentPackageSource = (Get-IcingaForWindowsInstallerValuesFromStep -InstallerStep 'Show-IcingaForWindowsInstallerMenuEnterIcingaAgentPackageSource');
break;
};
'2' {
# Do not install Icinga Agent
$InstallAgent = $FALSE;
break;
}
}
switch ($WindowsServiceType) {
switch ($InstallPSService) {
'0' {
#GitHub
$ServiceSourceGitHub = $TRUE;
# Install Icinga for Windows Service
$InstallService = $TRUE;
break;
};
'1' {
# Custom location
$ServicePackageSource = (Get-IcingaForWindowsInstallerValuesFromStep -InstallerStep 'Show-IcingaForWindowsInstallerMenuEnterWindowsServicePackageSource');
break;
};
'2' {
# Do not install Icinga for Windows service
$InstallService = $FALSE;
break;
}
}
switch ($WindowsPluginsType) {
switch ($InstallPluginChoice) {
'0' {
# Download Release from GitHub
# Download stable release
$PluginPackageRelease = $TRUE;
break;
};
'1' {
# Download Snapshot (master) from GitHub
$PluginPackageSnapshot = $TRUE;
break;
};
'2' {
# Use custom package source
break;
};
'3' {
# Do not install plugins
$InstallPlugins = $FALSE;
break;
@ -173,7 +162,8 @@ function Start-IcingaForWindowsInstallation()
}
if ($InstallAgent) {
Install-IcingaAgent -Version $AgentVersion -Source $AgentPackageSource -InstallDir $AgentInstallDir -AllowUpdates $TRUE | Out-Null;
Set-IcingaPowerShellConfig -Path 'Framework.Icinga.AgentLocation' -Value $AgentInstallDir;
Install-IcingaComponent -Name 'agent' -Version $AgentVersion -Confirm -Release;
Reset-IcingaAgentConfigFile;
Move-IcingaAgentDefaultConfig;
Set-IcingaAgentNodeName -Hostname $Hostname;
@ -198,14 +188,16 @@ function Start-IcingaForWindowsInstallation()
Write-IcingaAgentZonesConfig -Endpoints $IcingaEndpoints -EndpointConnections $IcingaParentAddresses -ParentZone $IcingaZone -GlobalZones $GlobalZones -Hostname $Hostname;
if ($InstallService) {
$ServiceData = Get-IcingaFrameworkServiceBinary -FrameworkServiceUrl $ServicePackageSource -Release:$ServiceSourceGitHub -ServiceDirectory $WindowsServiceDir;
Set-IcingaPowerShellConfig -Path 'Framework.Icinga.IcingaForWindowsService' -Value $WindowsServiceDir;
Set-IcingaPowerShellConfig -Path 'Framework.Icinga.ServiceUser' -User $ServiceUser;
Set-IcingaInternalPowerShellServicePassword -Password (ConvertTo-IcingaSecureString $ServicePassword);
Install-IcingaFrameworkService -Path $ServiceData.ServiceBin -User $ServiceUser -Password (ConvertTo-IcingaSecureString $ServicePassword) | Out-Null;
Install-IcingaComponent -Name 'service' -Release -Confirm;
Register-IcingaBackgroundDaemon -Command 'Start-IcingaServiceCheckDaemon';
}
if ($InstallPlugins) {
Install-IcingaFrameworkComponent -Name 'plugins' -Release:$PluginPackageRelease -Snapshot:$PluginPackageSnapshot -Url $WindowsPluginsPackage | Out-Null;
Install-IcingaComponent -Name 'plugins' -Release:$PluginPackageRelease -Snapshot:$PluginPackageSnapshot -Confirm;
}
switch ($FirewallType) {
@ -232,6 +224,20 @@ function Start-IcingaForWindowsInstallation()
Restart-IcingaService 'icingapowershell';
}
switch ($InstallJEAProfile) {
'0' {
Install-IcingaJEAProfile;
break;
};
'1' {
Install-IcingaSecurity;
break;
};
'2' {
# Do not install JEA profile
}
}
# Update configuration and clear swap
$ConfigSwap = Get-IcingaPowerShellConfig -Path 'Framework.Config.Swap';
Set-IcingaPowerShellConfig -Path 'Framework.Config.Swap' -Value $null;

View file

@ -15,12 +15,14 @@ function Add-IcingaForWindowsInstallationAdvancedEntries()
Show-IcingaForWindowsInstallerMenuSelectGlobalZones -Automated -Advanced;
Show-IcingaForWindowsInstallationMenuEnterCustomGlobalZones -Automated -Advanced;
Show-IcingaForWindowsInstallationMenuEnterIcingaAgentVersion -Automated -Advanced;
Show-IcingaForWindowsInstallerMenuSelectIcingaAgentSource -Automated -Advanced;
Show-IcingaForWindowsInstallerMenuSelectInstallIcingaAgent -Automated -Advanced;
Show-IcingaForWindowsInstallationMenuEnterIcingaAgentDirectory -Automated -Advanced;
Show-IcingaForWindowsInstallationMenuEnterIcingaAgentUser -Automated -Advanced;
Show-IcingaForWindowsInstallerMenuSelectIcingaPluginsSource -Automated -Advanced;
Show-IcingaForWindowsInstallerMenuSelectWindowsServiceSource -Automated -Advanced;
Show-IcingaForWindowsInstallerMenuSelectInstallIcingaPlugins -Automated -Advanced;
Show-IcingaForWindowsInstallerMenuSelectInstallIcingaForWindowsService -Automated -Advanced;
Show-IcingaForWindowsInstallationMenuEnterWindowsServiceDirectory -Automated -Advanced;
Show-IcingaForWindowsInstallationMenuStableRepository -Automated -Advanced;
Show-IcingaForWindowsInstallerMenuSelectInstallJEAProfile -Automated -Advanced;
Enable-IcingaFrameworkConsoleOutput;

View file

@ -1,31 +0,0 @@
function Show-IcingaForWindowsInstallerMenuEnterIcingaAgentPackageSource()
{
param (
[array]$Value = @( 'https://packages.icinga.com/windows/' ),
[string]$DefaultInput = 'c',
[switch]$JumpToSummary = $FALSE,
[switch]$Automated = $FALSE,
[switch]$Advanced = $FALSE
);
Show-IcingaForWindowsInstallerMenu `
-Header 'Please enter the location on where to find your Icinga Agent installation package:' `
-Entries @(
@{
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
'Help' = 'The location on where to find your Icinga Agent .MSI packages. You can specify a local path "C:\icinga\msi", a network path "\\example.com\software\icinga\" or a web path "https://example.com/icinga/windows". For the last variant it is required that the web server is printing the directory file list.';
}
) `
-DefaultIndex $DefaultInput `
-AddConfig `
-ConfigLimit 1 `
-DefaultValues $Value `
-ContinueFirstValue `
-MandatoryValue `
-JumpToSummary:$JumpToSummary `
-ConfigElement `
-Automated:$Automated `
-Advanced:$Advanced;
}
Set-Alias -Name 'IfW-AgentPackageSource' -Value 'Show-IcingaForWindowsInstallerMenuEnterIcingaAgentPackageSource';

View file

@ -0,0 +1,32 @@
function Show-IcingaForWindowsInstallerMenuSelectInstallIcingaAgent()
{
param (
[array]$Value = @(),
[string]$DefaultInput = '0',
[switch]$JumpToSummary = $FALSE,
[switch]$Automated = $FALSE,
[switch]$Advanced = $FALSE
);
Show-IcingaForWindowsInstallerMenu `
-Header 'Please select if the Icinga Agent should be installed' `
-Entries @(
@{
'Caption' = 'Install Icinga Agent';
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
'Help' = 'Downloads the Icinga Agent from the specified stable repository and installs it';
},
@{
'Caption' = 'Do not install Icinga Agent';
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
'Help' = 'Do not install the Icinga Agent on this system';
}
) `
-DefaultIndex $DefaultInput `
-JumpToSummary:$FALSE `
-ConfigElement `
-Automated:$Automated `
-Advanced:$Advanced;
}
Set-Alias -Name 'IfW-InstallAgent' -Value 'Show-IcingaForWindowsInstallerMenuSelectInstallIcingaAgent';

View file

@ -1,42 +0,0 @@
function Show-IcingaForWindowsInstallerMenuSelectIcingaAgentSource()
{
param (
[array]$Value = @(),
[string]$DefaultInput = '0',
[switch]$JumpToSummary = $FALSE,
[switch]$Automated = $FALSE,
[switch]$Advanced = $FALSE
);
Show-IcingaForWindowsInstallerMenu `
-Header 'Please select where your Icinga Agent .MSI package is downloaded from:' `
-Entries @(
@{
'Caption' = 'Download from "https://packages.icinga.com"';
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
'Help' = 'Download the Icinga Agent directly from "https://packages.icinga.com" for the specified version';
},
@{
'Caption' = 'Use custom source';
'Command' = 'Show-IcingaForWindowsInstallerMenuEnterIcingaAgentPackageSource';
'Help' = 'Specify the path on where the .MSI installer packages for the Icinga Agent can be found in your environment';
},
@{
'Caption' = 'Do not install Icinga Agent';
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
'Help' = 'Do not install the Icinga Agent on this system';
}
) `
-DefaultIndex $DefaultInput `
-JumpToSummary:$FALSE `
-ConfigElement `
-Automated:$Automated `
-Advanced:$Advanced;
# In case we use the default location, delete our custom location entry
if (Get-IcingaForWindowsManagementConsoleLastInput -ne '1') {
Remove-IcingaForWindowsInstallerConfigEntry -Menu 'Show-IcingaForWindowsInstallerMenuEnterIcingaAgentPackageSource';
}
}
Set-Alias -Name 'IfW-AgentSource' -Value 'Show-IcingaForWindowsInstallerMenuSelectIcingaAgentSource';

View file

@ -155,15 +155,14 @@ function Resolve-IcingaForWindowsManagementConsoleInstallationDirectorTemplate()
if ($DirectorConfig.install_framework_service -eq 0) {
# Do not install
$InstallServiceSelection = 2;
$InstallServiceSelection = 1;
} else {
# TODO: This is currently not supported. We use the "default" config for installing from GitHub by now
$InstallServiceSelection = 0;
}
if ($DirectorConfig.install_framework_plugins -eq 0) {
# Do not install
$InstallPluginsSelection = 3;
$InstallPluginsSelection = 1;
} else {
# TODO: This is currently not supported. We use the "default" config for installing from GitHub by now
$InstallPluginsSelection = 0;
@ -174,8 +173,8 @@ function Resolve-IcingaForWindowsManagementConsoleInstallationDirectorTemplate()
Add-IcingaForWindowsInstallationAdvancedEntries;
Disable-IcingaFrameworkConsoleOutput;
Show-IcingaForWindowsInstallerMenuSelectIcingaPluginsSource -DefaultInput $InstallPluginsSelection -Value @() -Automated;
Show-IcingaForWindowsInstallerMenuSelectWindowsServiceSource -DefaultInput $InstallServiceSelection -Value @() -Automated;
Show-IcingaForWindowsInstallerMenuSelectInstallIcingaPlugins -DefaultInput $InstallPluginsSelection -Value @() -Automated;
Show-IcingaForWindowsInstallerMenuSelectInstallIcingaForWindowsService -DefaultInput $InstallServiceSelection -Value @() -Automated;
Show-IcingaForWindowsInstallerMenuSelectOpenWindowsFirewall -DefaultInput $WindowsFirewallSelection -Value @() -Automated;
if ($Register) {

View file

@ -0,0 +1,30 @@
function Show-IcingaForWindowsInstallationMenuStableRepository()
{
param (
[array]$Value = @( 'https://packages.icinga.com/IcingaForWindows/stable' ),
[string]$DefaultInput = 'c',
[switch]$JumpToSummary = $FALSE,
[switch]$Automated = $FALSE,
[switch]$Advanced = $FALSE
);
Show-IcingaForWindowsInstallerMenu `
-Header 'Please enter the path or Url for your stable Icinga repository:' `
-Entries @(
@{
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
'Help' = 'This is the stable repository from where all packages of Icinga for Windows are downloaded and intstalled from. Defaults to "https://packages.icinga.com/IcingaForWindows/stable"';
}
) `
-DefaultIndex $DefaultInput `
-AddConfig `
-ConfigLimit 1 `
-DefaultValues @( $Value ) `
-MandatoryValue `
-JumpToSummary:$JumpToSummary `
-ConfigElement `
-Automated:$Automated `
-Advanced:$Advanced;
}
Set-Alias -Name 'IfW-StableRepository' -Value 'Show-IcingaForWindowsInstallationMenuStableRepository';

View file

@ -0,0 +1,41 @@
function Show-IcingaForWindowsInstallerMenuSelectInstallJEAProfile()
{
param (
[array]$Value = @(),
[string]$DefaultInput = '2',
[switch]$JumpToSummary = $FALSE,
[switch]$Automated = $FALSE,
[switch]$Advanced = $FALSE
);
if ($PSVersionTable.PSVersion -lt '5.0.0.0') {
return;
}
Show-IcingaForWindowsInstallerMenu `
-Header 'Please select if you want to install the JEA profile for the assigned service user or to create a managed user' `
-Entries @(
@{
'Caption' = 'Install JEA Profile';
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
'Help' = 'Installs the Icinga for Windows JEA profile for the specified service user';
},
@{
'Caption' = 'Install JEA Profile with managed user "IcingaForWindows"';
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
'Help' = 'Installs the Icinga for Windows JEA profile with a newly created, managed user "IcingaForWindows". This will override your service and service password configuration';
},
@{
'Caption' = 'Do not install JEA Profile';
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
'Help' = 'Do not install the Icinga for Windows JEA profile';
}
) `
-DefaultIndex $DefaultInput `
-JumpToSummary:$FALSE `
-ConfigElement `
-Automated:$Automated `
-Advanced:$Advanced;
}
Set-Alias -Name 'IfW-InstallJEAProfile' -Value 'Show-IcingaForWindowsInstallerMenuSelectInstallJEAProfile';

View file

@ -0,0 +1,32 @@
function Show-IcingaForWindowsInstallerMenuSelectInstallIcingaForWindowsService()
{
param (
[array]$Value = @(),
[string]$DefaultInput = '0',
[switch]$JumpToSummary = $FALSE,
[switch]$Automated = $FALSE,
[switch]$Advanced = $FALSE
);
Show-IcingaForWindowsInstallerMenu `
-Header 'Please select of you want to install the Icinga for Windows service:' `
-Entries @(
@{
'Caption' = 'Install Icinga for Windows Service';
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
'Help' = 'Installs the Icinga for Windows service from the provided stable repository';
},
@{
'Caption' = 'Do not install Icinga for Windows service';
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
'Help' = 'Select this if you do not want to install the Icinga for Windows service';
}
) `
-DefaultIndex $DefaultInput `
-JumpToSummary:$FALSE `
-ConfigElement `
-Automated:$Automated `
-Advanced:$Advanced;
}
Set-Alias -Name 'IfW-InstallPowerShellService' -Value 'Show-IcingaForWindowsInstallerMenuSelectInstallIcingaForWindowsService';

View file

@ -1,42 +0,0 @@
function Show-IcingaForWindowsInstallerMenuSelectWindowsServiceSource()
{
param (
[array]$Value = @(),
[string]$DefaultInput = '0',
[switch]$JumpToSummary = $FALSE,
[switch]$Automated = $FALSE,
[switch]$Advanced = $FALSE
);
Show-IcingaForWindowsInstallerMenu `
-Header 'Please select where the Icinga for Windows service binary is downloaded from:' `
-Entries @(
@{
'Caption' = 'Download latest release from GitHub';
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
'Help' = 'Download the latest stable release of the service binary directly from "https://github.com/Icinga/icinga-powershell-service/releases"';
},
@{
'Caption' = 'Use custom source';
'Command' = 'Show-IcingaForWindowsInstallerMenuEnterWindowsServicePackageSource';
'Help' = 'Specify a custom location from where to get the Icinga for Windows service package';
},
@{
'Caption' = 'Do not install service';
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
'Help' = 'Select this if you do not want to install the Icinga for Windows service';
}
) `
-DefaultIndex $DefaultInput `
-JumpToSummary:$FALSE `
-ConfigElement `
-Automated:$Automated `
-Advanced:$Advanced;
# In case we use the default location, delete our custom location entry
if (Get-IcingaForWindowsManagementConsoleLastInput -ne '1') {
Remove-IcingaForWindowsInstallerConfigEntry -Menu 'Show-IcingaForWindowsInstallerMenuEnterWindowsServicePackageSource';
}
}
Set-Alias -Name 'IfW-WindowsServiceSource' -Value 'Show-IcingaForWindowsInstallerMenuSelectWindowsServiceSource';

View file

@ -0,0 +1,32 @@
function Show-IcingaForWindowsInstallerMenuSelectInstallIcingaPlugins()
{
param (
[array]$Value = @(),
[string]$DefaultInput = '0',
[switch]$JumpToSummary = $FALSE,
[switch]$Automated = $FALSE,
[switch]$Advanced = $FALSE
);
Show-IcingaForWindowsInstallerMenu `
-Header 'Please select where your Icinga plugins are downloaded from:' `
-Entries @(
@{
'Caption' = 'Install plugins';
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
'Help' = 'Installs the Icinga Plugins from the defined stable repository';
},
@{
'Caption' = 'Do not install plugins';
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
'Help' = 'Select this if you do not want to install the plugins for the moment';
}
) `
-DefaultIndex $DefaultInput `
-JumpToSummary:$FALSE `
-ConfigElement `
-Automated:$Automated `
-Advanced:$Advanced;
}
Set-Alias -Name 'IfW-InstallPlugins' -Value 'Show-IcingaForWindowsInstallerMenuSelectInstallIcingaPlugins';

View file

@ -1,47 +0,0 @@
function Show-IcingaForWindowsInstallerMenuSelectIcingaPluginsSource()
{
param (
[array]$Value = @(),
[string]$DefaultInput = '0',
[switch]$JumpToSummary = $FALSE,
[switch]$Automated = $FALSE,
[switch]$Advanced = $FALSE
);
Show-IcingaForWindowsInstallerMenu `
-Header 'Please select where your Icinga plugins are downloaded from:' `
-Entries @(
@{
'Caption' = 'Download latest release from GitHub';
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
'Help' = 'Downloads the latest stable release directly from "https://github.com/icinga/icinga-powershell-plugins/releases"';
},
@{
'Caption' = 'Download snapshot from GitHub';
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
'Help' = 'Uses the master branch of the plugin repository for checkout. Not recommended in production';
},
@{
'Caption' = 'Use custom source';
'Command' = 'Show-IcingaForWindowsInstallerMenuEnterPluginsPackageSource';
'Help' = 'Specify a custom location from where to get your plugins from';
},
@{
'Caption' = 'Do not install plugins';
'Command' = 'Show-IcingaForWindowsInstallerConfigurationSummary';
'Help' = 'Select this if you do not want to install the plugins for the moment';
}
) `
-DefaultIndex $DefaultInput `
-JumpToSummary:$FALSE `
-ConfigElement `
-Automated:$Automated `
-Advanced:$Advanced;
# In case we use the default location, delete our custom location entry
if (Get-IcingaForWindowsManagementConsoleLastInput -ne '2') {
Remove-IcingaForWindowsInstallerConfigEntry -Menu 'Show-IcingaForWindowsInstallerMenuEnterPluginsPackageSource';
}
}
Set-Alias -Name 'IfW-PluginSource' -Value 'Show-IcingaForWindowsInstallerMenuSelectIcingaPluginsSource';

View file

@ -0,0 +1,52 @@
function Show-IcingaForWindowsMenuInstallComponents()
{
$IcingaInstallation = Get-IcingaComponentList;
$CurrentComponents = Get-IcingaInstallation -Release;
[int]$MaxComponentLength = Get-IcingaMaxTextLength -TextArray $IcingaInstallation.Components.Keys;
[array]$InstallList = @();
foreach ($entry in $IcingaInstallation.Components.Keys) {
$LatestVersion = $IcingaInstallation.Components[$entry];
$LockedVersion = Get-IcingaComponentLock -Name $entry;
$VersionText = $LatestVersion;
# Only show not installed components
if ($CurrentComponents.ContainsKey($entry)) {
continue;
}
if ($null -ne $LockedVersion) {
$VersionText = [string]::Format('{0}*', $LockedVersion);
$LatestVersion = $LockedVersion;
}
$InstallList += @{
'Caption' = ([string]::Format('{0} [{1}]', (Add-IcingaWhiteSpaceToString -Text $entry -Length $MaxComponentLength), $VersionText));
'Command' = 'Show-IcingaForWindowsMenuInstallComponents';
'Help' = ([string]::Format('This will install the component "{0}" with version "{1}"', $entry, $VersionText));
'Disabled' = $FALSE;
'Action' = @{
'Command' = 'Show-IcingaWindowsManagementConsoleYesNoDialog';
'Arguments' = @{
'-Caption' = ([string]::Format('Install component "{0}" with version "{1}"', $entry, $VersionText));
'-Command' = 'Install-IcingaComponent';
'-CmdArguments' = @{
'-Name' = $entry;
'-Version' = $LatestVersion;
'-Release' = $TRUE;
'-Confirm' = $TRUE;
}
}
}
}
}
if ($InstallList.Count -ne 0) {
Show-IcingaForWindowsInstallerMenu `
-Header 'Install Icinga for Windows components. Select an entry to continue:' `
-Entries $InstallList;
} else {
Show-IcingaForWindowsInstallerMenu `
-Header 'There are no packages found for installation'
}
}

View file

@ -1,9 +1,11 @@
function Show-IcingaForWindowsMenuRemoveComponents()
{
[array]$UninstallFeatures = @();
$AgentInstalled = Get-Service -Name 'icinga2' -ErrorAction SilentlyContinue;
$ModuleList = Get-Module 'icinga-powershell-*' -ListAvailable;
[array]$UninstallFeatures = @();
$AgentInstalled = Get-Service -Name 'icinga2' -ErrorAction SilentlyContinue;
$PowerShellServiceInstalled = Get-Service -Name 'icingapowershell' -ErrorAction SilentlyContinue;
$IcingaWindowsServiceData = Get-IcingaForWindowsServiceData;
$ModuleList = Get-Module 'icinga-powershell-*' -ListAvailable;
$UninstallFeatures += @{
'Caption' = 'Uninstall Icinga Agent';
@ -13,8 +15,11 @@ function Show-IcingaForWindowsMenuRemoveComponents()
'Action' = @{
'Command' = 'Show-IcingaWindowsManagementConsoleYesNoDialog';
'Arguments' = @{
'-Caption' = 'Uninstall Icinga Agent';
'-Command' = 'Uninstall-IcingaAgent';
'-Caption' = 'Uninstall Icinga Agent';
'-Command' = 'Uninstall-IcingaComponent';
'-CmdArguments' = @{
'-Name' = 'agent';
}
}
}
}
@ -28,9 +33,45 @@ function Show-IcingaForWindowsMenuRemoveComponents()
'Command' = 'Show-IcingaWindowsManagementConsoleYesNoDialog';
'Arguments' = @{
'-Caption' = 'Uninstall Icinga Agent (include ProgramData)';
'-Command' = 'Uninstall-IcingaAgent';
'-Command' = 'Uninstall-IcingaComponent';
'-CmdArguments' = @{
'-RemoveDataFolder' = $TRUE;
'-Name' = 'agent';
'-RemovePackageFiles' = $TRUE;
}
}
}
}
$UninstallFeatures += @{
'Caption' = 'Uninstall Icinga for Windows Service';
'Command' = 'Show-IcingaForWindowsMenuRemoveComponents';
'Help' = 'This will remove the icingapowershell service for Icinga for Windows if installed'
'Disabled' = ($null -eq $PowerShellServiceInstalled);
'Action' = @{
'Command' = 'Show-IcingaWindowsManagementConsoleYesNoDialog';
'Arguments' = @{
'-Caption' = 'Uninstall Icinga for Windows service';
'-Command' = 'Uninstall-IcingaComponent';
'-CmdArguments' = @{
'-Name' = 'service';
}
}
}
}
$UninstallFeatures += @{
'Caption' = 'Uninstall Icinga for Windows Service (include files)';
'Command' = 'Show-IcingaForWindowsMenuRemoveComponents';
'Help' = 'This will remove the icingapowershell service for Icinga for Windows if installed and the service binary including the folder, if empty afterwards'
'Disabled' = (-Not (Test-Path $IcingaWindowsServiceData.Directory));
'Action' = @{
'Command' = 'Show-IcingaWindowsManagementConsoleYesNoDialog';
'Arguments' = @{
'-Caption' = 'Uninstall Icinga for Windows service (include files)';
'-Command' = 'Uninstall-IcingaComponent';
'-CmdArguments' = @{
'-Name' = 'service';
'-RemovePackageFiles' = $TRUE;
}
}
}
@ -40,7 +81,7 @@ function Show-IcingaForWindowsMenuRemoveComponents()
$ComponentName = $module.Name.Replace('icinga-powershell-', '');
$Caption = ([string]::Format('Uninstall component "{0}"', $ComponentName));
if ($ComponentName -eq 'framework') {
if ($ComponentName -eq 'framework' -Or $ComponentName -eq 'service' -Or $ComponentName -eq 'agent') {
continue;
}
@ -53,7 +94,7 @@ function Show-IcingaForWindowsMenuRemoveComponents()
'Command' = 'Show-IcingaWindowsManagementConsoleYesNoDialog';
'Arguments' = @{
'-Caption' = $Caption;
'-Command' = 'Uninstall-IcingaFrameworkComponent';
'-Command' = 'Uninstall-IcingaComponent';
'-CmdArguments' = @{
'-Name' = $ComponentName;
}

View file

@ -0,0 +1,68 @@
function Show-IcingaForWindowsMenuUpdateComponents()
{
$IcingaInstallation = Get-IcingaInstallation -Release;
[int]$MaxComponentLength = Get-IcingaMaxTextLength -TextArray $IcingaInstallation.Keys;
[array]$UpdateList = @();
foreach ($entry in $IcingaInstallation.Keys) {
$Component = $IcingaInstallation[$entry];
$LatestVersion = $Component.LatestVersion;
if ([string]::IsNullOrEmpty($Component.LockedVersion) -eq $FALSE) {
if ([Version]$Component.CurrentVersion -ge [Version]$Component.LockedVersion) {
continue;
}
$LatestVersion = [string]::Format('{0}*', $Component.LockedVersion);
}
if ([string]::IsNullOrEmpty($LatestVersion)) {
continue;
}
$UpdateList += @{
'Caption' = ([string]::Format('{0} [{1}] => [{2}]', (Add-IcingaWhiteSpaceToString -Text $entry -Length $MaxComponentLength), $Component.CurrentVersion, $LatestVersion));
'Command' = 'Show-IcingaForWindowsMenuUpdateComponents';
'Help' = ([string]::Format('This will update the component "{0}" from current version "{1}" to stable version "{2}"', $entry, $Component.CurrentVersion, $LatestVersion));
'Disabled' = $FALSE;
'Action' = @{
'Command' = 'Show-IcingaWindowsManagementConsoleYesNoDialog';
'Arguments' = @{
'-Caption' = ([string]::Format('Update component "{0}" from version "{1}" to stable version "{2}"', $entry, $Component.CurrentVersion, $LatestVersion));
'-Command' = 'Update-Icinga';
'-CmdArguments' = @{
'-Name' = $entry;
'-Release' = $TRUE;
'-Confirm' = $TRUE;
}
}
}
}
}
if ($UpdateList.Count -ne 0) {
$UpdateList += @{
'Caption' = 'Update entire environment';
'Command' = 'Show-IcingaForWindowsMenuUpdateComponents';
'Help' = 'This will update all components listed above to the mentioned stable version'
'Disabled' = $FALSE;
'Action' = @{
'Command' = 'Show-IcingaWindowsManagementConsoleYesNoDialog';
'Arguments' = @{
'-Caption' = 'Update entire Icinga for Windows environment';
'-Command' = 'Update-Icinga';
'-CmdArguments' = @{
'-Release' = $TRUE;
'-Confirm' = $TRUE;
}
}
}
}
Show-IcingaForWindowsInstallerMenu `
-Header 'Updates Icinga for Windows components. Select an entry to continue:' `
-Entries $UpdateList;
} else {
Show-IcingaForWindowsInstallerMenu `
-Header 'There are no updates pending for your environment'
}
}

View file

@ -0,0 +1,8 @@
function Get-IcingaInternalPowerShellServicePassword()
{
if ($null -eq $global:Icinga -Or $Global:Icinga.ContainsKey('InstallerServicePassword') -eq $FALSE) {
return $null;
}
return $Global:Icinga.InstallerServicePassword;
}

View file

@ -0,0 +1,25 @@
function Set-IcingaInternalPowerShellServicePassword()
{
param (
[SecureString]$Password = $null
);
if ($null -eq $global:Icinga) {
$Global:Icinga = @{
'InstallerServicePassword' = $Password;
}
return;
}
if ($Global:Icinga.ContainsKey('InstallerServicePassword') -eq $FALSE) {
$Global:Icinga.Add(
'InstallerServicePassword',
$Password
)
return;
}
$Global:Icinga.InstallerServicePassword = $Password;
}

View file

@ -0,0 +1,43 @@
function Add-IcingaRepository()
{
param (
[string]$Name = $null,
[string]$RemotePath = $null
);
if ([string]::IsNullOrEmpty($Name)) {
Write-IcingaConsoleError 'You have to provide a name for the repository';
return;
}
if ([string]::IsNullOrEmpty($RemotePath)) {
Write-IcingaConsoleError 'You have to provide a remote path for the repository';
return;
}
$CurrentRepositories = Get-IcingaPowerShellConfig -Path 'Framework.Repository.Repositories';
if ($null -eq $CurrentRepositories) {
$CurrentRepositories = New-Object -TypeName PSObject;
}
if (Test-IcingaPowerShellConfigItem -ConfigObject $CurrentRepositories -ConfigKey $Name) {
Write-IcingaConsoleError 'A repository with the given name "{0}" does already exist.' -Objects $Name;
return;
}
[array]$RepoCount = $CurrentRepositories.PSObject.Properties.Count;
$CurrentRepositories | Add-Member -MemberType NoteProperty -Name $Name -Value (New-Object -TypeName PSObject);
$CurrentRepositories.$Name | Add-Member -MemberType NoteProperty -Name 'LocalPath' -Value $null;
$CurrentRepositories.$Name | Add-Member -MemberType NoteProperty -Name 'RemotePath' -Value $RemotePath;
$CurrentRepositories.$Name | Add-Member -MemberType NoteProperty -Name 'CloneSource' -Value $null;
$CurrentRepositories.$Name | Add-Member -MemberType NoteProperty -Name 'UseSCP' -Value $FALSE;
$CurrentRepositories.$Name | Add-Member -MemberType NoteProperty -Name 'Order' -Value $RepoCount.Count;
$CurrentRepositories.$Name | Add-Member -MemberType NoteProperty -Name 'Enabled' -Value $True;
Set-IcingaPowerShellConfig -Path 'Framework.Repository.Repositories' -Value $CurrentRepositories;
Push-IcingaRepository -Name $Name -Silent;
Write-IcingaConsoleNotice 'Remote repository "{0}" was successfully added' -Objects $Name;
}

View file

@ -0,0 +1,27 @@
function Disable-IcingaRepository()
{
param (
[string]$Name = $null
);
if ([string]::IsNullOrEmpty($Name)) {
Write-IcingaConsoleError 'You have to provide a name for the repository';
return;
}
$CurrentRepositories = Get-IcingaPowerShellConfig -Path ([string]::Format('Framework.Repository.Repositories.{0}', $Name));
if ($null -eq $CurrentRepositories) {
Write-IcingaConsoleError 'A repository with the name "{0}" is not configured' -Objects $Name;
return;
}
if ($CurrentRepositories.Enabled -eq $FALSE) {
Write-IcingaConsoleNotice 'The repository "{0}" is already disabled' -Objects $Name;
return;
}
Set-IcingaPowerShellConfig -Path ([string]::Format('Framework.Repository.Repositories.{0}.Enabled', $Name)) -Value $FALSE;
Write-IcingaConsoleNotice 'The repository "{0}" was successfully disabled' -Objects $Name;
}

View file

@ -0,0 +1,27 @@
function Enable-IcingaRepository()
{
param (
[string]$Name = $null
);
if ([string]::IsNullOrEmpty($Name)) {
Write-IcingaConsoleError 'You have to provide a name for the repository';
return;
}
$CurrentRepositories = Get-IcingaPowerShellConfig -Path ([string]::Format('Framework.Repository.Repositories.{0}', $Name));
if ($null -eq $CurrentRepositories) {
Write-IcingaConsoleError 'A repository with the name "{0}" is not configured' -Objects $Name;
return;
}
if ($CurrentRepositories.Enabled -eq $TRUE) {
Write-IcingaConsoleNotice 'The repository "{0}" is already enabled' -Objects $Name;
return;
}
Set-IcingaPowerShellConfig -Path ([string]::Format('Framework.Repository.Repositories.{0}.Enabled', $Name)) -Value $TRUE;
Write-IcingaConsoleNotice 'The repository "{0}" was successfully enabled' -Objects $Name;
}

View file

@ -0,0 +1,64 @@
function Get-IcingaComponentList()
{
param (
[switch]$Snapshot = $FALSE
);
$Repositories = Get-IcingaRepositories -ExcludeDisabled;
[Version]$LatestVersion = $null;
[string]$SourcePath = $null;
[bool]$FoundPackage = $FALSE;
[array]$Output = @();
[bool]$FoundPackage = $FALSE;
$SearchList = New-Object -TypeName PSObject;
$SearchList | Add-Member -MemberType NoteProperty -Name 'Repos' -Value @();
$SearchList | Add-Member -MemberType NoteProperty -Name 'Components' -Value @{ };
foreach ($entry in $Repositories) {
$RepoContent = Read-IcingaRepositoryFile -Name $entry.Name;
if ($null -eq $RepoContent) {
continue;
}
if ((Test-IcingaPowerShellConfigItem -ConfigObject $RepoContent -ConfigKey 'Packages') -eq $FALSE) {
continue;
}
foreach ($repoEntry in $RepoContent.Packages.PSObject.Properties.Name) {
$RepoData = New-Object -TypeName PSObject;
$RepoData | Add-Member -MemberType NoteProperty -Name 'Name' -Value $entry.Name;
$RepoData | Add-Member -MemberType NoteProperty -Name 'RemoteSource' -Value $RepoContent.Info.RemoteSource;
$RepoData | Add-Member -MemberType NoteProperty -Name 'ComponentName' -Value $repoEntry;
$RepoData | Add-Member -MemberType NoteProperty -Name 'Packages' -Value @();
foreach ($package in $RepoContent.Packages.$repoEntry) {
$ComponentData = New-Object -TypeName PSObject;
$ComponentData | Add-Member -MemberType NoteProperty -Name 'Version' -Value $package.Version;
$ComponentData | Add-Member -MemberType NoteProperty -Name 'Location' -Value $package.Location;
$ComponentData | Add-Member -MemberType NoteProperty -Name 'Snapshot' -Value $package.Snapshot;
if ($Snapshot -And $package.Snapshot -eq $FALSE) {
continue;
}
if ($SearchList.Components.ContainsKey($repoEntry) -eq $FALSE) {
$SearchList.Components.Add($repoEntry, $package.Version);
}
if ([version]($SearchList.Components[$repoEntry]) -lt [version]$package.Version) {
$SearchList.Components[$repoEntry] = $package.Version;
}
$RepoData.Packages += $ComponentData;
}
$SearchList.Repos += $RepoData;
}
}
return $SearchList;
}

View file

@ -0,0 +1,23 @@
function Get-IcingaComponentLock()
{
param (
[string]$Name = $null
);
if ([string]::IsNullOrEmpty($Name)) {
Write-IcingaConsoleError 'You have to specify the component to get the lock version';
return;
}
$LockedComponents = Get-IcingaPowerShellConfig -Path 'Framework.Repository.ComponentLock';
if ($null -eq $LockedComponents) {
return $null;
}
if (Test-IcingaPowerShellConfigItem -ConfigObject $LockedComponents -ConfigKey $Name) {
return $LockedComponents.$Name;
}
return $null;
}

View file

@ -0,0 +1,26 @@
function Get-IcingaForWindowsServiceData()
{
$IcingaForWindowsService = Get-IcingaServices -Service 'icingapowershell';
[hashtable]$ServiceData = @{
'Directory' = '';
'FullPath' = '';
'User' = '';
}
if ($null -ne $IcingaForWindowsService) {
$ServicePath = $IcingaForWindowsService.icingapowershell.configuration.ServicePath;
$ServicePath = $ServicePath.SubString(0, $ServicePath.IndexOf('.exe') + 4);
$ServicePath = $ServicePath.Replace('"', '');
$ServiceData.FullPath = $ServicePath;
$ServiceData.Directory = $ServicePath.Substring(0, $ServicePath.LastIndexOf('\') + 1);
$ServiceData.User = $IcingaForWindowsService.icingapowershell.configuration.ServiceUser;
return $ServiceData;
}
$ServiceData.Directory = (Join-Path -Path $env:ProgramFiles -ChildPath 'icinga-framework-service');
$ServiceData.User = 'NT Authority\NetworkService';
return $ServiceData;
}

View file

@ -0,0 +1,108 @@
function Get-IcingaInstallation()
{
param (
[switch]$Release = $FALSE,
[switch]$Snapshot = $FALSE
)
[hashtable]$InstalledComponents = @{ };
$PowerShellModules = Get-Module -ListAvailable;
foreach ($entry in $PowerShellModules) {
$RootPath = (Get-IcingaForWindowsRootPath);
if ($entry.Path -NotLike "$RootPath*") {
continue;
}
if ($entry.Name -Like 'icinga-powershell-*') {
$ComponentName = $entry.Name.Replace('icinga-powershell-', '');
$InstallPackage = (Get-IcingaRepositoryPackage -Name $ComponentName -Release:$Release -Snapshot:$Snapshot);
$LatestVersion = '';
$CurrentVersion = ([string]((Get-Module -ListAvailable -Name $entry.Name -ErrorAction SilentlyContinue) | Sort-Object Version -Descending | Select-Object Version -First 1).Version);
if ($InstallPackage.HasPackage) {
[string]$LatestVersion = $InstallPackage.Package.Version;
}
if ([string]::IsNullOrEmpty($LatestVersion) -eq $FALSE -And [Version]$LatestVersion -le [Version]$CurrentVersion) {
$LatestVersion = '';
}
Add-IcingaHashtableItem `
-Hashtable $InstalledComponents `
-Key $ComponentName `
-Value @{
'Path' = (Join-Path -Path $RootPath -ChildPath $entry.Name);
'CurrentVersion' = $CurrentVersion;
'LatestVersion' = $LatestVersion;
'LockedVersion' = (Get-IcingaComponentLock -Name $ComponentName);
} | Out-Null;
}
}
$IcingaForWindowsService = Get-IcingaServices -Service 'icingapowershell';
if ($null -ne $IcingaForWindowsService) {
$ServicePath = Get-IcingaForWindowsServiceData;
if ($InstalledComponents.ContainsKey('service')) {
$InstalledComponents.Remove('service');
}
$InstallPackage = (Get-IcingaRepositoryPackage -Name 'service' -Release:$Release -Snapshot:$Snapshot);
$LatestVersion = '';
$CurrentVersion = ([string]((Read-IcingaServicePackage -File $ServicePath.FullPath).ProductVersion));
if ($InstallPackage.HasPackage) {
[string]$LatestVersion = $InstallPackage.Package.Version;
}
if ([string]::IsNullOrEmpty($LatestVersion) -eq $FALSE -And [Version]$LatestVersion -le [Version]$CurrentVersion) {
$LatestVersion = '';
}
$InstalledComponents.Add(
'service',
@{
'Path' = $ServicePath.Directory;
'CurrentVersion' = $CurrentVersion;
'LatestVersion' = $LatestVersion;
'LockedVersion' = (Get-IcingaComponentLock -Name 'service');
}
)
}
$IcingaAgent = Get-IcingaAgentInstallation;
if ($InstalledComponents.ContainsKey('agent')) {
$InstalledComponents.Remove('agent');
}
if ($IcingaAgent.Installed) {
$InstallPackage = (Get-IcingaRepositoryPackage -Name 'agent' -Release:$Release -Snapshot:$Snapshot);
$LatestVersion = '';
$CurrentVersion = ([string]$IcingaAgent.Version.Full);
if ($InstallPackage.HasPackage) {
$LatestVersion = $InstallPackage.Package.Version;
}
if ([string]::IsNullOrEmpty($LatestVersion) -eq $FALSE -And [Version]$LatestVersion -le [Version]$CurrentVersion) {
$LatestVersion = '';
}
$InstalledComponents.Add(
'agent',
@{
'Path' = $IcingaAgent.RootDir;
'CurrentVersion' = $CurrentVersion;
'LatestVersion' = $LatestVersion;
'LockedVersion' = (Get-IcingaComponentLock -Name 'agent');
}
)
}
return $InstalledComponents;
}

View file

@ -0,0 +1,25 @@
function Get-IcingaRepositories()
{
param (
[switch]$ExcludeDisabled = $FALSE
);
$CurrentRepositories = Get-IcingaPowerShellConfig -Path 'Framework.Repository.Repositories';
[array]$RepoList = $CurrentRepositories.PSObject.Properties | Sort-Object { $_.Value.Order } -Descending;
if ($ExcludeDisabled -eq $FALSE) {
return $RepoList;
}
[array]$ActiveRepos = @();
foreach ($repo in $RepoList) {
if ($repo.Value.Enabled -eq $FALSE) {
continue;
}
$ActiveRepos += $repo;
}
return $ActiveRepos;
}

View file

@ -0,0 +1,23 @@
function Get-IcingaRepositoryHash()
{
param (
[string]$Path
);
if ([string]::IsNullOrEmpty($Path) -Or (Test-Path $Path) -eq $FALSE) {
Write-IcingaConsoleError 'The provided path "{0}" does not exist' -Objects $Path;
return;
}
$RepositoryFolder = Get-ChildItem -Path $Path -Recurse;
[array]$FileHashes = @();
foreach ($entry in $RepositoryFolder) {
$FileHashes += (Get-FileHash -Path $entry.FullName -Algorithm SHA256).Hash;
}
$HashAlgorithm = [System.Security.Cryptography.HashAlgorithm]::Create('SHA256');
$BinaryHash = $HashAlgorithm.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($FileHashes.ToString()))
return [System.BitConverter]::ToString($BinaryHash).Replace('-', '');
}

View file

@ -0,0 +1,78 @@
function Get-IcingaRepositoryPackage()
{
param (
[string]$Name,
[string]$Version = $null,
[switch]$Release = $FALSE,
[switch]$Snapshot = $FALSE
);
if ([string]::IsNullOrEmpty($Name)) {
Write-IcingaConsoleError 'You have to provide a component name';
return;
}
$Repositories = Get-IcingaRepositories -ExcludeDisabled;
[Version]$LatestVersion = $null;
$InstallPackage = $null;
$SourceRepo = $null;
$RepoName = $null;
[bool]$HasRepo = $FALSE;
foreach ($entry in $Repositories) {
$RepoContent = Read-IcingaRepositoryFile -Name $entry.Name;
[bool]$FoundPackage = $FALSE;
if ($null -eq $RepoContent) {
continue;
}
if ((Test-IcingaPowerShellConfigItem -ConfigObject $RepoContent -ConfigKey 'Packages') -eq $FALSE) {
continue;
}
if ((Test-IcingaPowerShellConfigItem -ConfigObject $RepoContent.Packages -ConfigKey $Name) -eq $FALSE) {
continue;
}
foreach ($package in $RepoContent.Packages.$Name) {
if ($Snapshot -And $package.Snapshot -eq $FALSE) {
continue;
}
if ($Release -And $package.Snapshot -eq $TRUE) {
continue;
}
if ([string]::IsNullOrEmpty($Version) -And ($null -eq $LatestVersion -Or $LatestVersion -lt $package.Version)) {
[Version]$LatestVersion = [Version]$package.Version;
$InstallPackage = $package;
$HasRepo = $TRUE;
$SourceRepo = $RepoContent;
$RepoName = $entry.Name;
continue;
}
if ([string]::IsNullOrEmpty($Version) -eq $FALSE -And [version]$package.Version -eq [version]$Version) {
$InstallPackage = $package;
$FoundPackage = $TRUE;
$HasRepo = $TRUE;
$SourceRepo = $RepoContent;
$RepoName = $entry.Name;
break;
}
}
if ($FoundPackage) {
break;
}
}
return @{
'HasPackage' = $HasRepo;
'Package' = $InstallPackage;
'Source' = $SourceRepo;
'Repository' = $RepoName;
};
}

View file

@ -0,0 +1,354 @@
function Install-IcingaComponent()
{
param (
[string]$Name = $null,
[string]$Version = $null,
[switch]$Release = $FALSE,
[switch]$Snapshot = $FALSE,
[switch]$Confirm = $FALSE,
[switch]$Force = $FALSE
);
if ([string]::IsNullOrEmpty($Name)) {
Write-IcingaConsoleError 'You have to provide a component name';
return;
}
Set-IcingaTLSVersion;
if ($Version -eq 'release') {
$Version = $null;
}
if ($Release -eq $TRUE -And $Snapshot -eq $TRUE) {
Write-IcingaConsoleError 'You can only select either "Release" or "Snapshot" channel for package installation';
return;
}
if ($Release -eq $FALSE -And $Snapshot -eq $FALSE) {
$Release = $TRUE;
}
$LockedVersion = Get-IcingaComponentLock -Name $Name;
if ($null -ne $LockedVersion) {
$Version = $LockedVersion;
Write-IcingaConsoleNotice 'Component "{0}" is locked to version "{1}"' -Objects $Name, $LockedVersion;
}
$PackageContent = Get-IcingaRepositoryPackage -Name $Name -Version $Version -Release:$Release -Snapshot:$Snapshot;
$InstallPackage = $PackageContent.Package;
$SourceRepo = $PackageContent.Source;
$RepoName = $PackageContent.Repository;
if ($PackageContent.HasPackage -eq $FALSE) {
$SearchVersion = 'release';
if ([string]::IsNullOrEmpty($Version) -eq $FALSE) {
$SearchVersion = $Version;
}
if ($Release) {
Write-IcingaConsoleError 'The component "{0}" was not found on stable channel with version "{1}"' -Objects $Name, $SearchVersion;
return;
}
if ($Snapshot) {
Write-IcingaConsoleError 'The component "{0}" was not found on snapshot channel with version "{1}"' -Objects $Name, $SearchVersion;
return;
}
return;
}
$FileSource = $InstallPackage.Location;
if ($InstallPackage.RelativePath -eq $TRUE) {
$FileSource = Join-WebPath -Path ($SourceRepo.Info.RemoteSource.Replace('\', '/')) -ChildPath ($InstallPackage.Location.Replace('\', '/'));
}
if ($Confirm -eq $FALSE) {
if ((Get-IcingaAgentInstallerAnswerInput -Prompt ([string]::Format('Do you want to install component "{0}" from source "{1}" ({2})?', $Name.ToLower(), $RepoName, $FileSource)) -Default 'y').result -ne 1) {
return;
}
}
$FileName = $FileSource.SubString($FileSource.LastIndexOf('/') + 1, $FileSource.Length - $FileSource.LastIndexOf('/') - 1);
$DownloadDirectory = New-IcingaTemporaryDirectory;
$DownloadDestination = (Join-Path -Path $DownloadDirectory -ChildPath $FileName);
Write-IcingaConsoleNotice ([string]::Format('Downloading "{0}" from "{1}"', $Name.ToLower(), $FileSource));
if ((Invoke-IcingaWebRequest -UseBasicParsing -Uri $FileSource -OutFile $DownloadDestination).HasErrors) {
Write-IcingaConsoleError ([string]::Format('Failed to download "{0}" from "{1}" into "{2}". Starting cleanup process', $Name.ToLower(), $FileSource, $DownloadDestination));
Start-Sleep -Seconds 2;
Remove-Item -Path $DownloadDirectory -Recurse -Force;
return;
}
$FileHash = (Get-FileHash -Path $DownloadDestination -Algorithm SHA256).Hash;
if ([string]::IsNullOrEmpty($InstallPackage.Hash) -eq $FALSE -And (Get-FileHash -Path $DownloadDestination -Algorithm SHA256).Hash -ne $InstallPackage.Hash) {
Write-IcingaConsoleError ([string]::Format('File validation failed. The stored hash inside the repository "{0}" is not matching the file hash "{1}"', $InstallPackage.Hash, $FileHash));
return;
}
if ([IO.Path]::GetExtension($FileName) -eq '.zip') {
<#
Handles installation of Icinga for Windows packages and Icinga for Windows service
#>
Expand-IcingaZipArchive -Path $DownloadDestination -Destination $DownloadDirectory | Out-Null;
Start-Sleep -Seconds 2;
Remove-Item -Path $DownloadDestination -Force;
$FolderContent = Get-ChildItem -Path $DownloadDirectory -Recurse -Include '*.psd1';
<#
Handles installation of Icinga for Windows packages
#>
if ($null -ne $FolderContent -And $FolderContent.Count -ne 0) {
$ManifestFile = $null;
$PackageName = $null;
$PackageRoot = $null;
foreach ($manifest in $FolderContent) {
$ManifestFile = Read-IcingaPackageManifest -File $manifest.FullName;
if ($null -ne $ManifestFile) {
$PackageName = $manifest.Name.Replace('.psd1', '');
$PackageRoot = $manifest.FullName.SubString(0, $manifest.FullName.LastIndexOf('\'));
$PackageRoot = Join-Path -Path $PackageRoot -ChildPath '\*'
break;
}
}
if ($null -eq $ManifestFile) {
Write-IcingaConsoleError ([string]::Format('Unable to read manifest for package "{0}". Aborting installation', $Name.ToLower()));
Start-Sleep -Seconds 2;
Remove-Item -Path $DownloadDirectory -Recurse -Force;
return;
}
$ComponentFolder = Join-Path -Path (Get-IcingaForWindowsRootPath) -ChildPath $PackageName;
$ModuleData = (Get-Module -ListAvailable -Name $PackageName -ErrorAction SilentlyContinue) | Sort-Object Version -Descending | Select-Object Version -First 1;
[string]$InstallVersion = $null;
$ServiceStatus = $null;
$AgentStatus = $null;
if ($null -ne $ModuleData) {
[string]$InstallVersion = $ModuleData.Version;
}
if ($ManifestFile.ModuleVersion -eq $InstallVersion -And $Force -eq $FALSE) {
Write-IcingaConsoleError ([string]::Format('The package "{0}" with version "{1}" is already installed. Use "-Force" to re-install the component', $Name.ToLower(), $ManifestFile.ModuleVersion));
Start-Sleep -Seconds 2;
Remove-Item -Path $DownloadDirectory -Recurse -Force;
return;
}
# These update steps only apply for the framework
if ($Name.ToLower() -eq 'framework') {
$ServiceStatus = (Get-Service 'icingapowershell' -ErrorAction SilentlyContinue).Status;
$AgentStatus = (Get-Service 'icinga2' -ErrorAction SilentlyContinue).Status;
if ($ServiceStatus -eq 'Running') {
Write-IcingaConsoleNotice 'Stopping Icinga for Windows service';
Stop-IcingaService 'icingapowershell';
Start-Sleep -Seconds 1;
}
if ($AgentStatus -eq 'Running') {
Write-IcingaConsoleNotice 'Stopping Icinga Agent service';
Stop-IcingaService 'icinga2';
Start-Sleep -Seconds 1;
}
}
if ((Test-Path $ComponentFolder) -eq $FALSE) {
[void](New-Item -ItemType Directory -Path $ComponentFolder -Force);
}
$ComponentFileContent = Get-ChildItem -Path $ComponentFolder;
foreach ($entry in $ComponentFileContent) {
if (($entry.Name -eq 'cache' -Or $entry.Name -eq 'config') -And $Name.ToLower() -eq 'framework') {
continue;
}
[void](Remove-ItemSecure -Path $entry.FullName -Recurse -Force);
}
[void](Copy-ItemSecure -Path $PackageRoot -Destination $ComponentFolder -Recurse -Force);
Write-IcingaConsoleNotice 'Installing version "{0}" of component "{1}"' -Objects $ManifestFile.ModuleVersion, $Name.ToLower();
Unblock-IcingaPowerShellFiles -Path $ComponentFolder;
if ($Name.ToLower() -eq 'framework') {
if (Test-IcingaFunction 'Write-IcingaFrameworkCodeCache') {
Write-IcingaFrameworkCodeCache;
}
if ($ServiceStatus -eq 'Running') {
Write-IcingaConsoleNotice 'Starting Icinga for Windows service';
Start-IcingaService 'icingapowershell';
}
if ($AgentStatus -eq 'Running') {
Write-IcingaConsoleNotice 'Starting Icinga Agent service';
Start-IcingaService 'icinga2';
}
}
Import-Module -Name $PackageName -Force;
Write-IcingaConsoleNotice 'Installation of component "{0}" with version "{1}" was successful. Open a new PowerShell to apply the changes' -Objects $Name.ToLower(), $ManifestFile.ModuleVersion;
} else {
<#
Handles installation of Icinga for Windows service
#>
$FolderContent = Get-ChildItem -Path $DownloadDirectory -Recurse -Include 'icinga-service.exe';
if ($Name.ToLower() -eq 'service') {
$ConfigDirectory = Get-IcingaPowerShellConfig -Path 'Framework.Icinga.IcingaForWindowsService';
$ConfigUser = Get-IcingaPowerShellConfig -Path 'Framework.Icinga.ServiceUser';
$ServiceData = Get-IcingaForWindowsServiceData;
$ServiceDirectory = $ServiceData.Directory;
$ServiceUser = $ServiceData.User;
if ([string]::IsNullOrEmpty($ConfigDirectory) -eq $FALSE) {
$ServiceDirectory = $ConfigDirectory;
}
if ([string]::IsNullOrEmpty($ConfigUser) -eq $FALSE) {
$ServiceUser = $ConfigUser;
}
foreach ($binary in $FolderContent) {
if ((Test-IcingaZipBinaryChecksum -Path $binary.FullName) -eq $FALSE) {
Write-IcingaConsoleError 'The checksum for the given service binary does not match';
continue;
}
if ((Test-Path $ServiceDirectory) -eq $FALSE) {
[void](New-Item -ItemType Directory -Path $ServiceDirectory -Force);
}
$UpdateBin = Join-Path -Path $ServiceDirectory -ChildPath 'icinga-service.exe.update';
$ServiceBin = Join-Path -Path $ServiceDirectory -ChildPath 'icinga-service.exe';
# Service is already installed
if (Test-Path $ServiceBin) {
$InstalledService = Read-IcingaServicePackage -File $ServiceBin;
$NewService = Read-IcingaServicePackage -File $binary.FullName;
if ($InstalledService.ProductVersion -eq $NewService.ProductVersion -And $null -ne $InstalledService -And $null -ne $NewService -And $Force -eq $FALSE) {
Write-IcingaConsoleError ([string]::Format('The package "service" with version "{0}" is already installed. Use "-Force" to re-install the component', $InstalledService.ProductVersion));
Start-Sleep -Seconds 2;
Remove-Item -Path $DownloadDirectory -Recurse -Force;
return;
}
}
Write-IcingaConsoleNotice 'Installing component "service" into "{0}"' -Objects $ServiceDirectory;
Copy-ItemSecure -Path $binary.FullName -Destination $UpdateBin -Force;
[void](Install-IcingaForWindowsService -Path $ServiceBin -User $ServiceUser -Password (Get-IcingaInternalPowerShellServicePassword));
Set-IcingaInternalPowerShellServicePassword -Password $null;
Start-Sleep -Seconds 2;
Remove-Item -Path $DownloadDirectory -Recurse -Force;
Write-IcingaConsoleNotice 'Installation of component "service" was successful'
return;
}
Write-IcingaConsoleError 'Failed to install component "service". Either the package did not include a service binary or the checksum of the binary did not match';
Start-Sleep -Seconds 2;
Remove-Item -Path $DownloadDirectory -Recurse -Force;
return;
} else {
Write-IcingaConsoleError 'There was no manifest file found inside the package';
Remove-Item -Path $DownloadDirectory -Recurse -Force;
return;
}
}
} elseif ([IO.Path]::GetExtension($FileName) -eq '.msi') {
<#
Handles installation of Icinga Agent MSI Packages
#>
$IcingaData = Get-IcingaAgentInstallation;
$InstalledVersion = Get-IcingaAgentVersion;
$InstallTarget = $IcingaData.RootDir;
$InstallDir = Get-IcingaPowerShellConfig -Path 'Framework.Icinga.AgentLocation';
$ConfigUser = Get-IcingaPowerShellConfig -Path 'Framework.Icinga.ServiceUser';
$ServiceUser = $IcingaData.User;
if ([string]::IsNullOrEmpty($InstallDir) -eq $FALSE) {
if ((Test-Path $InstallDir) -eq $FALSE) {
[void](New-Item -Path $InstallDir -ItemType Directory -Force);
}
$InstallTarget = $InstallDir;
}
if ([string]::IsNullOrEmpty($ConfigUser) -eq $FALSE) {
$ServiceUser = $ConfigUser;
}
[string]$InstallFolderMsg = $InstallTarget;
if ([string]::IsNullOrEmpty($InstallTarget) -eq $FALSE) {
$InstallTarget = [string]::Format(' INSTALL_ROOT="{0}"', $InstallTarget);
} else {
$InstallTarget = '';
if ($IcingaData.Architecture -eq 'x86') {
$InstallFolderMsg = Join-Path -Path ${env:ProgramFiles(x86)} -ChildPath 'icinga2';
} else {
$InstallFolderMsg = Join-Path -Path $env:ProgramFiles -ChildPath 'icinga2';
}
}
$MSIData = & powershell.exe -Command { Use-Icinga; return Read-IcingaMSIMetadata -File $args[0] } -Args $DownloadDestination;
if ($InstalledVersion.Full -eq $MSIData.ProductVersion -And $Force -eq $FALSE) {
Write-IcingaConsoleError 'The package "agent" with version "{0}" is already installed. Use "-Force" to re-install the component' -Objects $InstalledVersion.Full;
Remove-Item -Path $DownloadDirectory -Recurse -Force;
return;
}
Write-IcingaConsoleNotice 'Installing component "agent" with version "{0}" into "{1}"' -Objects $MSIData.ProductVersion, $InstallFolderMsg;
if ($IcingaData.Installed) {
if ((Uninstall-IcingaAgent) -eq $FALSE) {
return;
}
}
$InstallProcess = powershell.exe -Command {
$IcingaInstaller = $args[0];
$InstallTarget = $args[1];
Use-Icinga;
$InstallProcess = Start-IcingaProcess -Executable 'MsiExec.exe' -Arguments ([string]::Format('/quiet /i "{0}" {1}', $IcingaInstaller, $InstallTarget)) -FlushNewLines;
return $InstallProcess;
} -Args $DownloadDestination, $InstallTarget;
if ($InstallProcess.ExitCode -ne 0) {
Write-IcingaConsoleError -Message 'Failed to install component "agent": {0}{1}' -Objects $InstallProcess.Message, $InstallProcess.Error;
return $FALSE;
}
Set-IcingaAgentServiceUser -User $ServiceUser -SetPermission;
Write-IcingaConsoleNotice 'Installation of component "agent" with version "{0}" was successful.' -Objects $MSIData.ProductVersion;
} else {
Write-IcingaConsoleError ([string]::Format('Unsupported file extension "{0}" found for package "{1}". Aborting installation', ([IO.Path]::GetExtension($FileName)), $Name.ToLower()));
}
Start-Sleep -Seconds 1;
Remove-Item -Path $DownloadDirectory -Recurse -Force;
}

View file

@ -0,0 +1,51 @@
function Lock-IcingaComponent()
{
param (
[string]$Name = $null,
[string]$Version = $null
);
if ([string]::IsNullOrEmpty($Name)) {
Write-IcingaConsoleError 'You have to specify the component to lock';
return;
}
$Name = $Name.ToLower();
if ([string]::IsNullOrEmpty($Version)) {
if ($Name -eq 'agent') {
$Version = (Get-IcingaAgentVersion).Full;
} else {
$ModuleData = Get-Module -ListAvailable -Name ([string]::Format('icinga-powershell-{0}', $Name)) -ErrorAction SilentlyContinue;
if ($null -eq $ModuleData) {
$ModuleData = Get-Module -ListAvailable -Name "*$Name*" -ErrorAction SilentlyContinue;
}
if ($null -ne $ModuleData) {
$Version = $ModuleData.Version.ToString();
$Name = (Read-IcingaPackageManifest -File $ModuleData.Path).ComponentName;
}
}
}
if ([string]::IsNullOrEmpty($Version)) {
Write-IcingaConsoleError 'Pinning the current version of component "{0}" is not possible, as it seems to be not installed. Please install the component first or manually specify version with "-Version"';
return;
}
$LockedComponents = Get-IcingaPowerShellConfig -Path 'Framework.Repository.ComponentLock';
if ($null -eq $LockedComponents) {
$LockedComponents = New-Object -TypeName PSObject;
}
if (Test-IcingaPowerShellConfigItem -ConfigObject $LockedComponents -ConfigKey $Name) {
$LockedComponents.$Name = $Version;
} else {
$LockedComponents | Add-Member -MemberType NoteProperty -Name $Name -Value $Version;
}
Write-IcingaConsoleNotice 'Locking of component "{0}" to version "{1}" successful. You can release the lock with "Unlock-IcingaComponent -Name {2}{0}{2}"' -Objects $Name, $Version, "'";
Set-IcingaPowerShellConfig -Path 'Framework.Repository.ComponentLock' -Value $LockedComponents;
}

View file

@ -0,0 +1,54 @@
function New-IcingaRepository()
{
param (
[string]$Name = $null,
[string]$Path = $null,
[string]$RemotePath = $null,
[switch]$Force = $FALSE
);
if ([string]::IsNullOrEmpty($Name)) {
Write-IcingaConsoleError 'You have to provide a name for the repository';
return;
}
if ([string]::IsNullOrEmpty($Path) -Or (Test-Path $Path) -eq $FALSE) {
Write-IcingaConsoleError 'The provided path "{0}" does not exist' -Objects $Path;
return;
}
if ([string]::IsNullOrEmpty($RemotePath)) {
Write-IcingaConsoleWarning 'No explicit remote path has been defined. Using local path "{0}" as remote path' -Objects $Path;
$RemotePath = $Path;
}
$CurrentRepositories = Get-IcingaPowerShellConfig -Path 'Framework.Repository.Repositories';
if ($null -eq $CurrentRepositories) {
$CurrentRepositories = New-Object -TypeName PSObject;
}
if (Test-IcingaPowerShellConfigItem -ConfigObject $CurrentRepositories -ConfigKey $Name) {
Write-IcingaConsoleError 'A repository with the given name "{0}" does already exist. Use "Update-IcingaRepository -Name {1}{0}{1}" to update it.' -Objects $Name, "'";
return;
}
$IcingaRepository = New-IcingaRepositoryFile -Path $Path -RemotePath $RemotePath;
[array]$ConfigCount = $IcingaRepository.Packages.PSObject.Properties.Count;
if ($ConfigCount.Count -eq 0) {
Write-IcingaConsoleWarning 'Created empty repository at location "{0}"' -Objects $Path;
}
[array]$RepoCount = $CurrentRepositories.PSObject.Properties.Count;
$CurrentRepositories | Add-Member -MemberType NoteProperty -Name $Name -Value (New-Object -TypeName PSObject);
$CurrentRepositories.$Name | Add-Member -MemberType NoteProperty -Name 'LocalPath' -Value $Path;
$CurrentRepositories.$Name | Add-Member -MemberType NoteProperty -Name 'RemotePath' -Value $RemotePath;
$CurrentRepositories.$Name | Add-Member -MemberType NoteProperty -Name 'CloneSource' -Value $null;
$CurrentRepositories.$Name | Add-Member -MemberType NoteProperty -Name 'UseSCP' -Value $FALSE;
$CurrentRepositories.$Name | Add-Member -MemberType NoteProperty -Name 'Order' -Value $RepoCount.Count;
$CurrentRepositories.$Name | Add-Member -MemberType NoteProperty -Name 'Enabled' -Value $True;
Set-IcingaPowerShellConfig -Path 'Framework.Repository.Repositories' -Value $CurrentRepositories;
}

View file

@ -0,0 +1,91 @@
function New-IcingaRepositoryFile()
{
param (
[string]$Path = $null,
[string]$RemotePath = $null
);
$RepoFile = 'ifw.repo.json';
$RepoPath = Join-Path -Path $Path -ChildPath $RepoFile;
$IcingaRepository = New-Object -TypeName PSObject;
$IcingaRepository | Add-Member -MemberType NoteProperty -Name 'Info' -Value (New-Object -TypeName PSObject);
# Info
$IcingaRepository.Info | Add-Member -MemberType NoteProperty -Name 'LocalSource' -Value $Path;
$IcingaRepository.Info | Add-Member -MemberType NoteProperty -Name 'RemoteSource' -Value $RemotePath;
$IcingaRepository.Info | Add-Member -MemberType NoteProperty -Name 'Created' -Value ((Get-Date).ToUniversalTime().ToString('yyyy\/MM\/dd HH:mm:ss'));
$IcingaRepository.Info | Add-Member -MemberType NoteProperty -Name 'Updated' -Value $IcingaRepository.Info.Created;
$IcingaRepository.Info | Add-Member -MemberType NoteProperty -Name 'RepoHash' -Value $null;
# Packages
$IcingaRepository | Add-Member -MemberType NoteProperty -Name 'Packages' -Value (New-Object -TypeName PSObject);
$RepositoryFolder = Get-ChildItem -Path $Path -Recurse -Include '*.msi', '*.zip';
foreach ($entry in $RepositoryFolder) {
$RepoFilePath = $entry.FullName.Replace($Path, '');
$FileHash = Get-FileHash -Path $entry.FullName -Algorithm SHA256;
$ComponentName = '';
$IcingaForWindowsPackage = New-Object -TypeName PSObject;
$IcingaForWindowsPackage | Add-Member -MemberType NoteProperty -Name 'Hash' -Value $FileHash.Hash;
$IcingaForWindowsPackage | Add-Member -MemberType NoteProperty -Name 'Location' -Value $RepoFilePath;
$IcingaForWindowsPackage | Add-Member -MemberType NoteProperty -Name 'RelativePath' -Value $TRUE;
if ([IO.Path]::GetExtension($entry.Name) -eq '.zip') {
$IcingaPackage = Read-IcingaPackageManifest -File $entry.FullName;
$IcingaService = $null;
$Version = $null;
if ($null -ne $IcingaPackage) {
$PackageVersion = $IcingaPackage.ModuleVersion;
$ComponentName = $IcingaPackage.ComponentName;
} else {
$IcingaService = Read-IcingaServicePackage -File $entry.FullName;
}
if ($null -ne $IcingaService) {
$PackageVersion = $IcingaService.ProductVersion;
$ComponentName = $IcingaService.ComponentName;
}
[bool]$IsSnapshot = $FALSE;
if ($entry.FullName.ToLower() -like '*\master.zip') {
$IsSnapshot = $TRUE;
}
if ([string]::IsNullOrEmpty($ComponentName) -eq $FALSE) {
$IcingaForWindowsPackage | Add-Member -MemberType NoteProperty -Name 'Version' -Value $PackageVersion;
$IcingaForWindowsPackage | Add-Member -MemberType NoteProperty -Name 'Snapshot' -Value $IsSnapshot;
$IcingaForWindowsPackage | Add-Member -MemberType NoteProperty -Name 'Architecture' -Value 'Multi';
}
} elseif ([IO.Path]::GetExtension($entry.Name) -eq '.msi') {
$IcingaPackage = Read-IcingaMSIMetadata -File $entry.FullName;
if ([string]::IsNullOrEmpty($IcingaPackage.ProductName) -eq $FALSE -And $IcingaPackage.ProductName -eq 'Icinga 2') {
$IcingaForWindowsPackage | Add-Member -MemberType NoteProperty -Name 'Version' -Value $IcingaPackage.ProductVersion;
$IcingaForWindowsPackage | Add-Member -MemberType NoteProperty -Name 'Snapshot' -Value $IcingaPackage.Snapshot;
$IcingaForWindowsPackage | Add-Member -MemberType NoteProperty -Name 'Architecture' -Value $IcingaPackage.Architecture;
$ComponentName = 'agent';
}
}
if ([string]::IsNullOrEmpty($ComponentName)) {
continue;
}
if (Test-IcingaPowerShellConfigItem -ConfigObject $IcingaRepository.Packages -ConfigKey $ComponentName) {
$IcingaRepository.Packages.$ComponentName += $IcingaForWindowsPackage;
} else {
$IcingaRepository.Packages | Add-Member -MemberType NoteProperty -Name $ComponentName -Value @();
$IcingaRepository.Packages.$ComponentName += $IcingaForWindowsPackage;
}
$IcingaRepository.Info.RepoHash = Get-IcingaRepositoryHash -Path $Path;
}
Set-Content -Path $RepoPath -Value (ConvertTo-Json -InputObject $IcingaRepository -Depth 100);
return $IcingaRepository;
}

View file

@ -0,0 +1,36 @@
function Pop-IcingaRepository()
{
param (
[string]$Name = $null
);
if ([string]::IsNullOrEmpty($Name)) {
Write-IcingaConsoleError 'You have to provide a name for the repository';
return;
}
$CurrentRepositories = Get-IcingaPowerShellConfig -Path 'Framework.Repository.Repositories';
if ($null -eq $CurrentRepositories) {
Write-IcingaConsoleNotice 'You have no repositories configured yet.';
return;
}
[array]$RepoList = Get-IcingaRepositories;
[int]$Index = $RepoList.Count - 1;
foreach ($repo in $RepoList) {
if ($repo.Name -eq $Name) {
continue;
}
$CurrentRepositories.($repo.Name).Order = [int]$Index;
$Index -= 1;
}
$CurrentRepositories.$Name.Order = [int]$Index;
Write-IcingaConsoleNotice 'The repository "{0}" was put at the bottom of the repository list' -Objects $Name;
Set-IcingaPowerShellConfig -Path 'Framework.Repository.Repositories' -Value $CurrentRepositories;
}

View file

@ -0,0 +1,43 @@
function Push-IcingaRepository()
{
param (
[string]$Name = $null,
[switch]$Silent = $FALSE
);
if ([string]::IsNullOrEmpty($Name)) {
if ($Silent -eq $FALSE) {
Write-IcingaConsoleError 'You have to provide a name for the repository';
}
return;
}
$CurrentRepositories = Get-IcingaPowerShellConfig -Path 'Framework.Repository.Repositories';
if ($null -eq $CurrentRepositories) {
if ($Silent -eq $FALSE) {
Write-IcingaConsoleNotice 'You have no repositories configured yet.';
}
return;
}
[array]$RepoList = Get-IcingaRepositories;
[int]$Index = 0;
foreach ($repo in $RepoList) {
if ($repo.Name -eq $Name) {
continue;
}
$CurrentRepositories.($repo.Name).Order = [int]$Index;
$Index += 1;
}
$CurrentRepositories.$Name.Order = [int]$Index;
if ($Silent -eq $FALSE) {
Write-IcingaConsoleNotice 'The repository "{0}" was put at the top of the repository list' -Objects $Name;
}
Set-IcingaPowerShellConfig -Path 'Framework.Repository.Repositories' -Value $CurrentRepositories;
}

View file

@ -0,0 +1,77 @@
function Read-IcingaMSIMetadata()
{
param (
[string]$File = $null
);
if ([string]::IsNullOrEmpty($File) -Or (Test-Path $File) -eq $FALSE) {
Write-IcingaConsoleError 'The provided file "{0}" does not exist' -Objects $File;
return $null;
}
if ([IO.Path]::GetExtension($File) -ne '.msi') {
Write-IcingaConsoleError 'This Cmdlet is only supporting files with .msi extension. Extension "{0}" given.' -Objects ([IO.Path]::GetExtension($File));
return $null;
}
$AgentFile = Get-Item $File;
$MSIPackageData = @{
'ProductCode' = '';
'ProductVersion' = '';
'ProductName' = '';
}
[array]$MSIObjects = $MSIPackageData.Keys;
try {
$InstallerInstance = New-Object -ComObject 'WindowsInstaller.Installer';
$MSIPackage = $InstallerInstance.OpenDatabase($File, 0);
foreach ($PackageInfo in $MSIObjects) {
$MSIQuery = [string]::Format(
"SELECT `Value` FROM `Property` WHERE `Property` = '{0}'",
$PackageInfo
);
$MSIDb = $MSIPackage.OpenView($MSIQuery);
if ($null -eq $MSIDb) {
continue;
}
$MSIDb.Execute();
$MSITable = $MSIDb.Fetch();
if ($null -eq $MSITable) {
continue;
}
$MSIPackageData[$PackageInfo] = $MSITable.GetType().InvokeMember('StringData', 'GetProperty', $null, $MSITable, 1);
$MSIDb.Close();
$MSIPackage.Commit();
}
$MSIPackage.Commit();
$MSIPackage = $null;
[void]([System.Runtime.InteropServices.Marshal]::ReleaseComObject($InstallerInstance));
if ($AgentFile.Name.Contains('x86_64')) {
$MSIPackageData.Add('Architecture', 'x64')
} else {
$MSIPackageData.Add('Architecture', 'x86')
}
[Version]$PackageVersion = $MSIPackageData.ProductVersion;
if ($PackageVersion.Revision -eq -1) {
$MSIPackageData.Add('Snapshot', $False);
} else {
$MSIPackageData.Add('Snapshot', $True);
}
return $MSIPackageData;
} catch {
Write-IcingaConsoleError 'Failed to query MSI package information for package "{0}". Exception: {1}' -Objects $File, $_.Exception.Message;
}
return $null;
}

View file

@ -0,0 +1,96 @@
function Read-IcingaPackageManifest()
{
param (
[string]$File = $null
);
if ([string]::IsNullOrEmpty($File) -Or (Test-Path $File) -eq $FALSE) {
Write-IcingaConsoleError 'The provided file "{0}" does not exist' -Objects $File;
return $null;
}
if ((Test-IcingaAddTypeExist 'System.IO.Compression.FileSystem') -eq $FALSE) {
Add-Type -Assembly 'System.IO.Compression.FileSystem';
}
if ([IO.Path]::GetExtension($File) -ne '.zip' -And [IO.Path]::GetExtension($File) -ne '.psd1') {
Write-IcingaConsoleError 'Your Icinga for Windows manifest must be inside a .zip file or directly given on the "-File" argument. Extension "{0}" given.' -Objects ([IO.Path]::GetExtension($File));
return $null;
}
try {
$ZipPackage = $null;
if ([IO.Path]::GetExtension($File) -eq '.zip') {
$ZipPackage = [System.IO.Compression.ZipFile]::OpenRead($File);
$PackageManifest = $null;
$FileName = $null;
foreach ($entry in $ZipPackage.Entries) {
if ([IO.Path]::GetExtension($entry.FullName) -ne '.psd1') {
continue;
}
$FileName = $entry.Name.Replace('.psd1', '');
$FilePath = $entry.FullName.Replace($entry.Name, '');
$FileStream = $entry.Open();
$FileReader = [System.IO.StreamReader]::new($FileStream);
$PackageManifestContent = $FileReader.ReadToEnd();
$FileReader.Dispose();
[ScriptBlock]$PackageScript = [ScriptBlock]::Create('return ' + $PackageManifestContent);
$PackageManifest = (& $PackageScript);
if ($null -eq $PackageManifest -Or $PackageManifest.Count -eq 0) {
continue;
}
if ($PackageManifest.ContainsKey('PrivateData') -eq $FALSE -Or $PackageManifest.ContainsKey('ModuleVersion') -eq $FALSE) {
continue;
}
break;
}
$ZipPackage.Dispose();
} elseif ([IO.Path]::GetExtension($File) -eq '.psd1') {
$FileName = (Get-Item -Path $File).Name.Replace('.psd1', '');
$PackageManifestContent = Get-Content -Path $File -Raw;
[ScriptBlock]$PackageScript = [ScriptBlock]::Create('return ' + $PackageManifestContent);
$PackageManifest = (& $PackageScript);
} else {
return $null;
}
if ($null -eq $PackageManifest) {
return $null;
}
$PackageManifest.Add('ComponentName', '');
if ([string]::IsNullOrEmpty($FileName) -eq $FALSE) {
if ($FileName.Contains('icinga-powershell-*')) {
$PackageManifest.ComponentName = $FileName.Replace('icinga-powershell-', '');
} else {
if ($PackageManifest.ContainsKey('PrivateData') -And $PackageManifest.PrivateData.ContainsKey('Name') -And $PackageManifest.PrivateData.ContainsKey('Type')) {
if ($PackageManifest.PrivateData.Name -eq 'Icinga for Windows' -And $PackageManifest.PrivateData.Type -eq 'framework') {
$PackageManifest.ComponentName = 'framework';
} else {
$PackageManifest.ComponentName = ($PackageManifest.PrivateData.Name -Replace 'Windows' -Replace '\W').ToLower();
}
}
}
}
return $PackageManifest;
} catch {
$ExMsg = $_.Exception.Message;
Write-IcingaConsoleError 'Failed to read package content and/or manifest file: {0}' -Objects $ExMsg;
} finally {
if ($null -ne $ZipPackage) {
$ZipPackage.Dispose();
}
}
return $null;
}

View file

@ -0,0 +1,66 @@
function Read-IcingaRepositoryFile()
{
param (
[string]$Name = $null
);
if ([string]::IsNullOrEmpty($Name)) {
Write-IcingaConsoleError 'You have to provide a name for the repository';
return $null;
}
$Repository = Get-IcingaPowerShellConfig -Path ([string]::Format('Framework.Repository.Repositories.{0}', $Name));
if ($null -eq $Repository) {
Write-IcingaConsoleError 'A repository with the given name "{0}" does not exist. Use "New-IcingaRepository" or "Sync-IcingaForWindowsRepository" to create a new one.' -Objects $Name;
return $null;
}
$RepoPath = $null;
$Content = $null;
if ([string]::IsNullOrEmpty($Repository.LocalPath) -eq $FALSE -And (Test-Path -Path $Repository.LocalPath)) {
$RepoPath = $Repository.LocalPath;
$Content = Get-Content -Path (Join-Path -Path $RepoPath -ChildPath 'ifw.repo.json') -Raw;
} elseif ([string]::IsNullOrEmpty($Repository.RemotePath) -eq $FALSE -And (Test-Path -Path $Repository.RemotePath)) {
$RepoPath = $Repository.RemotePath;
$WebContent = Get-Content -Path (Join-Path -Path $RepoPath -ChildPath 'ifw.repo.json') -Raw;
} else {
try {
$WebContent = Invoke-WebRequest -UseBasicParsing -Uri $Repository.RemotePath;
$RepoPath = $Repository.RemotePath;
} catch {
# Nothing to do
}
if ($null -eq $WebContent) {
try {
$WebContent = Invoke-WebRequest -UseBasicParsing -Uri (Join-WebPath -Path $Repository.RemotePath -ChildPath 'ifw.repo.json');
} catch {
Write-IcingaConsoleError 'Failed to read repository file from "{0}" or "{0}/ifw.repo.json". Exception: {1}' -Objects $Repository.RemotePath, $_.Exception.Message;
return $null;
}
$RepoPath = $Repository.RemotePath;
}
if ($null -eq $WebContent) {
Write-IcingaConsoleError 'Unable to fetch data for repository "{0}" from any configured location' -Objects $Name;
return $null;
}
if ($WebContent.RawContent.Contains('application/octet-stream')) {
$Content = [System.Text.Encoding]::UTF8.GetString($WebContent.Content)
} else {
$Content = $WebContent.Content;
}
}
if ($null -eq $Content) {
Write-IcingaConsoleError 'Unable to fetch data for repository "{0}" from any configured location' -Objects $Name;
return $null;
}
$RepositoryObject = ConvertFrom-Json -InputObject $Content;
return $RepositoryObject;
}

View file

@ -0,0 +1,90 @@
function Read-IcingaServicePackage()
{
param (
[string]$File = $null
);
if ([string]::IsNullOrEmpty($File) -Or (Test-Path $File) -eq $FALSE) {
Write-IcingaConsoleError 'The provided file "{0}" does not exist' -Objects $File;
return $null;
}
if ((Test-IcingaAddTypeExist 'System.IO.Compression.FileSystem') -eq $FALSE) {
Add-Type -Assembly 'System.IO.Compression.FileSystem';
}
if ([IO.Path]::GetExtension($File) -ne '.zip' -And [IO.Path]::GetExtension($File) -ne '.exe') {
Write-IcingaConsoleError 'Your service binary must be inside a .zip file or directly given on the "-File" argument. Extension "{0}" given.' -Objects ([IO.Path]::GetExtension($File));
return $null;
}
[hashtable]$BinaryData = @{
'CompanyName' = '';
'FileVersion' = '';
'ProductVersion' = '';
'ComponentName' = 'service';
}
try {
$ZipPackage = $null;
if ([IO.Path]::GetExtension($File) -eq '.zip') {
$ZipPackage = [System.IO.Compression.ZipFile]::OpenRead($File);
foreach ($entry in $ZipPackage.Entries) {
if ([IO.Path]::GetExtension($entry.FullName) -ne '.exe') {
continue;
}
$ServiceTempDir = New-IcingaTemporaryDirectory;
$BinaryFile = (Join-Path -Path $ServiceTempDir -ChildPath $entry.Name);
[System.IO.Compression.ZipFileExtensions]::ExtractToFile(
$entry,
(Join-Path -Path $ServiceTempDir -ChildPath $entry.Name),
$TRUE
);
$ServiceBin = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($BinaryFile);
if ($ServiceBin.CompanyName -ne 'Icinga GmbH') {
Remove-Item -Path $ServiceTempDir -Recurse -Force;
continue;
}
$BinaryData.CompanyName = $ServiceBin.CompanyName;
$BinaryData.ProductVersion = ([version]($ServiceBin.ProductVersion)).ToString(3);
$BinaryData.FileVersion = ([version]($ServiceBin.FileVersion)).ToString(3);
break;
}
$ZipPackage.Dispose();
} elseif ([IO.Path]::GetExtension($File) -eq '.exe') {
$ServiceBin = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($File);
if ($ServiceBin.CompanyName -ne 'Icinga GmbH') {
return $null;
}
$BinaryData.CompanyName = $ServiceBin.CompanyName;
$BinaryData.ProductVersion = ([version]($ServiceBin.ProductVersion)).ToString(3);
$BinaryData.FileVersion = ([version]($ServiceBin.FileVersion)).ToString(3);
} else {
return $null;
}
if ([string]::IsNullOrEmpty($BinaryData.ProductVersion)) {
return $null;
}
return $BinaryData;
} catch {
$ExMsg = $_.Exception.Message;
Write-IcingaConsoleError 'Failed to read package content and/or binary file: {0}' -Objects $ExMsg;
} finally {
if ($null -ne $ZipPackage) {
$ZipPackage.Dispose();
}
}
return $null;
}

View file

@ -0,0 +1,29 @@
function Remove-IcingaRepository()
{
param (
[string]$Name = $null
);
if ([string]::IsNullOrEmpty($Name)) {
Write-IcingaConsoleError 'You have to provide a name for the repository to remove';
return;
}
$CurrentRepositories = Get-IcingaPowerShellConfig -Path 'Framework.Repository.Repositories';
if ((Test-IcingaPowerShellConfigItem -ConfigObject $CurrentRepositories -ConfigKey $Name) -eq $FALSE) {
Write-IcingaConsoleError 'A repository with the name "{0}" is not configured' -Objects $Name;
return;
}
Push-IcingaRepository -Name $Name -Silent;
Remove-IcingaPowerShellConfig -Path (
[string]::Format(
'Framework.Repository.Repositories.{0}',
$Name
)
);
Write-IcingaConsoleNotice 'The repository with the name "{0}" was successfully removed' -Objects $Name;
}

View file

@ -0,0 +1,126 @@
function Search-IcingaRepository()
{
param (
[string]$Name = $null,
[string]$Version = $null,
[switch]$Release = $FALSE,
[switch]$Snapshot = $FALSE
);
if ($Version -eq 'release') {
$Version = $null;
}
if ([string]::IsNullOrEmpty($Name)) {
Write-IcingaConsoleError 'You have to provide a component name';
return;
}
if ($Release -eq $FALSE -And $Snapshot -eq $FALSE) {
$Release = $TRUE;
}
$Repositories = Get-IcingaRepositories -ExcludeDisabled;
[Version]$LatestVersion = $null;
[string]$SourcePath = $null;
[bool]$FoundPackage = $FALSE;
[array]$Output = @();
[bool]$FoundPackage = $FALSE;
$SearchList = New-Object -TypeName PSObject;
$SearchList | Add-Member -MemberType NoteProperty -Name 'Repos' -Value @();
foreach ($entry in $Repositories) {
$RepoContent = Read-IcingaRepositoryFile -Name $entry.Name;
if ($null -eq $RepoContent) {
continue;
}
if ((Test-IcingaPowerShellConfigItem -ConfigObject $RepoContent -ConfigKey 'Packages') -eq $FALSE) {
continue;
}
foreach ($repoEntry in $RepoContent.Packages.PSObject.Properties.Name) {
if ($repoEntry -NotLike $Name) {
continue;
}
$RepoData = New-Object -TypeName PSObject;
$RepoData | Add-Member -MemberType NoteProperty -Name 'Name' -Value $entry.Name;
$RepoData | Add-Member -MemberType NoteProperty -Name 'RemoteSource' -Value $RepoContent.Info.RemoteSource;
$RepoData | Add-Member -MemberType NoteProperty -Name 'ComponentName' -Value $repoEntry;
$RepoData | Add-Member -MemberType NoteProperty -Name 'Packages' -Value @();
foreach ($package in $RepoContent.Packages.$repoEntry) {
$ComponentData = New-Object -TypeName PSObject;
$ComponentData | Add-Member -MemberType NoteProperty -Name 'Version' -Value $package.Version;
$ComponentData | Add-Member -MemberType NoteProperty -Name 'Location' -Value $package.Location;
$ComponentData | Add-Member -MemberType NoteProperty -Name 'Snapshot' -Value $package.Snapshot;
if ($Snapshot -And $package.Snapshot -eq $TRUE -And [string]::IsNullOrEmpty($Version)) {
$RepoData.Packages += $ComponentData;
continue;
}
if ($Snapshot -And $package.Snapshot -eq $TRUE -And [string]::IsNullOrEmpty($Version) -eq $FALSE -And [version]$package.Version -eq [version]$Version) {
$RepoData.Packages += $ComponentData;
continue;
}
if ($Release -And [string]::IsNullOrEmpty($Version) -And $package.Snapshot -eq $FALSE) {
$RepoData.Packages += $ComponentData;
continue;
}
if ([string]::IsNullOrEmpty($Version) -eq $FALSE -And $Release -eq $FALSE -And $Snapshot -eq $FALSE -And $package.Snapshot -eq $FALSE) {
$RepoData.Packages += $ComponentData;
continue;
}
}
if ($RepoData.Packages.Count -ne 0) {
$FoundPackage = $TRUE;
}
$SearchList.Repos += $RepoData;
}
}
if ($FoundPackage -eq $FALSE) {
$SearchVersion = 'release';
if ([string]::IsNullOrEmpty($Version) -eq $FALSE) {
$SearchVersion = $Version;
}
if ($Release) {
Write-IcingaConsoleNotice 'The component "{0}" was not found on stable channel with version "{1}"' -Objects $Name, $SearchVersion;
}
if ($Snapshot) {
Write-IcingaConsoleNotice 'The component "{0}" was not found on snapshot channel with version "{1}"' -Objects $Name, $SearchVersion;
}
return;
}
foreach ($repo in $SearchList.Repos) {
if ($repo.Packages.Count -eq 0) {
continue;
}
$Output += $repo.Name;
$Output += '-----------';
$Output += [string]::Format('Source => {0}', $repo.RemoteSource);
$Output += '';
$Output += $repo.ComponentName;
[array]$VersionList = $repo.Packages | Sort-Object { $_.Version } -Descending;
foreach ($componentData in $VersionList) {
$Output += [string]::Format('{0} => {1}', $componentData.Version, $componentData.Location);
}
$Output += '';
}
Write-Host ($Output | Out-String);
}

View file

@ -0,0 +1,56 @@
function Show-Icinga()
{
$IcingaInstallation = Get-IcingaInstallation -Release;
[array]$Output = @( 'Icinga for Windows environment' );
[int]$MaxComponentLength = Get-IcingaMaxTextLength -TextArray $IcingaInstallation.Keys;
[int]$MaxVersionLength = Get-IcingaMaxTextLength -TextArray $IcingaInstallation.Values.CurrentVersion;
[string]$ComponentHeader = Add-IcingaWhiteSpaceToString -Text 'Component' -Length $MaxComponentLength;
[string]$ComponentLine = Add-IcingaWhiteSpaceToString -Text '---' -Length $MaxComponentLength;
$Output += '-----------';
$Output += '';
$Output += 'Installed components on this system';
$Output += '';
$Output += [string]::Format('{0} {1} Available', $ComponentHeader, ((Add-IcingaWhiteSpaceToString -Text 'Version' -Length $MaxVersionLength)));
$Output += [string]::Format('{0} {1} ---', $ComponentLine, ((Add-IcingaWhiteSpaceToString -Text '---' -Length $MaxVersionLength)));
foreach ($component in $IcingaInstallation.Keys) {
$Data = $IcingaInstallation[$component];
$LatestVersion = $Data.LatestVersion;
$CurrentVersion = $Data.CurrentVersion;
if ([string]::IsNullOrEmpty($Data.LockedVersion) -eq $FALSE) {
if ($Data.LockedVersion -eq $Data.CurrentVersion) {
$CurrentVersion = [string]::Format('{0}*', $CurrentVersion);
} else {
$LatestVersion = [string]::Format('{0}*', $Data.LockedVersion);
}
}
[string]$ComponentName = Add-IcingaWhiteSpaceToString -Text $component -Length $MaxComponentLength;
$Output += [string]::Format('{0} {1} {2}', $ComponentName, (Add-IcingaWhiteSpaceToString -Text $CurrentVersion -Length $MaxVersionLength), $LatestVersion);
}
$Output += '';
$Output += 'Available versions flagged with "*" mean that this component is locked to this version';
$IcingaForWindowsService = Get-IcingaForWindowsServiceData;
$IcingaAgentService = Get-IcingaAgentInstallation;
$WindowsInformation = Get-IcingaWindowsInformation Win32_OperatingSystem | Select-Object Version, BuildNumber, Caption;
$Output += '';
$Output += 'Environment configuration';
$Output += '';
$Output += ([string]::Format('PowerShell Root => {0}', (Get-IcingaForWindowsRootPath)));
$Output += ([string]::Format('Icinga for Windows Service Path => {0}', $IcingaForWindowsService.Directory));
$Output += ([string]::Format('Icinga for Windows Service User => {0}', $IcingaForWindowsService.User));
$Output += ([string]::Format('Icinga Agent Path => {0}', $IcingaAgentService.RootDir));
$Output += ([string]::Format('Icinga Agent User => {0}', $IcingaAgentService.User));
$Output += ([string]::Format('PowerShell Version => {0}', $PSVersionTable.PSVersion.ToString()));
$Output += ([string]::Format('Operating System => {0}', $WindowsInformation.Caption));
$Output += ([string]::Format('Operating System Version => {0}', $WindowsInformation.Version));
$Output += '';
$Output += (Show-IcingaRepository);
Write-Output $Output;
}

View file

@ -0,0 +1,32 @@
function Show-IcingaRepository()
{
[hashtable]$Repositories = @{ };
[array]$RepoSummary = @(
'List of configured repositories on this system. The list order matches the apply order.',
''
);
[array]$RepoList = Get-IcingaRepositories;
foreach ($repo in $RepoList) {
$RepoSummary += $repo.Name;
$RepoSummary += '-----------';
[int]$MaxLength = Get-IcingaMaxTextLength -TextArray $repo.Value.PSObject.Properties.Name;
[array]$RepoData = @();
foreach ($repoConfig in $repo.Value.PSObject.Properties) {
$PrintName = Add-IcingaWhiteSpaceToString -Text $repoConfig.Name -Length $MaxLength;
$RepoData += [string]::Format('{0} => {1}', $PrintName, $repoConfig.Value);
}
$RepoSummary += $RepoData | Sort-Object;
$RepoSummary += '';
}
if ($RepoList.Count -eq 0) {
$RepoSummary += 'No repositories configured';
}
Write-Output $RepoSummary;
}

View file

@ -0,0 +1,263 @@
function Sync-IcingaRepository()
{
param (
[string]$Name = $null,
[string]$Path = $null,
[string]$RemotePath = $null,
[string]$Source = $null,
[switch]$UseSCP = $FALSE,
[switch]$Force = $FALSE,
[switch]$ForceTrust = $FALSE
);
if ([string]::IsNullOrEmpty($Name)) {
Write-IcingaConsoleError 'You have to provide a name for the repository';
return;
}
if ($UseSCP -And $null -eq (Get-Command 'scp' -ErrorAction SilentlyContinue) -And $null -eq (Get-Command 'ssh' -ErrorAction SilentlyContinue)) {
Write-IcingaConsoleWarning 'You cannot use SCP on this system, as SCP and/or SSH seem not to be installed';
return;
}
if ($UseSCP -And $Path.Contains(':') -eq $FALSE -And $Path.Contains('@') -eq $FALSE) {
Write-IcingaConsoleWarning 'You have to add host and username to your "-Path" argument. Example: "icinga@icinga.example.com:/var/www/icingarepo/" ';
return;
}
if ([string]::IsNullOrEmpty($Path) -Or (Test-Path $Path) -eq $FALSE -And $UseSCP -eq $FALSE) {
Write-IcingaConsoleWarning 'The provided path "{0}" does not exist and will be created' -Objects $Path;
}
if ([string]::IsNullOrEmpty($RemotePath)) {
Write-IcingaConsoleWarning 'No explicit remote path has been defined. Using local path "{0}" as remote path' -Objects $Path;
$RemotePath = $Path;
}
if ([string]::IsNullOrEmpty($Source)) {
Write-IcingaConsoleError 'You have to specify a source to sync from';
return;
}
$CurrentRepositories = Get-IcingaPowerShellConfig -Path 'Framework.Repository.Repositories';
if ($null -eq $CurrentRepositories) {
$CurrentRepositories = New-Object -TypeName PSObject;
}
if ((Test-IcingaPowerShellConfigItem -ConfigObject $CurrentRepositories -ConfigKey $Name) -And $Force -eq $FALSE) {
Write-IcingaConsoleError 'A repository with the given name "{0}" does already exist. Use "Update-IcingaRepository -Name {1}{0}{1}" to update it.' -Objects $Name, "'";
return;
}
if ((Test-Path $Path) -eq $FALSE -And $UseSCP -eq $FALSE) {
$FolderCreated = New-Item -Path $Path -ItemType Directory -Force -ErrorAction SilentlyContinue;
if ($null -eq $FolderCreated) {
Write-IcingaConsoleError 'Unable to create repository folder at location "{0}". Please verify that you have permissions to write into the location and try again or create the folder manually' -Objects $Path;
return;
}
}
$RepoFile = $null;
$SSHAuth = $null;
$RemovePath = $null;
if (Test-Path $Source) {
$CopySource = Join-Path -Path $Source -ChildPath '\*';
} else {
$CopySource = $Source;
}
if ($UseSCP -eq $FALSE) {
$Path = Join-Path -Path $Path -ChildPath '\';
$RemovePath = Join-Path -Path $Path -ChildPath '\*';
} else {
$SSHIndex = $Path.IndexOf(':');
$SSHAuth = $Path.Substring(0, $SSHIndex);
$Path = $Path.Substring($SSHIndex + 1, $Path.Length - $SSHIndex - 1);
if ($Path[-1] -eq '/') {
$RemovePath = [string]::Format('{0}*', $Path);
} else {
$RemovePath = [string]::Format('{0}/*', $Path);
}
}
# All cloning will be done into a local file first
$TmpDir = New-IcingaTemporaryDirectory;
$RepoFile = (Join-Path -Path $TmpDir -ChildPath 'ifw.repo.json');
[bool]$HasNonRelative = $FALSE;
if (Test-Path $CopySource) { # Sync source is local path
$Success = Copy-ItemSecure -Path $CopySource -Destination $TmpDir -Recurse -Force;
} else { # Sync Source is web path
$ProgressPreference = "SilentlyContinue";
try {
Invoke-WebRequest -USeBasicParsing -Uri $Source -OutFile $RepoFile;
} catch {
try {
Invoke-WebRequest -USeBasicParsing -Uri (Join-WebPath -Path $Source -ChildPath 'ifw.repo.json') -OutFile $RepoFile;
} catch {
Write-IcingaConsoleError 'Unable to download repository file from "{0}". Exception: "{1}"' -Objects $Source, $_.Exception.Message;
$Success = Remove-Item -Path $TmpDir -Recurse -Force;
return;
}
}
$RepoContent = Get-Content -Path $RepoFile -Raw;
$JsonRepo = ConvertFrom-Json -InputObject $RepoContent;
foreach ($component in $JsonRepo.Packages.PSObject.Properties.Name) {
$IfWPackage = $JsonRepo.Packages.$component
foreach ($package in $IfWPackage) {
$DownloadLink = $package.Location;
$TargetLocation = $TmpDir;
if ($package.RelativePath -eq $TRUE) {
$DownloadLink = Join-WebPath -Path $JsonRepo.Info.RemoteSource -ChildPath $package.Location;
$TargetLocation = Join-Path -Path $TmpDir -ChildPath $package.Location;
[void](
New-Item `
-ItemType Directory `
-Path (
$TargetLocation.SubString(
0,
$TargetLocation.LastIndexOf('\')
)
) `
-Force
);
} else {
$HasNonRelative = $TRUE;
$FileName = $package.Location.Replace('/', '\');
$Index = $FileName.LastIndexOf('\');
$FileName = $FileName.SubString($Index, $FileName.Length - $Index);
$TargetLocation = Join-Path -Path $TmpDir -ChildPath $component;
[void](New-Item -ItemType Directory -Path $TargetLocation -Force);
$TargetLocation = Join-Path -Path $TargetLocation -ChildPath $FileName;
}
try {
Write-IcingaConsoleNotice 'Syncing repository component "{0}" as file "{1}" into temp directory' -Objects $component, $package.Location;
Invoke-WebRequest -USeBasicParsing -Uri $DownloadLink -OutFile $TargetLocation;
} catch {
Write-IcingaConsoleError 'Failed to download repository component "{0}". Exception: "{1}"' -Objects $DownloadLink, $_.Exception.Message;
continue;
}
}
}
}
[string]$CopySource = [string]::Format('{0}\*', $TmpDir);
if ((Test-Path $RepoFile) -eq $FALSE) {
Write-IcingaConsoleError 'The files from this repository were cloned but no repository file was found. Deleting temporary files';
$Success = Remove-Item -Path $TmpDir -Recurse -Force;
return;
}
$RepoContent = Get-Content -Path $RepoFile -Raw;
$JsonRepo = ConvertFrom-Json -InputObject $RepoContent;
if ($null -eq $JsonRepo) {
Write-IcingaConsoleError 'The repository file was found but it is either damaged or empty. Deleting temporary files';
$Success = Remove-Item -Path $TmpDir -Recurse -Force;
return;
}
$EnableRepo = $TRUE;
if ($ForceTrust -eq $FALSE -And $UseSCP -eq $FALSE) {
if ($null -eq $JsonRepo.Info.RepoHash -Or [string]::IsNullOrEmpty($JsonRepo.Info.RepoHash)) {
Write-IcingaConsoleWarning 'The cloned repository file hash cannot be verified, as it is not present inside the repository file. The repository will be added, but disabled for security reasons. Review the content first and ensure you trust the source before enabling it.';
$EnableRepo = $FALSE;
} elseif ($JsonRepo.Info.RepoHash -ne (Get-IcingaRepositoryHash -Path $TmpDir)) {
$Success = Remove-Item -Path $TmpDir -Recurse -Force;
Write-IcingaConsoleError 'The repository hash for the cloned repository is not matching the file hash of the files inside. Removing repository data';
return;
}
}
if ($HasNonRelative) {
[void](New-IcingaRepositoryFile -Path $TmpDir -RemotePath $RemotePath);
$RepoContent = Get-Content -Path $RepoFile -Raw;
$JsonRepo = ConvertFrom-Json -InputObject $RepoContent;
Start-Sleep -Seconds 2;
}
$JsonRepo.Info.RepoHash = Get-IcingaRepositoryHash -Path $TmpDir;
$JsonRepo.Info.LocalSource = $Path;
$JsonRepo.Info.RemoteSource = $RemotePath;
$JsonRepo.Info.Updated = ((Get-Date).ToUniversalTime().ToString('yyyy\/MM\/dd HH:mm:ss'));
Set-Content -Path $RepoFile -Value (ConvertTo-Json -InputObject $JsonRepo -Depth 100);
if ($UseSCP -eq $FALSE) { # Windows target
$Success = Remove-Item -Path $RemovePath -Recurse -Force;
$Success = Copy-ItemSecure -Path $CopySource -Destination $Path -Recurse -Force;
if ($Success -eq $FALSE) {
Write-IcingaConsoleError 'Unable to sync repository from location "{0}" to destination "{1}". Please verify that you have permissions to write into the location and try again or create the folder manually' -Objects $TmpDir, $Path;
$Success = Remove-Item -Path $TmpDir -Recurse -Force;
return;
}
} else { # Linux target
Write-IcingaConsoleNotice 'Creating directory over SSH for host and user "{0}" and path "{1}"' -Objects $SSHAuth, $Path;
$Result = Start-IcingaProcess -Executable 'ssh' -Arguments ([string]::Format('{0} mkdir -p "{1}"', $SSHAuth, $Path));
if ($Result.ExitCode -ne 0) {
# TODO: Add link to setup docs
Write-IcingaConsoleError 'SSH Error on directory creation: {0}' -Objects $Result.Error;
$Success = Remove-Item -Path $TmpDir -Recurse -Force;
return;
}
Write-IcingaConsoleNotice 'Removing old repository files from "{0}"' -Objects $Path;
$Result = Start-IcingaProcess -Executable 'ssh' -Arguments ([string]::Format('{0} rm -Rf "{1}"', $SSHAuth, $RemovePath));
if ($Result.ExitCode -ne 0) {
Write-IcingaConsoleError 'SSH Error on removing old repository data: {0}' -Objects $Result.Error;
$Success = Remove-Item -Path $TmpDir -Recurse -Force;
return;
}
Write-IcingaConsoleNotice 'Syncing new repository files to "{0}"' -Objects $Path;
$Result = Start-IcingaProcess -Executable 'scp' -Arguments ([string]::Format('-r "{0}" "{1}:{2}"', $CopySource, $SSHAuth, $Path));
if ($Result.ExitCode -ne 0) {
Write-IcingaConsoleError 'SCP Error while copying repository files: {0}' -Objects $Result.Error;
$Success = Remove-Item -Path $TmpDir -Recurse -Force;
return;
}
}
$Success = Remove-Item -Path $TmpDir -Recurse -Force;
if ((Test-IcingaPowerShellConfigItem -ConfigObject $CurrentRepositories -ConfigKey $Name) -And $Force -eq $TRUE) {
$CurrentRepositories.$Name.Enabled = $EnableRepo;
Set-IcingaPowerShellConfig -Path 'Framework.Repository.Repositories' -Value $CurrentRepositories;
Write-IcingaConsoleNotice 'Re-syncing of repository "{0}" was successful' -Objects $Name;
return;
}
Write-IcingaConsoleNotice 'The repository was synced successfully. Use "Update-IcingaRepository" to sync possible changes from the source repository.';
[array]$RepoCount = $CurrentRepositories.PSObject.Properties.Count;
$CurrentRepositories | Add-Member -MemberType NoteProperty -Name $Name -Value (New-Object -TypeName PSObject);
$CurrentRepositories.$Name | Add-Member -MemberType NoteProperty -Name 'LocalPath' -Value $Path;
$CurrentRepositories.$Name | Add-Member -MemberType NoteProperty -Name 'RemotePath' -Value $RemotePath;
$CurrentRepositories.$Name | Add-Member -MemberType NoteProperty -Name 'CloneSource' -Value $Source;
$CurrentRepositories.$Name | Add-Member -MemberType NoteProperty -Name 'UseSCP' -Value ([bool]$UseSCP);
$CurrentRepositories.$Name | Add-Member -MemberType NoteProperty -Name 'Order' -Value $RepoCount.Count;
$CurrentRepositories.$Name | Add-Member -MemberType NoteProperty -Name 'Enabled' -Value $EnableRepo;
Set-IcingaPowerShellConfig -Path 'Framework.Repository.Repositories' -Value $CurrentRepositories;
return;
}

View file

@ -0,0 +1,42 @@
function Uninstall-IcingaComponent()
{
param (
[string]$Name = '',
[switch]$RemovePackageFiles = $FALSE
);
if ([string]::IsNullOrEmpty($Name)) {
Write-IcingaConsoleError 'You have to specify a component name to uninstall';
return $FALSE;
}
if ($Name.ToLower() -eq 'agent') {
return Uninstall-IcingaAgent -RemoveDataFolder:$RemovePackageFiles;
}
if ($Name.ToLower() -eq 'service') {
return; Uninstall-IcingaForWindowsService -RemoveFiles:$RemovePackageFiles;
}
$ModuleBase = Get-IcingaForWindowsRootPath;
$UninstallComponent = [string]::Format('icinga-powershell-{0}', $Name);
$UninstallPath = Join-Path -Path $ModuleBase -ChildPath $UninstallComponent;
if ((Test-Path $UninstallPath) -eq $FALSE) {
Write-IcingaConsoleNotice -Message 'The Icinga for Windows component "{0}" at "{1}" could not ne found.' -Objects $UninstallComponent, $UninstallPath;
return $FALSE;
}
Write-IcingaConsoleNotice -Message 'Uninstalling Icinga for Windows component "{0}" from "{1}"' -Objects $UninstallComponent, $UninstallPath;
if (Remove-ItemSecure -Path $UninstallPath -Recurse -Force) {
Write-IcingaConsoleNotice -Message 'Successfully removed Icinga for Windows component "{0}" from "{1}"' -Objects $UninstallComponent, $UninstallPath;
if ($UninstallComponent -ne 'icinga-powershell-framework') {
Remove-Module $UninstallComponent -Force -ErrorAction SilentlyContinue;
}
return $TRUE;
} else {
Write-IcingaConsoleError -Message 'Unable to uninstall Icinga for Windows component "{0}" from "{1}"' -Objects $UninstallComponent, $UninstallPath;
}
return $FALSE;
}

View file

@ -0,0 +1,25 @@
function Unlock-IcingaComponent()
{
param (
[string]$Name = $null
);
if ([string]::IsNullOrEmpty($Name)) {
Write-IcingaConsoleError 'You have to specify the component to unlock';
return;
}
$LockedComponents = Get-IcingaPowerShellConfig -Path 'Framework.Repository.ComponentLock';
if ($null -eq $LockedComponents) {
Write-IcingaConsoleNotice 'You have currently no components which are locked configured';
return;
}
if (Test-IcingaPowerShellConfigItem -ConfigObject $LockedComponents -ConfigKey $Name) {
Remove-IcingaPowerShellConfig -Path ([string]::Format('Framework.Repository.ComponentLock.{0}', $Name));
Write-IcingaConsoleNotice 'Unlocking of component "{0}" was successful.' -Objects $Name;
} else {
Write-IcingaConsoleNotice 'The component "{0}" is not locked on this system' -Objects $Name;
}
}

View file

@ -0,0 +1,44 @@
function Update-Icinga()
{
param (
[string]$Name = $null,
[switch]$Release = $FALSE,
[switch]$Snapshot = $FALSE,
[switch]$Confirm = $FALSE,
[switch]$Force = $FALSE
);
if ($Release -eq $FALSE -And $Snapshot -eq $FALSE) {
$Release = $TRUE;
}
$CurrentInstallation = Get-IcingaInstallation -Release:$Release -Snapshot:$Snapshot;
foreach ($entry in $CurrentInstallation.Keys) {
$Component = $CurrentInstallation[$entry];
if ([string]::IsNullOrEmpty($Name) -eq $FALSE -And $Name -ne $entry) {
continue;
}
$NewVersion = $Component.LatestVersion;
if ([string]::IsNullOrEmpty($NewVersion)) {
Write-IcingaConsoleNotice 'No update package found for component "{0}"' -Objects $entry;
continue;
}
$LockedVersion = Get-IcingaComponentLock -Name $entry;
if ($null -ne $LockedVersion) {
$NewVersion = $LockedVersion;
}
if ([Version]$NewVersion -le [Version]$Component.CurrentVersion -And $Force -eq $FALSE) {
Write-IcingaConsoleNotice 'The installed version "{0}" of component "{1}" is identical or lower than the new version "{2}". Use "-Force" to install anyway' -Objects $Component.CurrentVersion, $entry, $NewVersion;
continue;
}
Install-IcingaComponent -Name $entry -Version $NewVersion -Release:$Release -Snapshot:$Snapshot -Confirm:$Confirm -Force:$Force
}
}

View file

@ -0,0 +1,98 @@
function Update-IcingaRepository()
{
param (
[string]$Name = $null,
[string]$Path = $null,
[string]$RemotePath = $null,
[switch]$CreateNew = $FALSE,
[switch]$ForceTrust = $FALSE
);
$CurrentRepositories = Get-IcingaPowerShellConfig -Path 'Framework.Repository.Repositories';
[array]$ConfigCount = $CurrentRepositories.PSObject.Properties.Count;
if (($null -eq $CurrentRepositories -Or $ConfigCount.Count -eq 0) -And $CreateNew -eq $FALSE) {
Write-IcingaConsoleNotice 'There are no repositories configured yet. You can create a custom repository with "New-IcingaRepository" or clone an existing one with "Sync-IcingaForWindowsRepository"';
return;
}
if ([string]::IsNullOrEmpty($Name) -eq $FALSE) {
if ((Test-IcingaPowerShellConfigItem -ConfigObject $CurrentRepositories -ConfigKey $Name) -eq $FALSE -And $CreateNew -eq $FALSE) {
Write-IcingaConsoleError 'A repository with the given name "{0}" does not exist. Use "New-IcingaRepository" or "Sync-IcingaForWindowsRepository" to create a new one.' -Objects $Name;
return;
}
}
foreach ($definedRepo in $CurrentRepositories.PSObject.Properties) {
if ([string]::IsNullOrEmpty($Name) -eq $FALSE -And $definedRepo.Name.ToLower() -ne $Name.ToLower()) {
continue;
}
if ($definedRepo.Value.Enabled -eq $FALSE) {
Write-IcingaConsoleNotice 'Skipping disabled repository "{0}"' -Objects $definedRepo.Name;
continue;
}
if ([string]::IsNullOrEmpty($definedRepo.Value.CloneSource) -eq $FALSE) {
continue;
}
if ([string]::IsNullOrEmpty($definedRepo.Value.LocalPath)) {
continue;
}
if ((Test-Path $definedRepo.Value.LocalPath) -eq $FALSE) {
if ($CreateNew) {
return $null;
}
continue;
}
$Path = Join-Path -Path $definedRepo.Value.LocalPath -ChildPath '\';
if ($CreateNew -eq $FALSE) {
Write-IcingaConsoleNotice 'Updating Icinga for Windows repository "{0}"' -Objects $definedRepo.Name;
}
$IcingaRepository = New-IcingaRepositoryFile -Path $Path -RemotePath $RemotePath;
if ($CreateNew) {
return $IcingaRepository;
}
}
# Always sync repositories at the end, in case we updated a local repository and cloned it to somewhere else
foreach ($definedRepo in $CurrentRepositories.PSObject.Properties) {
if ([string]::IsNullOrEmpty($Name) -eq $FALSE -And $definedRepo.Name.ToLower() -ne $Name.ToLower()) {
continue;
}
if ($definedRepo.Value.Enabled -eq $FALSE) {
continue;
}
if ([string]::IsNullOrEmpty($definedRepo.Value.LocalPath)) {
continue;
}
Write-IcingaConsoleNotice 'Syncing repository "{0}"' -Objects $definedRepo.Name;
if ([string]::IsNullOrEmpty($definedRepo.Value.CloneSource) -eq $FALSE) {
Sync-IcingaRepository `
-Name $definedRepo.Name `
-Path $definedRepo.Value.LocalPath `
-RemotePath $definedRepo.Value.RemotePath `
-Source $definedRepo.Value.CloneSource `
-UseSCP:$definedRepo.Value.UseSCP `
-Force `
-ForceTrust:$ForceTrust;
return;
}
}
Write-IcingaConsoleNotice 'All Icinga for Windows repositories were successfully updated';
}

View file

@ -0,0 +1,16 @@
function Add-IcingaWhiteSpaceToString()
{
param (
[string]$Text = '',
[int]$Length = 0
);
[int]$LengthOffset = $Length - $Text.Length;
while ($LengthOffset -gt 0) {
$Text += ' ';
$LengthOffset -= 1;
}
return $Text;
}

View file

@ -0,0 +1,16 @@
function Get-IcingaMaxTextLength()
{
param (
[array]$TextArray = ''
);
[int]$MaxLength = 0;
foreach ($text in $TextArray) {
if ($MaxLength -lt $text.Length) {
$MaxLength = $text.Length;
}
}
return $MaxLength;
}

View file

@ -11,7 +11,7 @@ function Get-IcingaServices()
if ($Service.Count -eq 0) {
$ServiceWmiInfo = Get-IcingaWindowsInformation Win32_Service;
} else {
$ServiceWmiInfo = Get-IcingaWindowsInformation Win32_Service | Where-Object { $Service -Contains $_.Name } | Select-Object StartName, Name, ExitCode, StartMode;
$ServiceWmiInfo = Get-IcingaWindowsInformation Win32_Service | Where-Object { $Service -Contains $_.Name } | Select-Object StartName, Name, ExitCode, StartMode, PathName;
}
if ($null -eq $ServiceInformation) {
@ -26,6 +26,7 @@ function Get-IcingaServices()
[array]$DependingServices = $null;
$ServiceExitCode = 0;
[string]$ServiceUser = '';
[string]$ServicePath = '';
[int]$StartModeId = 5;
[string]$StartMode = 'Unknown';
@ -36,6 +37,7 @@ function Get-IcingaServices()
foreach ($wmiService in $ServiceWmiInfo) {
if ($wmiService.Name -eq $service.ServiceName) {
$ServiceUser = $wmiService.StartName;
$ServicePath = $wmiService.PathName;
$ServiceExitCode = $wmiService.ExitCode;
if ([string]::IsNullOrEmpty($wmiService.StartMode) -eq $FALSE) {
$StartModeId = ([int]$IcingaEnums.ServiceWmiStartupType[$wmiService.StartMode]);
@ -90,6 +92,7 @@ function Get-IcingaServices()
'value' = $StartMode;
};
'ServiceUser' = $ServiceUser;
'ServicePath' = $ServicePath;
'ExitCode' = $ServiceExitCode;
}
}