Public/cloud-router.ps1

function Get-CloudRouter {
    <#
    .SYNOPSIS
        Gets routers from the Cloud Server.
     
    .DESCRIPTION
        Retrieves a list of routers. Automatically handles token refresh.
     
    .PARAMETER Name
        Optional. Filter by Router name.
     
    .EXAMPLE
        # Get all virtual routers
        Get-CloudRouter
         
    .EXAMPLE
        # Get virtual routers matching a name string
        Get-CloudRouter -Name "web-server-01"
 
    .EXAMPLE
        # Get a virtual router by ID
        Get-CloudRouter -ID 561
    #>

    
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $false)]
        [string]$Name,
        
        [Parameter(Mandatory = $false)]
        [int]$ID
    )
    
    # Build the URI - adjust this to match your actual API endpoint
    $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/router"
    
    # Use the helper function which handles token refresh automatically
    $response = Invoke-CloudApiRequest -Uri $uri -Method Get
    
    # Extract routers from the response
    $routers = $response.routers
 
    # Filter by name if specified
    if ($Name) {
        $routers = $routers | Where-Object { $_.name -like "*$Name*" }
    }
    
    # Filter by ID if specified - use PSBoundParameters to check if parameter was provided
    elseif ($PSBoundParameters.ContainsKey('ID')) {
            $routers = $routers | Where-Object { ($_.id -eq $ID) -and ($null -ne $_.id) }
    }
    
    return $routers
}

function Get-CloudRouterTemplate {
    <#
    .SYNOPSIS
        Gets template from the Cloud Server.
     
    .DESCRIPTION
        Retrieves a list of templates. Automatically handles token refresh.
     
    .PARAMETER Name
        Optional. Filter by Template name.
     
    .EXAMPLE
        # Get all virtual router templates
        Get-CloudRouterTemplate
 
    .EXAMPLE
        # Get virtual router templates matching a name string
        Get-CloudRouterTemplate -Name "debian-router"
         
    #>

    
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $false)]
        [string]$Name,
        
        [Parameter(Mandatory = $false)]
        [int]$ID
    )
    
    # Build the URI - adjust this to match your actual API endpoint
    $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/template"
    
    # Use the helper function which handles token refresh automatically
    $response = Invoke-CloudApiRequest -Uri $uri -Method Get
    
    # Extract templates from the response
    $templates = (Get-CloudTemplate| where {$_.template_text -match "VROUTER = YES"})
    
    # Filter by name if specified
    if ($Name) {
        $templates = $templates | Where-Object { $_.name -like "*$Name*" }
    }
    # Filter by ID if specified - use PSBoundParameters to check if parameter was provided
    elseif ($PSBoundParameters.ContainsKey('ID')) {
            $templates = $templates | Where-Object { ($_.id -eq $ID) -and ($null -ne $_.id) }
    }

    return $templates
}

function New-CloudRouter {
    <#
    .SYNOPSIS
        Creates a new virtual router in the Cloud Server.
     
    .DESCRIPTION
        Creates a virtual router. Automatically handles token refresh.
     
    .PARAMETER Name
        Name of the router
         
    .PARAMETER TemplateID
        Template ID to use for the router
         
    .PARAMETER KeepalivedPassword
        Keepalived password for the router
         
    .PARAMETER KeepalivedID
        Keepalived ID for the router
     
    .PARAMETER Template
        Full router template as a string (alternative to individual parameters)
     
    .EXAMPLE
        # Create a new virtual router with individual parameters
        New-CloudRouter -Name "gateway-router" -TemplateID 5 -KeepalivedPassword "secure123" -KeepalivedID 100
         
    .EXAMPLE
        # Create a new virtual router with a single template variable
        $template = @"
NAME="test-router"
TEMPLATE_ID=5
KEEPALIVED_PASSWORD="mypassword"
KEEPALIVED_ID=100
"@
        New-CloudRouter -Template $template
    #>

    
    [CmdletBinding(DefaultParameterSetName='Individual')]
    param(
        [Parameter(Mandatory = $true, ParameterSetName='Individual')]
        [string]$Name,
        
        [Parameter(Mandatory = $true, ParameterSetName='Individual')]
        [int]$TemplateID,
        
        [Parameter(Mandatory = $true, ParameterSetName='Individual')]
        [string]$KeepalivedPassword,
        
        [Parameter(Mandatory = $true, ParameterSetName='Individual')]
        [int]$KeepalivedID,
        
        [Parameter(Mandatory = $true, ParameterSetName='Template')]
        [string]$Template
    )
    
    # Build template string if using individual parameters
    if ($PSCmdlet.ParameterSetName -eq 'Individual') {
        $Template = @"
NAME="$Name"
TEMPLATE_ID=$TemplateID
KEEPALIVED_PASSWORD="$KeepalivedPassword"
KEEPALIVED_ID=$KeepalivedID
"@

    }
    
    $routerData = @{
        template = $Template
    }
    
    $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/router"
    
    Write-Verbose "Request URI: $uri"
    Write-Verbose "Router Template:`n$Template"
    
    $response = Invoke-CloudApiRequest -Uri $uri -Method Post -Body $routerData
    
    return $response
}

function Remove-CloudRouter {
    <#
    .SYNOPSIS
        Delete a router from the Cloud Server.
     
    .DESCRIPTION
        Deletes the specified router. Automatically handles token refresh.
     
    .PARAMETER ID
        Required. The ID of the router to be deleted.
     
    .EXAMPLE
        # Remove a virtual router
        Remove-CloudRouter -ID 561
         
    .EXAMPLE
        # Remove a virtual router, bypassing the confirmation prompt
        Remove-CloudRouter -ID 561 -Confirm:$false
         
    .EXAMPLE
        # Preview deletion without actually removing
        Remove-CloudRouter -ID 561 -WhatIf
    #>

    
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')]
    param(
        [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
        [int]$ID
    )
    
    process {
        # Get the router details for confirmation message
        try {
            $router = Get-CloudRouter -ID $ID
        }
        catch {
            Write-Warning "Router with ID $ID not found."
            return
        }
        
        if (-not $router) {
            Write-Warning "Router with ID $ID not found."
            return
        }
        
        $routerName = if ($router.name) { $router.name } else { "Unnamed" }
        
        # Confirm before deletion
        if ($PSCmdlet.ShouldProcess("Router ID $ID ($routerName)", "Remove router")) {
            
            $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/router/$ID"
            
            Write-Verbose "Removing router ID ${ID}: $routerName"
            
            try {
                $response = Invoke-CloudApiRequest -Uri $uri -Method Delete
                Write-Host "Router $ID removed successfully." -ForegroundColor Green
                return $response
            }
            catch {
                # Check for specific error messages
                if ($_.Exception.Message -match "not found|does not exist") {
                    Write-Warning "Router $ID not found or already deleted."
                    return
                }
                else {
                    # Re-throw other errors
                    throw
                }
            }
        }
    }
}

function Rename-CloudRouter {
    <#
    .SYNOPSIS
        Rename a virtual router in the Cloud Server.
     
    .DESCRIPTION
        Renames a virtual router. Automatically handles token refresh.
     
    .PARAMETER Name
        New name of the router
         
    .PARAMETER ID
        ID of the router
             
    .EXAMPLE
        # Rename a cloud router
        Rename-CloudRouter -Name "new-name" -ID 5
    #>

    
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true)]
        [string]$Name,
        
        [Parameter(Mandatory = $true)]
        [int]$ID
    )
        
    $newname = @{
        name = $Name
    }
    
    $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/router/${ID}/name"
       
    $response = Invoke-CloudApiRequest -Uri $uri -Method Patch -Body $newname
    
    return $response
}

function Update-CloudRouter {
    <#
    .SYNOPSIS
        Updates a virtual router in the Cloud Server.
     
    .DESCRIPTION
        Creates a virtual router. Automatically handles token refresh.
     
    .PARAMETER Name
        Name of the router
         
    .PARAMETER ID
        ID of the router
         
    .PARAMETER KeepalivedPassword
        Keepalived password for the router
         
    .PARAMETER KeepalivedID
        Keepalived ID for the router
     
    .PARAMETER Config
        Full router config as a string (alternative to individual parameters)
     
    .EXAMPLE
        # Update a virtual router with individual parameters
        Update-CloudRouter -Name "gateway-router" -ID 4 -KeepalivedPassword "secure123" -KeepalivedID 100
         
    .EXAMPLE
        # Update a virtual router with a template variable
        $router = @"
NAME="test-router"
KEEPALIVED_PASSWORD="mypassword"
KEEPALIVED_ID=100
"@
        Update-CloudRouter -Config $routerdata -ID 4
    #>

    
    [CmdletBinding(DefaultParameterSetName='Individual')]
    param(
        [Parameter(Mandatory = $false, ParameterSetName='Individual')]
        [string]$Name,
                
        [Parameter(Mandatory = $false, ParameterSetName='Individual')]
        [string]$KeepalivedPassword,
        
        [Parameter(Mandatory = $false, ParameterSetName='Individual')]
        [int]$KeepalivedID,
        
        [Parameter(Mandatory = $true, ParameterSetName='Individual')]
        [int]$ID,
        
        [Parameter(Mandatory = $true, ParameterSetName='Config')]
        [string]$Config
    )
    
    # Build template string if using individual parameters
    if ($PSCmdlet.ParameterSetName -eq 'Individual') {
        $routerData = @"
NAME="$Name"
KEEPALIVED_PASSWORD="$KeepalivedPassword"
KEEPALIVED_ID=$KeepalivedID
"@

    }
    
    $routerData = @{
        merge = $true
        template = $Config
    }
    
    $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/router/${ID}"
    
    Write-Verbose "Request URI: $uri"
    Write-Verbose "Router Template:`n$config"
    
    $response = Invoke-CloudApiRequest -Uri $uri -Method Patch -Body $routerData
    
    return $response
}

function Lock-CloudRouter {
    <#
    .SYNOPSIS
        Lock a virtual router in the Cloud Server.
     
    .DESCRIPTION
        Lock a virtual router. Automatically handles token refresh.
        
    .PARAMETER ID
        ID of the router
 
    .PARAMETER Level
        Lock level (USE, MANAGE, ADMIN, ALL)
 
    .PARAMETER Test
        When set, performs a test lock instead of a real one.
 
    .EXAMPLE
        # Lock a virtual router
        Lock-CloudRouter -ID 5 -Level ADMIN
 
    .EXAMPLE
        # Test locking a virtual router
        Lock-CloudRouter -ID 5 -Level USE -Test
 
    #>

    
    [CmdletBinding()]
    param(
        
        [Parameter(Mandatory = $true)]
        [int]$ID,
        
        [Parameter(Mandatory = $true)]
        [ValidateSet('USE','MANAGE','ADMIN','ALL')]
        [string]$Level,
        
        [switch]$Test
    )

    $lockdata = @{
        level = $Level
        test  = [bool]$Test
    }
    
    $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/router/${ID}/lock"
    $response = Invoke-CloudApiRequest -Uri $uri -Method Patch -Body $lockdata
    return $response
}

function Unlock-CloudRouter {
    <#
    .SYNOPSIS
        Unlock a virtual router in the Cloud Server.
     
    .DESCRIPTION
        Unlock a virtual router. Automatically handles token refresh.
        
    .PARAMETER ID
        ID of the router
 
    .EXAMPLE
        # Unlock a virtual router
        Unlock-CloudRouter -ID 5
 
    #>

    
    [CmdletBinding()]
    param(
        
        [Parameter(Mandatory = $true)]
        [int]$ID        

    )
   
    $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/router/${ID}/unlock"
    $response = Invoke-CloudApiRequest -Uri $uri -Method Patch #-Body $lockdata
    return $response
}

function Update-CloudRouterOwner {
    <#
    .SYNOPSIS
        Updates the ownership of a router in the Cloud Server.
     
    .DESCRIPTION
        Changes the user and/or group ownership of a router. Prompts for confirmation.
     
    .PARAMETER ID
        Required. ID of the router.
     
    .PARAMETER UserID
        Required. ID of the user to own the router.
         
    .PARAMETER GroupID
        Optional. ID of the group to own the router.
         
    .EXAMPLE
        # Change the ownership of a virtual router to a user
        Update-CloudRouterOwner -ID 5 -UserID 2
         
    .EXAMPLE
        # Change the ownership of a virtual router to a user and a group
        Update-CloudRouterOwner -ID 5 -UserID 2 -GroupID 100
         
    .EXAMPLE
        # Change the ownership of a virtual router to a user, bypassing the confirmation prompt
        Update-CloudRouterOwner -ID 5 -UserID 2 -Confirm:$false
    #>

    
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')]
    param(
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [int]$ID,
        
        [Parameter(Mandatory = $true)]
        [Alias('User')]
        [int]$UserID,
                
        [Parameter(Mandatory = $false)]
        [Alias('Group')]
        [int]$GroupID
    )
    
    process {
        # Build the update body
        $body = [PSCustomObject]@{
            user = $UserID
        }
        
        if ($PSBoundParameters.ContainsKey('GroupID')) {
            $body | Add-Member -NotePropertyName 'group' -NotePropertyValue $GroupID
        }
        
        $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/router/${ID}/ownership"
        
        # Build action description for confirmation
        $actionParts = @("Change owner to User ID $UserID")
        if ($PSBoundParameters.ContainsKey('GroupID')) {
            $actionParts += "Group ID $GroupID"
        }
        $actionDescription = $actionParts -join " and "
        
        # Use the helper function
        Invoke-CloudResourceUpdate `
            -CallerPSCmdlet $PSCmdlet `
            -ResourceType "Router" `
            -ID $ID `
            -Uri $uri `
            -Body $body `
            -Action $actionDescription `
            -GetResourceScript { Get-CloudRouter -ID $ID } `
            -SuccessMessage "Router $ID ownership updated successfully."
    }
}

function Update-CloudRouterPermissions {
    <#
    .SYNOPSIS
        Updates the permissions of a router in the Cloud Server.
     
    .DESCRIPTION
        Changes the permission of a router. Prompts for confirmation.
     
    .PARAMETER ID
        Required. ID of the router.
     
    .PARAMETER OwnerUse
        Optional. True or false, enable OwnerUse
 
    .PARAMETER OwnerManage
        Optional. True or false, enable OwnerManage
 
    .PARAMETER OwnerAdmin
        Optional. True or false, enable OwnerAdmin
 
    .PARAMETER GroupUse
        Optional. True or false, enable GroupUse
         
    .PARAMETER GroupManage
        Optional. True or false, enable GroupManage
         
    .PARAMETER GroupAdmin
        Optional. True or false, enable GroupAdmin
         
    .PARAMETER OtherUse
        Optional. True or false, enable OtherUse
         
    .PARAMETER OtherManage
        Optional. True or false, enable OtherManage
         
    .PARAMETER OtherAdmin
        Optional. True or false, enable OtherManage
         
    .EXAMPLE
        # Give group users permission to use the router
        Update-CloudRouterPermissions -ID 35 -GroupUse $true
         
    .EXAMPLE
        # Deny group admin permission to the router
        Update-CloudRouterPermissions -ID 35 -GroupAdmin $false
         
    .EXAMPLE
        # Set multiple permissions at once
        Update-CloudRouterPermissions -ID 35 -GroupUse $true -GroupManage $true -OtherUse $true
    #>


    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')]
    param(
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [int]$ID,
        
        [Parameter(Mandatory = $false)]
        [bool]$OwnerUse,
        
        [Parameter(Mandatory = $false)]
        [bool]$OwnerManage,
        
        [Parameter(Mandatory = $false)]
        [bool]$OwnerAdmin,
        
        [Parameter(Mandatory = $false)]
        [bool]$GroupUse,
        
        [Parameter(Mandatory = $false)]
        [bool]$GroupManage,
        
        [Parameter(Mandatory = $false)]
        [bool]$GroupAdmin,
        
        [Parameter(Mandatory = $false)]
        [bool]$OtherUse,
        
        [Parameter(Mandatory = $false)]
        [bool]$OtherManage,
        
        [Parameter(Mandatory = $false)]
        [bool]$OtherAdmin
    )
    
    process {
        # Build the permissions object structure as shown in the API spec
        $permissions = @{}
        
        if ($PSBoundParameters.ContainsKey('OwnerUse')) { $permissions['owner_use'] = $OwnerUse }
        if ($PSBoundParameters.ContainsKey('OwnerManage')) { $permissions['owner_manage'] = $OwnerManage }
        if ($PSBoundParameters.ContainsKey('OwnerAdmin')) { $permissions['owner_admin'] = $OwnerAdmin }
        
        if ($PSBoundParameters.ContainsKey('GroupUse')) { $permissions['group_use'] = $GroupUse }
        if ($PSBoundParameters.ContainsKey('GroupManage')) { $permissions['group_manage'] = $GroupManage }
        if ($PSBoundParameters.ContainsKey('GroupAdmin')) { $permissions['group_admin'] = $GroupAdmin }
        
        if ($PSBoundParameters.ContainsKey('OtherUse')) { $permissions['other_use'] = $OtherUse }
        if ($PSBoundParameters.ContainsKey('OtherManage')) { $permissions['other_manage'] = $OtherManage }
        if ($PSBoundParameters.ContainsKey('OtherAdmin')) { $permissions['other_admin'] = $OtherAdmin }
        
        # Create the body with the permissions nested structure
        $body = @{
            permissions = $permissions
        }
        
        $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/router/${ID}/permissions"
        
        Invoke-CloudResourceUpdate `
            -CallerPSCmdlet $PSCmdlet `
            -ResourceType "Router" `
            -ID $ID `
            -Uri $uri `
            -Body $body `
            -Action "Update permissions" `
            -GetResourceScript { Get-CloudRouter -ID $ID }
    }
}

function New-CloudRouterFromTemplate {
    <#
    .SYNOPSIS
        Instantiates a virtual router from a template.
     
    .DESCRIPTION
        Creates a new virtual router instance from an existing router template.
     
    .PARAMETER RouterID
        Required. ID of the router template to instantiate.
     
    .PARAMETER Name
        Required. Name for the new router instance.
     
    .PARAMETER TemplateID
        Required. VM template ID to use for the router VMs.
     
    .PARAMETER Instances
        Optional. Number of instances to create. Default is 1.
     
    .PARAMETER Extra
        Optional. Additional template attributes to override or add.
     
    .PARAMETER Pending
        Optional. Create in pending state if true. Default is false.
     
    .EXAMPLE
        # Basic router instantiation
        New-CloudRouterFromTemplate -RouterID 5 -Name "production-router"
         
    .EXAMPLE
        # Create multiple router instances
        New-CloudRouterFromTemplate -RouterID 5 -Name "router-cluster" -Instances 3 -TemplateID 10
         
    .EXAMPLE
        # With custom template and extra parameters
        New-CloudRouterFromTemplate -RouterID 5 -Name "custom-router" -TemplateID 10 -Extra "CPU = 2"
         
    .EXAMPLE
        # Create in pending state for later activation
        New-CloudRouterFromTemplate -RouterID 5 -Name "staging-router" -Pending:$true -TemplateID 10
    #>

    
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('ID', 'router_id')]
        [int]$RouterID,
        
        [Parameter(Mandatory = $true)]
        [string]$Name,
        
        [Parameter(Mandatory = $false)]
        [int]$Instances = 1,
        
        [Parameter(Mandatory = $True)]
        [Alias('Template')]
        [int]$TemplateID,
        
        [Parameter(Mandatory = $false)]
        [string]$Extra,
        
        [Parameter(Mandatory = $false)]
        [bool]$Pending = $false
    )
    
    process {
        # Build the request body
        $body = @{
            name = $Name
            instances = $Instances
            pending = $Pending
        }
        
        # Add optional parameters if specified
        if ($PSBoundParameters.ContainsKey('InstanceTemplate')) {
            $body.instance_template = $InstanceTemplate
        }
        
        if ($PSBoundParameters.ContainsKey('Extra')) {
            $body.extra = $Extra
        }
        else {
            $body.extra = ""
        }
        
        # Convert to PSCustomObject for proper JSON serialization
        $bodyObject = [PSCustomObject]$body
        
        # Build the URI
        $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/router/${RouterID}/instantiate"
        
        Write-Verbose "Instantiating router from template ID: $RouterID"
        Write-Verbose "Router name: $Name"
        Write-Verbose "Instances: $Instances"
        if ($InstanceTemplate) {
            Write-Verbose "Instance template: $InstanceTemplate"
        }
        if ($Extra) {
            Write-Verbose "Extra parameters: $Extra"
        }
        Write-Verbose "Request body: $($bodyObject | ConvertTo-Json -Compress)"
        
        try {
            $response = Invoke-CloudApiRequest -Uri $uri -Method Patch -Body $bodyObject
            
            Write-Host "Router '$Name' created successfully from template ID $RouterID." -ForegroundColor Green
            return $response
        }
        catch {
            Write-Error "Failed to instantiate router from template ${RouterID}: $_"
            throw
        }
    }
}

function New-CloudRouterNIC2 {
    <#
    .SYNOPSIS
        Adds a NIC to a virtual router.
     
    .DESCRIPTION
        Attaches a new network interface to an existing virtual router.
     
    .PARAMETER RouterID
        Required. ID of the router.
     
    .PARAMETER Template
        Required. NIC template in OpenNebula format.
     
    .PARAMETER NetworkID
        Optional. Network ID to attach to (alternative to using Template).
     
    .PARAMETER NetworkName
        Optional. Network name to attach to (alternative to using Template).
     
    .PARAMETER IP
        Optional. Specific IP address to assign.
     
    .EXAMPLE
        # Add NIC using template
        $template = 'NETWORK_ID = "2"'
        New-CloudRouterNIC -RouterID 5 -Template $template
         
    .EXAMPLE
        # Add NIC using parameters
        New-CloudRouterNIC -RouterID 5 -NetworkID 2
         
    .EXAMPLE
        # Add NIC with specific IP
        New-CloudRouterNIC -RouterID 5 -NetworkID 2 -IP "192.168.1.1"
         
    .EXAMPLE
        # Add NIC by network name
        New-CloudRouterNIC -RouterID 5 -NetworkName "SI-Dev"
    #>

    
    [CmdletBinding(DefaultParameterSetName='Template')]
    param(
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName='Template')]
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName='Parameters')]
        [Alias('ID', 'router_id')]
        [int]$RouterID,
        
        [Parameter(Mandatory = $true, ParameterSetName='Template')]
        [string]$Template,
        
        [Parameter(Mandatory = $true, ParameterSetName='Parameters')]
        [int]$NetworkID,
        
        [Parameter(Mandatory = $false, ParameterSetName='Parameters')]
        [string]$NetworkName,
        
        [Parameter(Mandatory = $false, ParameterSetName='Parameters')]
        [string]$IP
    )
    
    process {
        # Build template if using parameters
        if ($PSCmdlet.ParameterSetName -eq 'Parameters') {
            $templateParts = @()
            
            if ($NetworkID) {
                $templateParts += "NETWORK_ID = `"$NetworkID`""
            }
            
            if ($NetworkName) {
                $templateParts += "NETWORK = `"$NetworkName`""
            }
            
            if ($IP) {
                $templateParts += "IP = `"$IP`""
            }
            
            $Template = $templateParts -join "`n"
        }
        
        # Build the request body
        $body = [PSCustomObject]@{
            template = $Template
        }
        
        # Build the URI
        $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/router/${RouterID}/nic"
        
        Write-Verbose "Adding NIC to router ID: $RouterID"
        Write-Verbose "NIC template:`n$Template"
        Write-Verbose "Request body: $($body | ConvertTo-Json -Compress)"
        
        try {
            $response = Invoke-CloudApiRequest -Uri $uri -Method Post -Body $body
            
            Write-Host "NIC added successfully to router ID $RouterID." -ForegroundColor Green
            return $response
        }
        catch {
            Write-Error "Failed to add NIC to router ${RouterID}: $_"
            throw
        }
    }
}

function New-CloudRouterNIC {
    <#
    .SYNOPSIS
        Adds a NIC to a virtual router.
     
    .DESCRIPTION
        Attaches a new network interface to an existing virtual router.
     
    .PARAMETER RouterID
        Required. ID of the router.
     
    .PARAMETER Template
        Optional. Complete NIC template in OpenNebula format (will be wrapped in NIC = [ ... ]).
     
    .PARAMETER NetworkID
        Optional. Network ID to attach to.
     
    .PARAMETER NetworkName
        Optional. Network name to attach to.
     
    .PARAMETER IP
        Optional. Specific IP address to assign.
     
    .PARAMETER Model
        Optional. NIC model (e.g., "virtio"). Default is "virtio".
     
    .EXAMPLE
        # Add NIC using network ID
        New-CloudRouterNIC -RouterID 4 -NetworkID 2
         
    .EXAMPLE
        # Add NIC with specific IP
        New-CloudRouterNIC -RouterID 4 -NetworkID 2 -IP "192.168.1.1"
         
    .EXAMPLE
        # Add NIC by network name
        New-CloudRouterNIC -RouterID 4 -NetworkName "SI-Dev" -IP "192.168.6.1"
         
    .EXAMPLE
        # Add NIC with custom model
        New-CloudRouterNIC -RouterID 4 -NetworkID 2 -Model "e1000"
    #>

    
    [CmdletBinding()]
    param(
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('ID', 'router_id')]
        [int]$RouterID,
        
        [Parameter(Mandatory = $false)]
        [string]$Template,
        
        [Parameter(Mandatory = $false)]
        [int]$NetworkID,
        
        [Parameter(Mandatory = $false)]
        [string]$NetworkName,
        
        [Parameter(Mandatory = $false)]
        [string]$IP,
        
        [Parameter(Mandatory = $false)]
        [string]$Model = "virtio"
    )
    
    process {
        # Validate that either Template or NetworkID/NetworkName is provided
        if (-not $Template -and -not $NetworkID -and -not $NetworkName) {
            Write-Error "Either Template, NetworkID, or NetworkName must be specified"
            return
        }
        
        # Build NIC attributes
        if (-not $Template) {
            $nicParts = @()
            
            if ($NetworkID) {
                $nicParts += "NETWORK_ID = $NetworkID"
            }
            
            if ($NetworkName) {
                $nicParts += "NETWORK = `"$NetworkName`""
            }
            
            if ($IP) {
                $nicParts += "IP = `"$IP`""
            }
            
            if ($Model) {
                $nicParts += "MODEL = $Model"
            }
            
            # Wrap in NIC = [ ... ] format
            $nicAttributes = $nicParts -join ", "
            $Template = "NIC = [ $nicAttributes ]"
        }
        else {
            # If template provided, ensure it's wrapped in NIC = [ ... ]
            if ($Template -notmatch '^\s*NIC\s*=') {
                $Template = "NIC = [ $Template ]"
            }
        }
        
        # Build the request body
        $body = [PSCustomObject]@{
            template = $Template
        }
        
        # Build the URI
        $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/router/${RouterID}/nic"
        
        Write-Verbose "Adding NIC to router ID: $RouterID"
        Write-Verbose "NIC template: $Template"
        Write-Verbose "Request body: $($body | ConvertTo-Json -Compress)"
        
        try {
            $response = Invoke-CloudApiRequest -Uri $uri -Method Post -Body $body
            
            Write-Host "NIC added successfully to router ID $RouterID." -ForegroundColor Green
            return $response
        }
        catch {
            Write-Error "Failed to add NIC to router ${RouterID}: $_"
            throw
        }
    }
}

function Remove-CloudRouterNIC {
    <#
    .SYNOPSIS
        Removes a NIC from a virtual router.
     
    .DESCRIPTION
        Detaches a network interface from a virtual router.
     
    .PARAMETER RouterID
        Required. ID of the router.
     
    .PARAMETER NICID
        Required. ID of the NIC to remove.
     
    .EXAMPLE
        # Remove NIC 0 from router 5
        Remove-CloudRouterNIC -RouterID 5 -NICID 0
         
    .EXAMPLE
        # Remove without confirmation
        Remove-CloudRouterNIC -RouterID 5 -NICID 0 -Confirm:$false
    #>

    
    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High')]
    param(
        [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)]
        [Alias('ID', 'router_id')]
        [int]$RouterID,
        
        [Parameter(Mandatory = $true)]
        [Alias('nic_id')]
        [int]$NICID
    )
    
    process {
        # Build the URI
        $uri = "$($script:CloudConnection.BaseUri)/manifold-api/v2/cloud/router/${RouterID}/nic/${NICID}"
        
        if ($PSCmdlet.ShouldProcess("Router ID $RouterID", "Remove NIC ID $NICID")) {
            Write-Verbose "Removing NIC ID $NICID from router ID: $RouterID"
            Write-Verbose "Request URI: $uri"
            
            try {
                $response = Invoke-CloudApiRequest -Uri $uri -Method Delete
                
                Write-Host "NIC ID $NICID removed successfully from router ID $RouterID." -ForegroundColor Green
                return $response
            }
            catch {
                Write-Error "Failed to remove NIC from router ${RouterID}: $_"
                throw
            }
        }
    }
}