modules/HomeLab.Azure/Private/Invoke-Deployment.ps1

function Invoke-Deployment {
    [CmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [string]$TemplateFile,
        
        [Parameter(Mandatory=$true)]
        [string]$ComponentName,
        
        [Parameter(Mandatory=$true)]
        [string]$ResourceType,
        
        [Parameter(Mandatory=$true)]
        [string]$ResourceName,
        
        [Parameter(Mandatory=$true)]
        [string]$ResourceGroup,
        
        [Parameter(Mandatory=$true)]
        [array]$DeploymentParams,
        
        [Parameter(Mandatory=$false)]
        [switch]$Monitor,
        
        [Parameter(Mandatory=$false)]
        [int]$PollIntervalSeconds = 10,
        
        [Parameter(Mandatory=$false)]
        [int]$TimeoutMinutes = 30
    )
    
    Write-Log -Message "=== Deploying $ComponentName ===" -Level Info
    Write-Log -Message "Using template: $TemplateFile" -Level Debug
    Write-Log -Message "Resource parameters: ResourceType=$ResourceType, ResourceName=$ResourceName, ResourceGroup=$ResourceGroup" -Level Debug
    
    # Verify template file exists
    if (-not (Test-Path -Path $TemplateFile)) {
        Write-Log -Message "Template file not found: $TemplateFile" -Level Error
        return $false
    }

    # Construct the deployment command
    $deployCmd = @("az", "deployment", "group", "create", "--template-file", $TemplateFile) + $DeploymentParams
    Write-Log -Message "Final command: $($deployCmd -join ' ')" -Level Debug

    try {
        # Execute the deployment command and capture output
        $result = & $deployCmd[0] $deployCmd[1..($deployCmd.Length-1)] 2>&1
        Write-Log -Message "Command output: $result" -Level Debug
    }
    catch {
        Write-Log -Message "$ComponentName deployment encountered an error: $($_.Exception.Message)" -Level Error
        return $false
    }

    if (-not $Monitor -and ($LASTEXITCODE -ne 0)) {
        Write-Log -Message "$ComponentName deployment failed with exit code $LASTEXITCODE" -Level Error
        return $false
    }

    # If Monitor is enabled, do foreground monitoring via a runspace
    if ($Monitor) {
        Write-Log -Message "Starting foreground monitoring for $ComponentName deployment." -Level Info
        $monitorScript = {
            param($ResourceGroup, $ResourceType, $ResourceName, $PollIntervalSeconds, $TimeoutMinutes)
            $monitorInstance = [DeploymentMonitor]::new($ResourceGroup, $ResourceType, $ResourceName, $PollIntervalSeconds, $TimeoutMinutes)
            return $monitorInstance.Monitor()
        }
        $runspacePool = [runspacefactory]::CreateRunspacePool(1, 5)
        $runspacePool.Open()
        $psInstance = [powershell]::Create()
        $psInstance.RunspacePool = $runspacePool
        $psInstance.AddScript($monitorScript).AddArgument($ResourceGroup).AddArgument($ResourceType).AddArgument($ResourceName).AddArgument($PollIntervalSeconds).AddArgument($TimeoutMinutes) | Out-Null
        $handle = $psInstance.BeginInvoke()
        $resultMonitor = $psInstance.EndInvoke($handle)
        $psInstance.Dispose()
        $runspacePool.Close()
        $runspacePool.Dispose()

        if (-not $resultMonitor) {
            Write-Log -Message "$ComponentName deployment monitoring failed or timed out" -Level Warning
            return $false
        }
    }

    Write-Log -Message "$ComponentName deployment completed successfully" -Level Success
    return $true
}