DSCResources/OctopusServer/OctopusServer.psm1

function Get-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Collections.Hashtable])]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]
        $ServerName
    )

    
    $returnValue = @{
        ServerName = $ServerName
    }

    $installedApps = Get-InstalledApp
    $octopusServer = $installedApps | Where-Object {$_.DisplayName -like "Octopus Deploy Server"} | Select-Object -First 1
    if($octopusServer){
        $returnValue.Ensure = "Present"
    }
    else{
        $returnValue.Ensure = "Absent"
    }
    $returnValue
}


function Set-TargetResource
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]
        $ServerName,

        [System.String]
        $Port,

        [System.Management.Automation.PSCredential]
        $Credentials,

        [ValidateSet("Present","Absent")]
        [System.String]
        $Ensure
    )

    $InstallPath = "C:\Program Files\Octopus Deploy\Octopus"
    $Server = $InstallPath + "\Octopus.Server.exe"

    if($Ensure -eq "Present"){
        Install-OctopusServer
        Set-OctopusConfiguration -Server $Server -ServerName $ServerName -Port $Port -Credentials $Credentials
    }
    else{
        Remove-OctopusConfiguration -Server $Server
        Uninstall-OctopusServer
    }
    #Include this line if the resource requires a system reboot.
    #$global:DSCMachineStatus = 1
}


function Test-TargetResource
{
    [CmdletBinding()]
    [OutputType([System.Boolean])]
    param
    (
        [parameter(Mandatory = $true)]
        [System.String]
        $ServerName,

        [System.String]
        $Port,

        [System.Management.Automation.PSCredential]
        $Credentials,

        [ValidateSet("Present","Absent")]
        [System.String]
        $Ensure
    )
    
    $result = [System.Boolean]
    $installedApps = Get-InstalledApp
    $octopusServer = $installedApps | Where-Object {$_.DisplayName -like "Octopus Deploy Server"} | Select-Object -First 1
    if($octopusServer){
        if($Ensure -eq "Present"){
            $result = $true
        }
        else{
            $result = $false
        }
    }
    else{
        if($Ensure -eq "Present"){
            $result = $false
        }
        else{
            $result = $true
        }
    }
    $result
}

#region supportingfunctions
function Get-InstalledApp {
param()
    begin{}
    process{
        $apps = Get-ItemProperty HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\* |
                Select-Object DisplayName, 
                DisplayVersion, 
                UnInstallString,
                InstallDate,
                @{Name="VERSION_MAJOR";Expression={($_.DisplayVersion.Split("."))[0]}},
                @{Name="VERSION_MINOR";Expression={($_.DisplayVersion.Split("."))[1]}},
                @{Name="VERSION_REVISION";Expression={($_.DisplayVersion.Split("."))[2]}},
                @{Name="VERSION_BUILD";Expression={($_.DisplayVersion.Split("."))[3]}}, 
                @{Name="GUID";Expression={$_.PSChildName}},
                @{Name="AppArchitecture";Expression={"86"}}
        if((Get-CimInstance Win32_Processor).AddressWidth -eq 64){
            $apps += Get-ItemProperty HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\* | 
                     Select-Object DisplayName,
                     DisplayVersion, 
                     UnInstallString,
                     InstallDate, 
                     @{Name="VERSION_MAJOR";Expression={($_.DisplayVersion.Split("."))[0]}},
                     @{Name="VERSION_MINOR";Expression={($_.DisplayVersion.Split("."))[1]}},
                     @{Name="VERSION_REVISION";Expression={($_.DisplayVersion.Split("."))[2]}},
                     @{Name="VERSION_BUILD";Expression={($_.DisplayVersion.Split("."))[3]}}, 
                     @{Name="GUID";Expression={$_.PSChildName}}, 
                     @{Name="AppArchitecture";Expression={"64"}}
        }

        $apps | Where-Object { !([string]::IsNullOrEmpty($_.DisplayName)) }
    }
    end{}
}

function Install-OctopusServer{
    $OctopusMsi = "C:\Softwares\Chocolatey\Octopus.3.3.27-x64.msi"
    $InstallPath = "C:\Program Files\Octopus Deploy\Octopus"
    $LogFile = "Octopus-Server-Install-Log.txt"

    Write-Verbose "Installing octopus deploy to location $InstallPath"
    Write-Verbose "The installation logs can be found from the file $LogFile"
    $commandArgs = "/i $OctopusMsi /qn /norestart /log $LogFile"

    Write-Debug "Starting installation"
    $process = Start-Process "msiexec" $commandArgs -Wait -Verb RunAs -PassThru

    if($process.ExitCode -eq 0){
        Write-Verbose "Successfully completed installation of the octopus server"
    }
    else {
        Write-Warning "There was a different error code than expected"
        Write-Warning "The setup will continue"
    }
}


function Uninstall-OctopusServer{
    $installedApps = Get-InstalledApp
    $octopusServer = $installedApps | Where-Object {$_.DisplayName -like "Octopus Deploy Server"} | Select-Object -First 1
    if ($octopusServer) {
        Write-Verbose "Uninstalling octopus server"
        Start-Process -FilePath cmd.exe -ArgumentList "/c $($octopusServer).UninstallString /S /qn /norestart"  -wait -NoNewWindow 
    } 
}

function Set-OctopusConfiguration{
    param(
        $Server, $ServerName, $Port, $Credentials
    )

    Write-Verbose "Starting server configuration"
    Write-Debug "Creating a new instance of octopus server"

    $ConfigPath = "C:\Octopus\OctopusServer.config"
    Write-Verbose "The configuration file will be created at location $ConfigPath"
    $processArguments = @('create-instance', '--instance="OctopusServer"', "--config=`"$ConfigPath`"")
    & $Server $processArguments

    Write-Verbose "Creating a new instance of octopus server"
    $processArguments = @("configure", `
                                "--instance=`"OctopusServer`"", `
                                "--home=`"C:\Octopus`"", `
                                "--storageConnectionString=`"Data Source=$ServerName\SQLEXPRESS;Initial Catalog=Octopus;Integrated Security=True`"", `
                                "--upgradeCheck=`"True`"", `
                                "--upgradeCheckWithStatistics=`"False`"", `
                                "--webAuthenticationMode=`"UsernamePassword`"", `
                                "--webForceSSL=`"False`"", `
                                "--webListenPrefixes=`"http://$($ServerName):$($Port)/`"", `
                                "--commsListenPort=`"10943`"", `
                                "--serverNodeName=`"$ServerName`"")          
    & $Server $processArguments

    Write-Verbose "Creating database"
    $processArguments = @("database", `
                                "--instance=`"OctopusServer`"", `
                                "--create", `
                                "--grant=`"NT AUTHORITY\SYSTEM`"")    
    & $Server $processArguments

    Write-Verbose "Stopping existing service"
    $processArguments = @("service", `
                                "--instance=`"OctopusServer`"", `
                                "--stop")    
    & $Server $processArguments

    Write-Verbose "Registering username and password"
    $admin = $Credentials.UserName
    $password = $Credentials.GetNetworkCredential().Password
    $processArguments = @("admin", `
                                "--instance=`"OctopusServer`"", `
                                "--username=`"$admin`"", `
                                "--password=`"$password`"", `
                                "--wait=`"5000`"")    
    & $Server $processArguments


    Write-Verbose "Processing licensekey"
    $processArguments = @("license", `
                                "--instance=`"OctopusServer`"", `
                                "--licenseBase64=`"[YOUR_LICENSE_HERE]`"", `
                                "--wait=`"5000`"")    
    & $Server $processArguments

    Write-Verbose "Restart octopus service"
    $processArguments = @("service", `
                                "--instance=`"OctopusServer`"", `
                                "--install", `
                                "--reconfigure", `
                                "--start")    
    & $Server $processArguments

    Write-Verbose "Successfully completed octopus server configuration"

}

function Remove-OctopusConfiguration{
    param($Server)
    Write-Verbose "Removing server configuration"

    Write-Debug "Stopping octopus server"
    $processArguments = @("service", `
                                "--instance=`"OctopusServer`"", `
                                "--stop", `
                                "--uninstall")    
    & $Server $processArguments
    Write-Debug "Removing octopus instance"

    $processArguments = @("delete-instance", `
                                "--instance=`"OctopusServer`"")  
}
#endregion

Export-ModuleMember -Function *-TargetResource