Public/VM/New-VergeCloudInitFile.ps1
|
function New-VergeCloudInitFile { <# .SYNOPSIS Creates a new cloud-init file in VergeOS. .DESCRIPTION New-VergeCloudInitFile creates a new cloud-init file in VergeOS for VM provisioning. Cloud-init files are used to provide user-data, meta-data, network-config, and other configuration to VMs during boot. .PARAMETER VMId The ID (key) of the VM that this cloud-init file belongs to. Cloud-init files are associated with specific VMs for provisioning. .PARAMETER VM A VM object from Get-VergeVM. Can be used instead of VMId. .PARAMETER Name The name of the cloud-init file. This should typically start with a forward slash (e.g., /user-data, /meta-data, /network-config). .PARAMETER Contents The contents of the cloud-init file. Maximum size is 65536 bytes (64KB). Can be provided as a string or read from a file using Get-Content -Raw. .PARAMETER Render Specifies how the file should be rendered during VM provisioning: - No: File is used as-is without any processing (default) - Variables: File supports VergeOS variable substitution - Jinja2: File is processed as a Jinja2 template .PARAMETER PassThru Return the created cloud-init file object. .PARAMETER Server The VergeOS connection to use. Defaults to the current default connection. .EXAMPLE New-VergeCloudInitFile -VMId 123 -Name "/user-data" -Contents $userData Creates a simple user-data file for VM 123 without variable processing. .EXAMPLE $vm = Get-VergeVM -Name "myvm" $userData = Get-Content ./user-data.yaml -Raw New-VergeCloudInitFile -VM $vm -Name "/user-data" -Contents $userData -Render Jinja2 -PassThru Creates a user-data file with Jinja2 template rendering for a VM and returns the created object. .EXAMPLE Get-VergeVM -Name "myvm" | New-VergeCloudInitFile -Name "/meta-data" -Contents "instance-id: {{vm_name}}" -Render Variables Creates a meta-data file with VergeOS variable substitution using pipeline input. .OUTPUTS None by default. Verge.CloudInitFile when -PassThru is specified. .NOTES Cloud-init files have a maximum size of 65536 bytes (64KB). Common cloud-init file names: - /user-data: User configuration (packages, users, scripts) - /meta-data: Instance metadata (instance-id, hostname) - /network-config: Network configuration - /vendor-data: Vendor-specific configuration #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium', DefaultParameterSetName = 'ByVMId')] [OutputType([PSCustomObject])] param( [Parameter(Mandatory, ParameterSetName = 'ByVMId')] [int]$VMId, [Parameter(Mandatory, ValueFromPipeline, ParameterSetName = 'ByVM')] [PSTypeName('Verge.VM')] [PSCustomObject]$VM, [Parameter(Mandatory, Position = 0)] [ValidateNotNullOrEmpty()] [ValidateLength(1, 256)] [string]$Name, [Parameter(Position = 1)] [ValidateScript({ if ($_.Length -gt 65536) { throw "Contents exceed maximum size of 65536 bytes (64KB). Current size: $($_.Length) bytes." } $true })] [string]$Contents, [Parameter()] [ValidateSet('No', 'Variables', 'Jinja2')] [string]$Render = 'No', [Parameter()] [switch]$PassThru, [Parameter()] [object]$Server ) begin { # Resolve connection if (-not $Server) { $Server = $script:DefaultConnection } if (-not $Server) { throw [System.InvalidOperationException]::new( 'Not connected to VergeOS. Use Connect-VergeOS to establish a connection.' ) } # Map friendly render names to API values $renderMapping = @{ 'No' = 'no' 'Variables' = 'variables' 'Jinja2' = 'jinja2' } } process { # Resolve VM ID $targetVMId = switch ($PSCmdlet.ParameterSetName) { 'ByVMId' { $VMId } 'ByVM' { $VM.Key } } if (-not $targetVMId) { throw "Unable to determine VM ID. Provide either -VMId or -VM parameter." } # Build request body $body = @{ name = $Name render = $renderMapping[$Render] owner = "vms/$targetVMId" } # Add contents if provided if ($Contents) { $body['contents'] = $Contents } # Determine display info for confirmation $renderDisplay = $Render $sizeInfo = if ($Contents) { "$($Contents.Length) bytes" } else { "empty" } if ($PSCmdlet.ShouldProcess("$Name for VM $targetVMId ($sizeInfo, Render: $renderDisplay)", 'Create CloudInit File')) { try { Write-Verbose "Creating cloud-init file '$Name' for VM $targetVMId with render type '$renderDisplay'" $response = Invoke-VergeAPI -Method POST -Endpoint 'cloudinit_files' -Body $body -Connection $Server # Get the created file key $fileKey = $response.'$key' if (-not $fileKey -and $response.key) { $fileKey = $response.key } Write-Verbose "Cloud-init file created with Key: $fileKey" if ($PassThru -and $fileKey) { # Return the created file Start-Sleep -Milliseconds 500 Get-VergeCloudInitFile -Key $fileKey -Server $Server } } catch { $errorMessage = $_.Exception.Message if ($errorMessage -match 'already exists' -or $errorMessage -match 'duplicate') { throw "A cloud-init file named '$Name' already exists." } throw "Failed to create cloud-init file '$Name': $errorMessage" } } } } |