src/public/Deployment/New-AitherLinuxCloudInit.ps1

#Requires -Version 7.0

<#
.SYNOPSIS
    Generate cloud-init configuration from Linux config

.DESCRIPTION
    Creates a cloud-init YAML/JSON configuration file based on config.linux.psd1.

.PARAMETER ConfigPath
    Path to Linux configuration file

.PARAMETER OutputPath
    Output directory for generated file

.PARAMETER Format
    Output format: yaml or json

.EXAMPLE
    New-AitherLinuxCloudInit -ConfigPath ./config.linux.psd1
    
    Generate cloud-init YAML configuration

.OUTPUTS
    String - Path to generated file, or null if generation is disabled

.NOTES
    Requires config.linux.psd1 with Linux.DeploymentArtifacts.CloudInit section.
    Generation can be disabled in configuration.

.LINK
    New-AitherDeploymentArtifact
    New-AitherLinuxShellScript
#>

function New-AitherLinuxCloudInit {
[CmdletBinding()]
param(
    [Parameter(Mandatory=$false)]
    [string]$ConfigPath,
    
    [string]$OutputPath = './artifacts/linux',
    
    [ValidateSet('yaml', 'json')]
    [string]$Format = 'yaml'
)

begin {
    if (-not [System.IO.Path]::IsPathRooted($OutputPath)) {
        $moduleRoot = Get-AitherModuleRoot
        $OutputPath = Join-Path $moduleRoot $OutputPath
    }
    
    # Helper function for YAML conversion
    function ConvertTo-SimpleYaml {
        param([hashtable]$Data, [int]$Indent = 0)
        $yaml = ""
        $indentStr = " " * $Indent
        foreach ($key in $Data.Keys) {
            $value = $Data[$key]
            if ($value -is [hashtable]) {
                $yaml += "$indentStr$($key):`n"
                $yaml += ConvertTo-SimpleYaml -Data $value -Indent ($Indent + 1)
            }
            elseif ($value -is [array]) {
                $yaml += "$indentStr$($key):`n"
                foreach ($item in $value) {
                    if ($item -is [hashtable]) {
                        $yaml += "$indentStr -`n"
                        foreach ($subKey in $item.Keys) {
                            $yaml += "$indentStr $($subKey): $($item[$subKey])`n"
                        }
                    }
                    else {
                        $yaml += "$indentStr - $item`n"
                    }
                }
            }
            elseif ($null -ne $value) {
                $yaml += "$indentStr$($key): $value`n"
            }
        }
        return $yaml
    }
}

process { try {
        # During module validation, skip execution
        if ($PSCmdlet.MyInvocation.InvocationName -eq '.') {
            return $null
        }
        
        $hasWriteAitherLog = Get-Command Write-AitherLog -ErrorAction SilentlyContinue
        
        if ($hasWriteAitherLog) {
            Write-AitherLog -Message "Generating cloud-init configuration from $ConfigPath" -Level Information -Source 'New-AitherLinuxCloudInit'
        }
        
        # Load configuration
        if (-not (Get-Command Get-AitherConfigs -ErrorAction SilentlyContinue)) {
            Write-AitherLog -Level Warning -Message "Get-AitherConfigs is not available. Cannot generate cloud-init config." -Source 'New-AitherLinuxCloudInit'
            return $null
        }
        
        $config = Get-AitherConfigs -ConfigFile $ConfigPath
        
        if (-not $config.Linux.DeploymentArtifacts.CloudInit.Generate) {
            if ($hasWriteAitherLog) {
                Write-AitherLog -Message "Cloud-init generation is disabled in configuration" -Level Warning -Source 'New-AitherLinuxCloudInit'
            } else {
                Write-Warning "Cloud-init generation is disabled in configuration"
            }
            return $null
        }
        
        $cloudInitConfig = $config.Linux.DeploymentArtifacts.CloudInit
        
        # Build cloud-init configuration
        $cloudInit = @{
            '#cloud-config' = $null
            hostname = $config.Linux.System.Hostname.Name
            fqdn = $config.Linux.System.Hostname.FQDN
            manage_etc_hosts = $true
        }
        
        # Add users
        if ($config.Linux.Users.Create.Count -gt 0) {
            $cloudInit.users = @()
            foreach ($user in $config.Linux.Users.Create) {
                $cloudInit.users += @{
                    name = $user.Username
                    groups = $user.Groups -join ','
                    shell = $user.Shell
                    sudo = if ($user.Groups -contains 'sudo') { 'ALL=(ALL) NOPASSWD:ALL' } else { $null }
                }
            }
        }
        
        # Add packages
        if ($config.Linux.Packages.Essential.Count -gt 0) {
            $cloudInit.packages = $config.Linux.Packages.Essential
        }
        
        # Add kernel parameters
        if ($config.Linux.KernelParameters.AutoApply) {
            $cloudInit.write_files = @(
                @{
                    path = $config.Linux.KernelParameters.ConfigFile
                    content = ($config.Linux.KernelParameters.Parameters.GetEnumerator() | ForEach-Object { "$($_.Key) = $($_.Value)" }) -join "`n"
                    owner = 'root:root'
                    permissions = '0644'
                }
            )
        }
        
        # Ensure output directory exists
        if (-not (Test-Path $OutputPath)) {
            New-Item -Path $OutputPath -ItemType Directory -Force | Out-Null
        }
        
        # Save cloud-init file
        $fileName = if ($Format -eq 'yaml') { 'cloud-init.yaml' } else { 'cloud-init.json' }
        $outputFile = Join-Path $OutputPath $fileName
        
        if ($Format -eq 'yaml') {
            $yamlContent = "#cloud-config`n"
            $yamlContent += ConvertTo-SimpleYaml -Data $cloudInit
            $yamlContent | Out-File -FilePath $outputFile -Encoding UTF8 -Force
        }
        else {
            $cloudInit | ConvertTo-Json -Depth 10 | Out-File -FilePath $outputFile -Encoding UTF8 -Force
        }
        
        if ($hasWriteAitherLog) {
            Write-AitherLog -Message "Generated cloud-init config: $outputFile" -Level Information -Source 'New-AitherLinuxCloudInit'
        }
        return $outputFile
    }
    catch {
        if ($hasWriteAitherLog) {
            Write-AitherLog -Message "Error generating cloud-init config: $($_.Exception.Message)" -Level Error -Source 'New-AitherLinuxCloudInit' -Exception $_
        } else {
            Write-AitherLog -Level Error -Message "Error generating cloud-init config: $($_.Exception.Message)" -Source 'New-AitherLinuxCloudInit' -Exception $_
        }
        throw
    }
}

}