OctopusMachines.psm1

#Install-Module PowershellOctopusClientPS
Import-Module PowershellOctopusClientPS
(Get-Module -ListAvailable PowershellOctopusClientPS).ModuleBase

try
{
    $octoclientpath = Join-Path -Path (Get-Module -ListAvailable PowershellOctopusClientPS).ModuleBase -ChildPath "lib\Octopus.Client.dll"
    $newtonsoftPath = Join-Path -Path (Get-Module -ListAvailable PowershellOctopusClientPS).ModuleBase -ChildPath "lib\Newtonsoft.Json.dll"
    Add-Type -Path $newtonsoftPath
    Add-Type -Path $octoclientpath
}
catch [System.Reflection.ReflectionTypeLoadException]
{    #system.attonations always throws
    #Write-Host "Message: $($_.Exception.Message)"
    #Write-Host "StackTrace: $($_.Exception.StackTrace)"
    #Write-Host "LoaderExceptions: $($_.Exception.LoaderExceptions)"
}
<#
    .SYNOPSIS
    return a setup client
#>

function LoadOctopusClientAndDependancies {
[OutputType([Octopus.Client.OctopusClient])]
    Param(
        [parameter(Mandatory=$true)][String] $url,
        [parameter(Mandatory=$true)][String] $apiKey
    )
    
    $client = [Octopus.Client.OctopusClient]::new([Octopus.Client.OctopusServerEndpoint]::new($url, $apiKey))
    $client
}

function CreateCloudRegion {
    Param(
        [parameter(Mandatory=$true)] [String]    $octopusURL,
        [parameter(Mandatory=$true)] [String]    $octopusAPIKey,
        [parameter(Mandatory=$true)] [String]    $Name,
        [parameter(Mandatory=$false)][String]    $Enviroment,
        [parameter(Mandatory=$false)][String]    $Space = '',
        [parameter(Mandatory=$false)][String]   $WorkerPool = '',
        [parameter(Mandatory=$false)][String[]] $Roles,
        [parameter(Mandatory=$false)][String[]] $Tenants,
        [parameter(Mandatory=$false)][String[]] $TenantTags,
        [parameter(Mandatory=$false)][switch]    $WhatIf
    )
    $client = LoadOctopusClientAndDependancies -url $octopusURL -apiKey $octopusAPIKey   
    $repository = $client.ForSystem()
    $spaces = $null
    if([string]::IsNullOrEmpty($Space)) {        
        $spaces = $repository.Spaces.GetAll()        
    }else{
        $spaces = $repository.Spaces.FindByName($Space)        
    }
    $spaces | foreach {        
        try {
            $currSpace = $_
            write-output "CreateCloudRegion -> Creating cloud region $Name for enviroment $Enviroment in space $($currSpace.Name)."
            $repositoryForSpace = $client.ForSpace($currSpace)
            $enviromentResource = $repositoryForSpace.Environments.FindByName($Enviroment)
            $endpoint = [Octopus.Client.Model.Endpoints.CloudRegionEndpointResource]::new()            

            if(-not([String]::IsNullOrEmpty($WorkerPool))) {
                $wpoolResource = $repositoryForSpace.WorkerPools.FindByName($WorkerPool)
                $endpoint.DefaultWorkerPoolId = $wpoolResource.Id
            }
            $newMachine = [Octopus.Client.Model.MachineResource]::new()
            $newMachine.Name = $Name
            $newMachine.Endpoint = $endpoint                
            $newMachine.TenantedDeploymentParticipation = [Octopus.Client.Model.TenantedDeploymentMode]::TenantedOrUntenanted
            $newMachine.AddOrUpdateEnvironments($enviromentResource)

            if(-not($Roles -eq $null)) {
                $Roles | foreach {
                    $newMachine.AddOrUpdateRoles($_)
                }
            }
            if(-not($Tenants -eq $null)) {
                $Tenants | foreach {         
                    $newMachine.AddOrUpdateTenants($_)                    
                }
            }

            $tenantTagResources = @()
            if(-not($TenantTags -eq $null)){
                $TenantTags | foreach {
                    $item = $_.split("/")            
                    $repositoryForSpace.TagSets.FindByName($item[0]) | foreach {
                        $_.Tags | foreach{
                            if($_.Name -eq $item[1]){               
                                $tenantTagResources += $_
                            }
                        }
                    }
                }
            }
            $newMachine.AddOrUpdateTenantTags($tenantTagResources)
            write-output "Creating new cloud region target"
            $newMachine
            if($WhatIf -eq $false) {
                $repositoryForSpace.Machines.Create($newMachine)
                Write-Output "CreateCloudRegion -> Added machine for cloud region $Name in space $($currSpace.Name)."
            }
        }catch {
            Write-Error "CreateCloudRegion -> $($_)."
        }
    }
}

function CreateWorkerPool {
    Param(
        [parameter(Mandatory=$true)] [String] $octopusURL,
        [parameter(Mandatory=$true)] [String] $octopusAPIKey,
        [parameter(Mandatory=$true)] [String] $Name,        
        [parameter(Mandatory=$true)] [String] $Enviroment,
        [parameter(Mandatory=$false)][String] $Space = ''
    )

    $client = LoadOctopusClientAndDependancies -url $octopusURL -apiKey $octopusAPIKey   
    $repository = $client.ForSystem()
    $spaces = $null

    if([string]::IsNullOrEmpty($Space)) {        
        $spaces = $repository.Spaces.GetAll()        
    }else{
        $spaces = $repository.Spaces.FindByName($Space)        
    }
    
    $spaces | foreach {
        $currSpace = $_
        $repositoryForSpace = $client.ForSpace($currSpace)
        $newWorkerPool = [Octopus.Client.Model.WorkerPoolResource]::new()
        $newWorkerPool.Name = $Name
        $newWorkerPool.IsDefault = $false
        $newWorkerPool.Description = "$Enviroment enviroment worker pool"
        try{
            $repositoryForSpace.WorkerPools.Create($newWorkerPool)
            write-output "CreateWorkerPool -> Added worker pool $Name to space $($currSpace.Name)"
        }catch {
            Write-Error "CreateWorkerPool -> $($_)"
        }
    }
}

function RemoveAllTenantMachines {
    Param(
        [parameter(Mandatory=$true)] [String] $octopusURL,
        [parameter(Mandatory=$true)] [String] $octopusAPIKey,
        [parameter(Mandatory=$true)] [String] $tenantName,        
        [parameter(Mandatory=$true)] [String] $Enviroment,
        [parameter(Mandatory=$true)] [String] $Space
    )

    $client = LoadOctopusClientAndDependancies -url $octopusURL -apiKey $octopusAPIKey   
    $repository = $client.ForSystem()
    $spaces = $null
    if([string]::IsNullOrEmpty($Space)) {        
        $spaces = $repository.Spaces.GetAll()        
    }else{
        $spaces = $repository.Spaces.FindByName($Space)        
    }

    $spaces | foreach {        
        try {
            $currSpace = $_        
            $repositoryForSpace = $client.ForSpace($currSpace)
            $theEnviromentResource = $repositoryForSpace.Environments.FindByName($Enviroment)
            $tenant = $repositoryForSpace.Tenants.FindByName($tenantName)    
            if($tenant) {
                $machines = $repositoryForSpace.Machines.FindMany({ param($x) $x.TenantIds -contains $tenant.Id -and $x.EnvironmentIds -contains $theEnviromentResource.Id });                                

                if($machines) {
                    $machines | foreach {
                        $currMachine = $_
                        write-output "Removing $($currMachine.Name)."
                        $repositoryForSpace.Machines.Delete($currMachine)
                    }
                }
            }
        }catch {
            Write-Error "RemoveTenantMachines for $tenantName in space $($currSpace.Name) -> $($_)."
        }
    
    }
}