UniversalAutomation.psm1

Import-Module "$PSScriptRoot\UniversalAutomation.Cmdlets.dll"
[UniversalAutomation.AssemblyResolver]::Bind()

function Start-UAServer  {
    param(
        [Parameter()]
        [string]$Port = 10000,
        [Parameter()]
        [string]$ConnectionString = "$Env:LOCALAPPDATA\UniversalAutomation\database.db",
        [Parameter()]
        [string]$RepositoryPath = "$Env:LOCALAPPDATA\UniversalAutomation\Repository",
        [Parameter()]
        [string]$GitRemote,
        [Parameter()]
        [PSCredential]$GitRemoteCredential,
        [Parameter()]
        [string]$JwtSigningKey = "UniversalAutomationSigningKey",
        [Parameter()]
        [string]$JwtAudience = "UniversalAutomation",
        [Parameter()]
        [string]$JwtIssuer = "Ironman Software",
        [Parameter()]
        [string]$LocalComputerName = "localhost",
        # [Parameter()]
        # [string]$Certificate,
        [Parameter()]
        [string]$CertificateFile,
        [Parameter()]
        [SecureString]$CertificatePassword,
        [Parameter()]
        [Switch]$InProcess,
        [Parameter()]
        [Switch]$LocalOnly,
        [Parameter()]
        [string]$ApiUrl
    )

    if ($null -ne [UniversalAutomation.UAServer]::Instance)
    {
        throw "Universal Automation is already running"
    }

    $Process = Get-Process -Id $Pid
    $HostProcess = $Process.MainModule.FileName

    if ($HostProcess.EndsWith('powershell_ise.exe', 'OrdinalIgnoreCase'))
    {
        $HostProcess = 'powershell.exe'
    }

    $Env:UARepositoryPath = $RepositoryPath

    if ($GitRemote)
    {
        $Env:GitRemote = $GitRemote
    }

    if ($GitRemoteCredential)
    {
        $Env:GitRemoteUserName = $GitRemoteCredential.UserName
        $Env:GitRemotePassword = $GitRemoteCredential.GetNetworkCredential().Password
    }

    $Env:UAJWTSigningKey = $JwtSigningKey
    $Env:UAJWTAudience = $JwtAudience
    $Env:UAJWTIssuer = $JwtIssuer

    $Env:UACertificate = $Certificate
    $Env:UACertificateFile = $CertificateFile

    if ($CertificatePassword)
    {
        $s = New-Object PSCredential -ArgumentList "test", $CertificatePassword
        $Env:UACertificatePassword = $s.GetNetworkCredential().Password
    }

    $AliveKey = New-Guid

    $StartUpScript = {
        try { 
            [System.Reflection.Assembly]::LoadFrom('$PSScriptRoot/UniversalAutomation.dll') | Out-Null;
            [System.Reflection.Assembly]::LoadFrom('$PSScriptRoot/UniversalAutomation.Common.dll') | Out-Null;
            [UniversalAutomation.AssemblyResolver]::Bind();
    
            if ($null -eq ([UniversalAutomation.PersistenceService]::Configuration))
            {
                Import-Module '$PSScriptRoot/UniversalAutomation.LiteDB.psd1';
                Use-UALiteDB -ConnectionString '$ConnectionString';
            }

            $Settings = [UniversalAutomation.AgentSettings]::new();
            $Settings.Port = $Port;
            $Settings.AliveKey = '$AliveKey';
            $Settings.LocalOnly = $LocalOnly;
            $Settings.ApiUrl = '$ApiUrl';
    
            [UniversalAutomation.EntryPoint]::Start($Settings); 
        } catch { 
            $_.Exception.Message;
            $_.Exception.InnerException.StackTrace;
        }
    }

    $Script = $StartUpScript.ToString()
    $Script = $Script.Replace('$PSScriptRoot', $PSScriptRoot);
    $Script = $Script.Replace('$Port', $Port);
    $Script = $Script.Replace('$AliveKey', $AliveKey);
    $Script = $Script.Replace('$ConnectionString', $ConnectionString);
    $Script = $Script.Replace('$LocalOnly', "`$$($LocalOnly.IsPresent)");
    $Script = $Script.Replace('$ApiUrl', $ApiUrl);

    if ($InProcess)
    {
        [ScriptBlock]::Create($Script).Invoke()
    }
    else 
    {
        $Script = $Script.ToString().Replace([Environment]::NewLine, '');
        [UniversalAutomation.UAServer]::Instance = Start-Process -FilePath $HostProcess -ArgumentList "-NoExit -NoProfile -Command `"& {$Script}`"" -PassThru 
    }

    $Retries = 0

    if ([string]::IsNullOrEmpty($ApiUrl)) 
    {
        $ApiUrl = "http://$LocalComputerName"+":"+"$port"
    }

    while($Retries -le 100)
    {
        try 
        {
            (Invoke-WebRequest ("$ApiUrl/api/v1/alive") -Headers @{ AliveKey = $AliveKey } -UseBasicParsing).Content
            break
        }
        catch { }
        Start-Sleep -Milliseconds 100
        $Retries++
    }

    if ($Retries -eq 100)
    {
        throw "Failed to start Universal Automation server"
    }
}

function Debug-UAJob
{
    param(
        [Parameter(ValueFromPipeline = $true, Mandatory)]
        $Job
    )

    Process 
    {
        Enter-PSHostProcess -Id $Job.ProcessId 
        Debug-Runspace -Id $Job.RunspaceId
    }
}

function Publish-UAService
{
    param(
        [Parameter()]
        $ServiceName = "UniversalAutomation",
        [Parameter()]
        $PowerShellPath = (Get-Command PowerShell).Path,
        [Parameter()]
        $PowerShellArguments = @(),
        [Parameter()]
        [int]$Port = 80,
        [Parameter()]
        [ValidateSet("x64", "x86")]
        [string]$Architecture = 'x64'
    )

    $nssm = [IO.Path]::Combine($PSScriptRoot, 'nssm', $Architecture, 'nssm')

    & $nssm install $ServiceName $PowerShellPath 
}

New-Alias -Name 'Receive-UAJob' -Value 'Get-UAJobPipelineOutput'