Public/domain.ps1

function Get-CSDomain {
    <#
    .SYNOPSIS
        Lists domains in CloudStack.

    .DESCRIPTION
        Retrieves a list of domains with optional filtering by ID, name,
        level, or other parameters.

    .PARAMETER Id
        Filter by domain ID

    .PARAMETER Name
        Filter by domain name (exact match)

    .PARAMETER Keyword
        Filter by keyword (partial match on name)

    .PARAMETER Level
        Filter by domain level

    .PARAMETER ListAll
        List all domains, including subdomains (requires appropriate permissions)

    .EXAMPLE
        Get-CSDomain
        Lists all domains

    .EXAMPLE
        Get-CSDomain -Name "ROOT"
        Gets a specific domain by name

    .EXAMPLE
        Get-CSDomain -Id "2c65dace-11e9-41ec-ba8f-005290d9ebd0"
        Gets a specific domain by ID

    .EXAMPLE
        Get-CSDomain -ListAll
        Lists all domains, including subdomains
    #>

    [CmdletBinding(DefaultParameterSetName='Default')]
    param(
        [Parameter(ParameterSetName='ById')]
        [string]$Id,

        [Parameter(ParameterSetName='ByName')]
        [string]$Name,

        [Parameter(ParameterSetName='Default')]
        [string]$Keyword,

        [Parameter(ParameterSetName='Default')]
        [int]$Level,

        [Parameter(ParameterSetName='Default')]
        [switch]$ListAll
    )

    # Build parameters
    $apiParams = @{}

    if ($PSBoundParameters.ContainsKey('Id')) {
        $apiParams['id'] = $Id
    }

    if ($PSBoundParameters.ContainsKey('Name')) {
        $apiParams['name'] = $Name
    }

    if ($PSBoundParameters.ContainsKey('Keyword')) {
        $apiParams['keyword'] = $Keyword
    }

    if ($PSBoundParameters.ContainsKey('Level')) {
        $apiParams['level'] = $Level
    }

    if ($ListAll) {
        $apiParams['listall'] = 'true'
    }

    # Make the API call
    $response = Invoke-CSApiRequest -Command 'listDomains' -Parameters $apiParams
    Write-Verbose ($apiParams | Out-String)

    # Return the domain list
    if ($response.listdomainsresponse.domain) {
        return $response.listdomainsresponse.domain
    }
    else {
        Write-Verbose "No domains found matching the criteria."
        return $null
    }
}

function New-CSDomain {
    <#
    .SYNOPSIS
        Creates a child domain.

    .DESCRIPTION
        Wraps the createDomain API. Creates a new domain beneath a parent domain
        (defaults to ROOT when -ParentDomainId is omitted).

    .PARAMETER Name
        Name for the new domain.

    .PARAMETER ParentDomainId
        UUID of the parent domain. Defaults to ROOT when omitted.

    .PARAMETER NetworkDomain
        DNS network domain for the domain's networks.

    .PARAMETER DomainId
        Assign a specific domain UUID instead of letting CloudStack generate one.

    .EXAMPLE
        New-CSDomain -Name 'engineering' -ParentDomainId 'root-domain-uuid'
        Creates a child domain under the given parent.

    .EXAMPLE
        New-CSDomain -Name 'platform' -NetworkDomain 'platform.example.com'
        Creates a top-level domain with a network domain.
    #>

    [CmdletBinding()]
    param([Parameter(Mandatory=$true)][string]$Name, [string]$ParentDomainId, [string]$NetworkDomain, [string]$DomainId)
    $apiParams = @{ name = $Name }
    if ($PSBoundParameters.ContainsKey('ParentDomainId')) { $apiParams['parentdomainid'] = $ParentDomainId }
    if ($PSBoundParameters.ContainsKey('NetworkDomain')) { $apiParams['networkdomain'] = $NetworkDomain }
    if ($PSBoundParameters.ContainsKey('DomainId')) { $apiParams['domainid'] = $DomainId }
    Invoke-CSApiRequest -Command 'createDomain' -Parameters $apiParams
}

function Remove-CSDomain {
    <#
    .SYNOPSIS
        Deletes a CloudStack domain.

    .DESCRIPTION
        Wraps the deleteDomain API. Removes a domain; use -Cleanup to also delete the
        accounts and resources it contains. Accepts a domain object (or its id) from
        the pipeline. This is destructive, so it honors -WhatIf/-Confirm.

    .PARAMETER DomainId
        The domain UUID to delete. Binds from a piped object's Id property.

    .PARAMETER Cleanup
        Also delete the accounts and resources contained in the domain.

    .EXAMPLE
        Remove-CSDomain -DomainId 'domain-uuid' -Confirm:$false
        Deletes an empty domain without prompting.

    .EXAMPLE
        Get-CSDomain -Name 'obsolete' | Remove-CSDomain -Cleanup
        Pipes a domain in and deletes it along with its contents.
    #>

    [CmdletBinding(SupportsShouldProcess=$true, ConfirmImpact='High')]
    param([Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)][Alias('Id')][string]$DomainId, [switch]$Cleanup)
    process {
        $apiParams = @{ id = $DomainId }; if ($Cleanup) { $apiParams['cleanup'] = 'true' }
        if ($PSCmdlet.ShouldProcess("domain $DomainId", 'Delete')) { Invoke-CSApiRequest -Command 'deleteDomain' -Parameters $apiParams }
    }
}

function Get-CSDomainChild {
    <#
    .SYNOPSIS
        Lists immediate child domains.

    .DESCRIPTION
        Wraps the listDomainChildren API. Returns the children of a domain; add
        -IsRecursive to include the whole subtree. Returns nothing when none match.

    .PARAMETER DomainId
        Parent domain whose children to list. Defaults to the caller's domain.

    .PARAMETER IsRecursive
        Include all descendants, not just immediate children.

    .PARAMETER Keyword
        Filter by a keyword substring match on the name.

    .PARAMETER Name
        Filter by child domain name.

    .PARAMETER ListAll
        List all child domains the caller can see (admin).

    .PARAMETER Page
        Page number for paged results.

    .PARAMETER PageSize
        Number of results per page.

    .EXAMPLE
        Get-CSDomainChild -DomainId 'domain-uuid'
        Lists the immediate children of a domain.

    .EXAMPLE
        Get-CSDomainChild -DomainId $domainId -IsRecursive
        Lists the entire subtree under a domain.
    #>

    [CmdletBinding()]
    param([string]$DomainId, [switch]$IsRecursive, [string]$Keyword, [string]$Name, [switch]$ListAll, [int]$Page, [int]$PageSize)
    $apiParams = @{}
    if ($PSBoundParameters.ContainsKey('DomainId')) { $apiParams['id'] = $DomainId }
    if ($IsRecursive) { $apiParams['isrecursive'] = 'true' }
    foreach ($key in @('Keyword','Name','Page','PageSize')) { if ($PSBoundParameters.ContainsKey($key)) { $apiParams[$key.ToLowerInvariant()] = (Get-Variable -Name $key -ValueOnly) } }
    if ($ListAll) { $apiParams['listall'] = 'true' }
    $response = Invoke-CSApiRequest -Command 'listDomainChildren' -Parameters $apiParams
    if ($response.listdomainchildrenresponse.domain) { return $response.listdomainchildrenresponse.domain }
}

function Move-CSDomain {
    <#
    .SYNOPSIS
        Moves a domain beneath a new parent domain.

    .DESCRIPTION
        Wraps the moveDomain API. Re-parents a domain (and its subtree) under a
        different parent domain. Accepts a domain object (or its id) from the pipeline.

    .PARAMETER DomainId
        The domain UUID to move. Binds from a piped object's Id property.

    .PARAMETER ParentDomainId
        UUID of the new parent domain.

    .EXAMPLE
        Move-CSDomain -DomainId 'domain-uuid' -ParentDomainId 'new-parent-domain-uuid'
        Moves a domain under a new parent.

    .EXAMPLE
        Get-CSDomain -Name 'engineering' | Move-CSDomain -ParentDomainId $platformDomainId
        Re-parents a piped domain.
    #>

    [CmdletBinding()]
    param([Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)][Alias('Id')][string]$DomainId, [Parameter(Mandatory=$true)][string]$ParentDomainId)
    process {
        Invoke-CSApiRequest -Command 'moveDomain' -Parameters @{ domainid = $DomainId; parentdomainid = $ParentDomainId }
    }
}

function Set-CSDomainLdapLink {
    <#
    .SYNOPSIS
        Links a CloudStack domain to an LDAP group or organizational unit.

    .DESCRIPTION
        Wraps the linkDomainToLdap API. Associates a domain with an LDAP group
        (-Type GROUP) or organizational unit (-Type OU) so matching LDAP users can
        authenticate into the domain. Accepts a domain object (or its id) from the
        pipeline.

    .PARAMETER DomainId
        The domain UUID to link. Binds from a piped object's Id property.

    .PARAMETER AccountType
        Privilege level for linked users: 0 (user) or 2 (domain admin).

    .PARAMETER Type
        Whether the link target is a GROUP or an OU.

    .PARAMETER Admin
        Username to designate as the domain's admin.

    .PARAMETER LdapDomain
        Distinguished name (or domain) of the LDAP group or OU.

    .PARAMETER Name
        Name of the LDAP group or OU to link.

    .EXAMPLE
        Set-CSDomainLdapLink -DomainId 'domain-uuid' -AccountType 0 -Type OU -LdapDomain 'example.com' -Name 'Engineering'
        Links a domain to an LDAP OU as regular users.

    .EXAMPLE
        Get-CSDomain -Name 'engineering' | Set-CSDomainLdapLink -AccountType 2 -Type GROUP -Name 'eng-admins'
        Links a piped domain to an LDAP group as domain admins.
    #>

    [CmdletBinding()]
    param([Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)][Alias('Id')][string]$DomainId, [Parameter(Mandatory=$true)][ValidateSet(0,2)][int]$AccountType, [Parameter(Mandatory=$true)][ValidateSet('GROUP','OU')][string]$Type, [string]$Admin, [string]$LdapDomain, [string]$Name)
    process {
        $apiParams = @{ domainid = $DomainId; accounttype = $AccountType; type = $Type }
        foreach ($key in @('Admin','LdapDomain','Name')) { if ($PSBoundParameters.ContainsKey($key)) { $apiParams[$key.ToLowerInvariant()] = (Get-Variable -Name $key -ValueOnly) } }
        Invoke-CSApiRequest -Command 'linkDomainToLdap' -Parameters $apiParams
    }
}

function Set-CSDomain {
    <#
    .SYNOPSIS
        Updates a domain's name or network domain.

    .DESCRIPTION
        Wraps the updateDomain API. Changes a domain's name and/or DNS network
        domain. Accepts a domain object (or its id) from the pipeline.

    .PARAMETER DomainId
        The domain UUID to update. Binds from a piped object's Id property.

    .PARAMETER Name
        New name for the domain.

    .PARAMETER NetworkDomain
        New DNS network domain for the domain's networks.

    .EXAMPLE
        Set-CSDomain -DomainId 'domain-uuid' -Name 'platform' -NetworkDomain 'platform.example.com'
        Renames a domain and sets its network domain.

    .EXAMPLE
        Get-CSDomain -Name 'engineering' | Set-CSDomain -NetworkDomain 'eng.example.com'
        Updates the network domain of a piped domain.
    #>

    [CmdletBinding()]
    param([Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true)][Alias('Id')][string]$DomainId, [string]$Name, [string]$NetworkDomain)
    process {
        $apiParams = @{ id = $DomainId }; if ($PSBoundParameters.ContainsKey('Name')) { $apiParams['name'] = $Name }; if ($PSBoundParameters.ContainsKey('NetworkDomain')) { $apiParams['networkdomain'] = $NetworkDomain }
        Invoke-CSApiRequest -Command 'updateDomain' -Parameters $apiParams
    }
}