PowervAA.psm1

<#
     _____ _____
    | __ \ | __ \ /\
    | |__) |____ _____ _ ____ _| |__) | / \
    | ___/ _ \ \ /\ / / _ \ '__\ \ / / _ / / /\ \
    | | | (_) \ V V / __/ | \ V /| | \ \ / ____ \
    |_| \___/ \_/\_/ \___|_| \_/ |_| \_\/_/ \_\
 
#>


# --- Clean up vRAConnection variable on module remove
$ExecutionContext.SessionState.Module.OnRemove = {

    Remove-Variable -Name vRAConnection -Force -ErrorAction SilentlyContinue

}
<#
    - Function: NewDynamicParam
#>


Function NewDynamicParam {
<#
    .SYNOPSIS
        Helper function to simplify creating dynamic parameters
     
    .DESCRIPTION
        Helper function to simplify creating dynamic parameters
 
        Example use cases:
            Include parameters only if your environment dictates it
            Include parameters depending on the value of a user-specified parameter
            Provide tab completion and intellisense for parameters, depending on the environment
 
        Please keep in mind that all dynamic parameters you create will not have corresponding variables created.
           One of the examples illustrates a generic method for populating appropriate variables from dynamic parameters
           Alternatively, manually reference $PSBoundParameters for the dynamic parameter value
 
    .NOTES
        Note: NewDynamicParam function from @PSCookieMonster https://github.com/RamblingCookieMonster/PowerShell/blob/master/New-DnamicParam.ps1
         
        Credit to http://jrich523.wordpress.com/2013/05/30/powershell-simple-way-to-add-dynamic-parameters-to-advanced-function/
            Added logic to make option set optional
            Added logic to add RuntimeDefinedParameter to existing DPDictionary
            Added a little comment based help
 
        Credit to BM for alias and type parameters and their handling
 
    .PARAMETER Name
        Name of the dynamic parameter
 
    .PARAMETER Type
        Type for the dynamic parameter. Default is string
 
    .PARAMETER Alias
        If specified, one or more aliases to assign to the dynamic parameter
 
    .PARAMETER ValidateSet
        If specified, set the ValidateSet attribute of this dynamic parameter
 
    .PARAMETER Mandatory
        If specified, set the Mandatory attribute for this dynamic parameter
 
    .PARAMETER ParameterSetName
        If specified, set the ParameterSet attribute for this dynamic parameter
 
    .PARAMETER Position
        If specified, set the Position attribute for this dynamic parameter
 
    .PARAMETER ValueFromPipelineByPropertyName
        If specified, set the ValueFromPipelineByPropertyName attribute for this dynamic parameter
 
    .PARAMETER HelpMessage
        If specified, set the HelpMessage for this dynamic parameter
     
    .PARAMETER DPDictionary
        If specified, add resulting RuntimeDefinedParameter to an existing RuntimeDefinedParameterDictionary (appropriate for multiple dynamic parameters)
        If not specified, create and return a RuntimeDefinedParameterDictionary (appropriate for a single dynamic parameter)
 
        See final example for illustration
 
    .EXAMPLE
         
        function Show-Free
        {
            [CmdletBinding()]
            Param()
            DynamicParam {
                $options = @( gwmi win32_volume | %{$_.driveletter} | sort )
                NewDynamicParam -Name Drive -ValidateSet $options -Positin 0 -Mandatory
            }
            begin{
                #have to manually populate
                $drive = $PSBoundParameters.drive
            }
            process{
                $vol = gwmi win32_volume -Filter "driveletter='$drive'"
                "{0:N2}% free on {1}" -f ($vol.Capacity / $vol.FreeSpace),$drive
            }
        } #Show-Free
 
        Show-Free -Drive <tab>
 
    # This example illustrates the use of NewDynamicParam to create a single dyamic parameter
    # The Drive parameter ValidateSet populates with all available volumes on the computer for handy tab completion / intellisense
 
    .EXAMPLE
 
    # I found many cases where I needed to add more than one dynamic parameter
    # The DPDictionary parameter lets you specify an existing dictionary
    # The block of code in the Begin block loops through bound parameters and defines variables if they don't exist
 
        Function Test-DynPar{
            [cmdletbinding()]
            param(
                [string[]]$x = $Null
            )
            DynamicParam
            {
                #Create the RuntimeDefinedParameterDictionary
                $Dictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
         
                NewDynamicParam -Name AlwaysParam -ValidateSet @( gwmi win32_volume | %{$_.driveletter} | sort ) -DPDictionry $Dictionary
 
                #Add dynamic parameters to $dictionary
                if($x -eq 1)
                {
                    NewDynamicParam -Name X1Param1 -ValidateSet 1,2 -mandatory -DPDictionry $Dictionary
                    NewDynamicParam -Name X1Param2 -DPDictionry $Dictionary
                    NewDynamicParam -Name X3Param3 -DPDictionary $Dictionary-Type DateTime
                }
                else
                {
                    NewDynamicParam -Name OtherParam1 -Mandatory -DPDictionry $Dictionary
                    NewDynamicParam -Name OtherParam2 -DPDictionry $Dictionary
                    NewDynamicParam -Name OtherParam3 -DPDictionary $Dictionary-Type DateTime
                }
         
                #return RuntimeDefinedParameterDictionary
                $Dictionary
            }
            Begin
            {
                #This standard block of code loops through bound parameters...
                #If no corresponding variable exists, one is created
                    #Get common parameters, pick out bound parameters not in that set
                    Function intTemp { [cmdletbinding()] param() }
                    $BoundKeys = $PSBoundParameters.keys | Where-Object { (get-command intTemp | select -ExpandProperty parameters).Keys -notcontains $_}
                    foreach($param in $BoundKeys)
                    {
                        if (-not ( Get-Variable -name $param -scope 0 -ErrorAction SilentlyContinue ) )
                        {
                            New-Variable -Name $Param -Value $PSBoundParameters.$param
                            Write-Verbose "Adding variable for dynamic parameter '$param' with value '$($PSBoundParameters.$param)'"
                        }
                    }
 
                #Appropriate variables should now be defined and accessible
                    Get-Variable -scope 0
            }
        }
 
    # This example illustrates the creation of many dynamic parameters using Nw-DynamicParam
        # You must create a RuntimeDefinedParameterDictionary object ($dictionary here)
        # To each NewDynamicParam call, add the -DPDictionary parameter pointing to this RuntimeDefinedParaeterDictionary
        # At the end of the DynamicParam block, return the RuntimeDefinedParameterDictionary
        # Initialize all bound parameters using the provided block or similar code
 
    .FUNCTIONALITY
        PowerShell Language
 
#>

param(
    
    [string]
    $Name,
    
    [System.Type]
    $Type = [string],

    [string[]]
    $Alias = @(),

    [string[]]
    $ValidateSet,
    
    [switch]
    $Mandatory,
    
    [string]
    $ParameterSetName="__AllParameterSets",
    
    [int]
    $Position,
    
    [switch]
    $ValueFromPipelineByPropertyName,
    
    [string]
    $HelpMessage,

    [validatescript({
        if(-not ( $_ -is [System.Management.Automation.RuntimeDefinedParameterDictionary] -or -not $_) )
        {
            Throw "DPDictionary must be a System.Management.Automation.RuntimeDefinedParameterDictionary object, or not exist"
        }
        $True
    })]
    $DPDictionary = $false
 
)
    #Create attribute object, add attributes, add to collection
        $ParamAttr = New-Object System.Management.Automation.ParameterAttribute
        $ParamAttr.ParameterSetName = $ParameterSetName
        if($mandatory)
        {
            $ParamAttr.Mandatory = $True
        }
        if($Position -ne $null)
        {
            $ParamAttr.Position=$Position
        }
        if($ValueFromPipelineByPropertyName)
        {
            $ParamAttr.ValueFromPipelineByPropertyName = $True
        }
        if($HelpMessage)
        {
            $ParamAttr.HelpMessage = $HelpMessage
        }
 
        $AttributeCollection = New-Object 'Collections.ObjectModel.Collection[System.Attribute]'
        $AttributeCollection.Add($ParamAttr)
    
    #param validation set if specified
        if($ValidateSet)
        {
            $ParamOptions = New-Object System.Management.Automation.ValidateSetAttribute -ArgumentList $ValidateSet
            $AttributeCollection.Add($ParamOptions)
        }

    #Aliases if specified
        if($Alias.count -gt 0) {
            $ParamAlias = New-Object System.Management.Automation.AliasAttribute -ArgumentList $Alias
            $AttributeCollection.Add($ParamAlias)
        }

 
    #Create the dynamic parameter
        $Parameter = New-Object -TypeName System.Management.Automation.RuntimeDefinedParameter -ArgumentList @($Name, $Type, $AttributeCollection)
    
    #Add the dynamic parameter to an existing dynamic parameter dictionary, or create the dictionary and add it
        if($DPDictionary)
        {
            $DPDictionary.Add($Name, $Parameter)
        }
        else
        {
            $Dictionary = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary
            $Dictionary.Add($Name, $Parameter)
            $Dictionary
        }
}

<#
    - Function: xRequires
#>


function xRequires {
<#
    .SYNOPSIS
    Checks the required API Version for the current function
 
    .DESCRIPTION
    Checks the required API Version for the current function
 
    .PARAMETER Version
    The API Version that the function supports.
 
    The version number passed to this parameter must be in the following format.. it can't be a single character.
 
    - 6.2.4
    - 7.0
    - 7.0.1
    - 7.1
    - 7.2
 
    .INPUTS
    System.Int
    System.Management.Automation.PSObject.
 
    .OUTPUTS
    None
 
    .EXAMPLE
 
    function Get-Example {
 
        # This function does not support API versions lower than Version 7
        xRequires -Version "7.0"
 
    }
 
#>


[CmdletBinding()][Alias("FunctionRequires")]
    Param (
        [Parameter(Mandatory=$true, Position=0)]
        [String]$Version
    )

    # --- Test for vRA API version
    if (-not $Script:vRAConnection){
        throw "vRA Connection variable does not exist. Please run Connect-vAAServer first to create it"
    }

    # --- Convert version strings to [version] objects
    $APIVersion = [version]$Script:vRAConnection.APIVersion
    $RequiredVersion = [version]$Version

    if ($APIVersion -lt $RequiredVersion) {
        $PSCallStack = Get-PSCallStack
        Write-Error -Message "$($PSCallStack[1].Command) is not supported with vRA API version $($Script:vRAConnection.APIVersion)"
        break
    }
}

<#
    - Function: Connect-vAAServer
#>


function Connect-vAAServer {
    <#
        .SYNOPSIS
        Connect to a vRA Server
 
        .DESCRIPTION
        Connect to a vRA Server and generate a connection object with Servername, Token etc
 
        .PARAMETER Server
        vRA Server to connect to
 
        .PARAMETER Username
        Username to connect with
        For domain accounts ensure to specify the Username in the format username@domain, not Domain\Username
 
        .PARAMETER Password
        Password to connect with
 
        .PARAMETER Credential
        Credential object to connect with
        For domain accounts ensure to specify the Username in the format username@domain, not Domain\Username
 
        .PARAMETER APIToken
        API Token to connect with
 
        .PARAMETER IgnoreCertRequirements
        Ignore requirements to use fully signed certificates
 
        .PARAMETER SslProtocol
        Alternative Ssl protocol to use from the default
        Requires vRA 7.x and above
        Windows PowerShell: Ssl3, Tls, Tls11, Tls12
        PowerShell Core: Tls, Tls11, Tls12
 
        .INPUTS
        System.String
        Switch
 
        .OUTPUTS
        System.Management.Automation.PSObject.
 
        .EXAMPLE
        $cred = Get-Credential
        Connect-vAAServer -Server vraappliance01.domain.local -Credential $cred
 
        .EXAMPLE
        $SecurePassword = ConvertTo-SecureString “P@ssword” -AsPlainText -Force
        Connect-vAAServer -Server vraappliance01.domain.local -Username TenantAdmin01@domain.com -Password $SecurePassword -IgnoreCertRequirements
 
        .EXAMPLE
        Connect-vAAServer -Server api.mgmt.cloud.vmware.com -APIToken 'CuIKrjQgI6htiyRgIyd0ZtQM91fqg6AQyQhwPFJYgzBsaIKxKcWHLAGk81kknulQ'
 
        .EXAMPLE
        Connect-vAAServer -Server vraappliance01.domain.local -APIToken 'CuIKrjQgI6htiyRgIyd0ZtQM91fqg6AQyQhwPFJYgzBsaIKxKcWHLAGk81kknulQ' -IgnoreCertRequirements
    #>

    [CmdletBinding(DefaultParameterSetName="Username")][OutputType('System.Management.Automation.PSObject')]

        Param (

            [parameter(Mandatory=$true)]
            [ValidateNotNullOrEmpty()]
            [String]$Server,

            [parameter(Mandatory=$true,ParameterSetName="Username")]
            [ValidateNotNullOrEmpty()]
            [String]$Username,

            [parameter(Mandatory=$true,ParameterSetName="Username")]
            [ValidateNotNullOrEmpty()]
            [SecureString]$Password,

            [Parameter(Mandatory=$true,ParameterSetName="Credential")]
            [ValidateNotNullOrEmpty()]
            [Management.Automation.PSCredential]$Credential,

            [parameter(Mandatory=$true,ParameterSetName="APIToken")]
            [ValidateNotNullOrEmpty()]
            [String]$APIToken,

            [parameter(Mandatory=$false)]
            [Switch]$IgnoreCertRequirements,

            [parameter(Mandatory=$false)]
            [ValidateSet('Ssl3', 'Tls', 'Tls11', 'Tls12')]
            [String]$SslProtocol
        )

        Process {
            # --- Handle untrusted certificates if necessary
            $SignedCertificates = $true

            if ($IgnoreCertRequirements.IsPresent){

                if (!$IsCoreCLR) {

                    if ( -not ("TrustAllCertsPolicy" -as [type])) {

                        Add-Type @"
                        using System.Net;
                        using System.Security.Cryptography.X509Certificates;
                        public class TrustAllCertsPolicy : ICertificatePolicy {
                            public bool CheckValidationResult(
                                ServicePoint srvPoint, X509Certificate certificate,
                                WebRequest request, int certificateProblem) {
                                return true;
                            }
                        }
"@

                    }
                    [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy

                }

                $SignedCertificates = $false

            }

            # --- Security Protocol
            $SslProtocolResult = 'Default'

            if ($PSBoundParameters.ContainsKey("SslProtocol") ){

                if (!$IsCoreCLR) {

                    $CurrentProtocols = ([System.Net.ServicePointManager]::SecurityProtocol).toString() -split ', '
                    if (!($SslProtocol -in $CurrentProtocols)){

                        [System.Net.ServicePointManager]::SecurityProtocol += [System.Net.SecurityProtocolType]::$($SslProtocol)
                    }
                }
                $SslProtocolResult = $SslProtocol
            }

            try {

                # --- if a refresh token is supplied, we use iaas login
                if ($PSBoundParameters.ContainsKey("APIToken")){
                    # -- iaas login with refresh token
                    $URI = "https://$($Server)/iaas/login"

                    # --- Create Invoke-RestMethod Parameters
                    $RawBody = @{
                        refreshToken = $APIToken
                    }
                } else {
                    # --- Convert Secure Credentials to a format for sending in the JSON payload
                    if ($PSBoundParameters.ContainsKey("Credential")){

                        $Username = $Credential.UserName
                        $JSONPassword = $Credential.GetNetworkCredential().Password
                    }

                    if ($PSBoundParameters.ContainsKey("Password")){

                        $JSONPassword = (New-Object System.Management.Automation.PSCredential("username", $Password)).GetNetworkCredential().Password
                    }

                    # --- Test for a '\' in the username, e.g. DOMAIN\Username, not supported by the API
                    if ($Username -match '\\'){

                        throw "The Username format DOMAIN\Username is not supported by the vRA REST API. Please use username@domain instead"
                    }

                    # --- Logging in with a domain
                    $URI = "https://$($Server)/csp/gateway/am/api/login?access_token"
                    if ($Username -match '@') {
                        # Log in using the advanced authentication API
                        $User = $Username.split('@')[0]
                        $Domain = $Username.split('@')[1]
                        $RawBody = @{
                            username = $User
                            password = $JSONPassword
                            domain = $Domain
                        }
                    } else {
                        # -- Login with the basic authentication API
                        # -- We assume local account which can use the advanced authentication API with domain set to 'System Domain'
                        # --- Create Invoke-RestMethod Parameters
                        $RawBody = @{
                            username = $Username
                            password = $JSONPassword
                            domain = "System Domain"
                        }
                    }
                }

                $Params = @{

                    Method = "POST"
                    URI = $URI
                    Headers = @{
                        "Accept"="application/json";
                        "Content-Type" = "application/json";
                    }
                    Body = $RawBody | ConvertTo-Json

                }

                if ((!$SignedCertificates) -and ($IsCoreCLR)) {

                    $Params.Add("SkipCertificateCheck", $true)

                }

                if (($SslProtocolResult -ne 'Default') -and ($IsCoreCLR)) {

                    $Params.Add("SslProtocol", $SslProtocol)

                }

                # Here we try with the first set of params, if it fails, it may be due to another configuration
                # so we try again with the alternative option if available
                try {
                    $Response = Invoke-RestMethod @Params
                } catch [System.Net.WebException]{
                    if ($_.Exception.Response.StatusCode -eq "BadRequest") {
                        $RawBody.username = $Username
                        $Params.Body = $RawBody | ConvertTo-Json
                        $Response = Invoke-RestMethod @Params
                    } else {
                        throw $_
                    }
                }

                if ('token' -in $Response.PSobject.Properties.Name) {
                    $Token = $Response.token
                }

                # Ony try this for the on-premises vRA version
                if ($Server -ne 'api.mgmt.cloud.vmware.com'){

                    if ('refresh_token' -in $Response.PSobject.Properties.Name) {
                        $RefreshToken = $Response.refresh_token
                    }

                    # now we need to login via the iaas api as well with the refresh token
                    $IaasParams = @{
                        Method = "POST"
                        URI = "https://$($Server)/iaas/api/login"
                        Headers = @{
                            "Accept"="application/json";
                            "Content-Type" = "application/json";
                        }
                        Body = @{
                            refreshToken = $RefreshToken
                        } | ConvertTo-Json
                    }


                    if ((!$SignedCertificates) -and ($IsCoreCLR)) {

                        $IaasParams.Add("SkipCertificateCheck", $true)

                    }

                    if (($SslProtocolResult -ne 'Default') -and ($IsCoreCLR)) {

                        $IaasParams.Add("SslProtocol", $SslProtocol)

                    }

                    $IaasResponse = Invoke-RestMethod @IaasParams

                    if ('token' -in $IaasResponse.PSobject.Properties.Name) {
                        $Token = $IaasResponse.token
                    }
                }

                # --- Create Output Object
                $Script:vRAConnection = [PSCustomObject] @{

                    Server = "https://$($Server)"
                    Token = $Token
                    RefreshToken = $RefreshToken
                    APIVersion = $Null
                    SignedCertificates = $SignedCertificates
                    SslProtocol = $SslProtocolResult
                }

                # --- Update vRAConnection with API version
                $Script:vRAConnection.APIVersion = (Get-vAAAPIVersion).APIVersion

            }
            catch [Exception]{

                throw

            }

            Write-Output $vRAConnection
    }
}


<#
    - Function: Disconnect-vAAServer
#>


function Disconnect-vAAServer {
<#
    .SYNOPSIS
    Disconnect from a vRA server
 
    .DESCRIPTION
    Disconnect from a vRA server by removing the authorization token and the vRAConnection script variable from PowerShell
 
    .EXAMPLE
    Disconnect-vAAServer
 
    .EXAMPLE
    Disconnect-vAAServer -Confirm:$false
#>

[CmdletBinding(SupportsShouldProcess,ConfirmImpact="High")]

    Param ()

    # --- Test for existing connection to vRA
    if (-not $Script:vRAConnection){

        throw "vRA Connection variable does not exist. Please run Connect-vAAServer first to create it"
    }

    if ($PSCmdlet.ShouldProcess($Script:vRAConnection.Server)){

        try {

            # --- Remove custom Security Protocol if it has been specified
            if ($Script:vRAConnection.SslProtocol -ne 'Default'){

                if (!$IsCoreCLR) {

                    [System.Net.ServicePointManager]::SecurityProtocol -= [System.Net.SecurityProtocolType]::$($Script:vRAConnection.SslProtocol)
                }
            }

        }
        catch [Exception]{

            throw

        }
        finally {

            # --- Remove the vRAConnection script variable
            Write-Verbose -Message "Removing vRAConnection script variable"
            Remove-Variable -Name vRAConnection -Scope Script -Force -ErrorAction SilentlyContinue
        }
    }
}

<#
    - Function: Invoke-vAARestMethod
#>


function Invoke-vAARestMethod {
<#
    .SYNOPSIS
    Wrapper for Invoke-RestMethod/Invoke-WebRequest with vRA specifics
 
    .DESCRIPTION
    Wrapper for Invoke-RestMethod/Invoke-WebRequest with vRA specifics
 
    .PARAMETER Method
    REST Method:
    Supported Methods: GET, PATCH, POST, PUT, DELETE
 
    .PARAMETER URI
    API URI, e.g. /identity/api/tenants
 
    .PARAMETER Headers
    Optionally supply custom headers
 
    .PARAMETER Body
    REST Body in JSON format
 
    .PARAMETER OutFile
    Save the results to a file
 
    .PARAMETER WebRequest
    Use Invoke-WebRequest rather than the default Invoke-RestMethod
 
    .INPUTS
    System.String
    Switch
 
    .OUTPUTS
    System.Management.Automation.PSObject
 
    .EXAMPLE
    Invoke-vAARestMethod -Method GET -URI '/iaas/api/about'
 
    .EXAMPLE
    $JSON = @"
        {
            "name": "TestOnboardingPlan",
            "endpointId": "42fe38765a63bd755921a88814a14",
            "projectId": "9f732951-2279-422a-8045-9b254d427100"
        }
    "@
 
    Invoke-vAARestMethod -Method POST -URI '/relocation/onboarding/plan' -Body $JSON -WebRequest
#>

[CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true, ParameterSetName="Standard")]
        [Parameter(Mandatory=$true, ParameterSetName="Body")]
        [Parameter(Mandatory=$true, ParameterSetName="OutFile")]
        [ValidateSet("GET","PATCH","POST","PUT","DELETE")]
        [String]$Method,

        [Parameter(Mandatory=$true, ParameterSetName="Standard")]
        [Parameter(Mandatory=$true, ParameterSetName="Body")]
        [Parameter(Mandatory=$true, ParameterSetName="OutFile")]
        [ValidateNotNullOrEmpty()]
        [String]$URI,

        [Parameter(Mandatory=$false, ParameterSetName="Standard")]
        [Parameter(Mandatory=$false, ParameterSetName="Body")]
        [Parameter(Mandatory=$false, ParameterSetName="OutFile")]
        [ValidateNotNullOrEmpty()]
        [System.Collections.IDictionary]$Headers,

        [Parameter(Mandatory=$false, ParameterSetName="Body")]
        [ValidateNotNullOrEmpty()]
        [String]$Body,

        [Parameter(Mandatory=$false, ParameterSetName="OutFile")]
        [ValidateNotNullOrEmpty()]
        [String]$OutFile,

        [Parameter(Mandatory=$false, ParameterSetName="Standard")]
        [Parameter(Mandatory=$false, ParameterSetName="Body")]
        [Parameter(Mandatory=$false, ParameterSetName="OutFile")]
        [Switch]$WebRequest
    )

    # --- Test for existing connection to vRA
    if (-not $Script:vRAConnection){

        throw "vRA Connection variable does not exist. Please run Connect-vAAServer first to create it"
    }

    # --- Create Invoke-RestMethod Parameters
    $FullURI = "$($Script:vRAConnection.Server)$($URI)"

    # --- Add default headers if not passed
    if (!$PSBoundParameters.ContainsKey("Headers")){

        $Headers = @{

            "Accept"="application/json";
            "Content-Type" = "application/json";
            "Authorization" = "Bearer $($Script:vRAConnection.Token)";
        }
    }

    # --- Set up default parmaeters
    $Params = @{

        Method = $Method
        Headers = $Headers
        Uri = $FullURI
    }

    if ($PSBoundParameters.ContainsKey("Body")) {

        $Params.Add("Body", $Body)

        # --- Log the payload being sent to the server
        Write-Debug -Message $Body

    } elseif ($PSBoundParameters.ContainsKey("OutFile")) {

        $Params.Add("OutFile", $OutFile)

    }

    # --- Support for PowerShell Core certificate checking
    if (!($Script:vRAConnection.SignedCertificates) -and ($IsCoreCLR)) {

        $Params.Add("SkipCertificateCheck", $true);
    }

    # --- Support for PowerShell Core SSL protocol checking
    if (($Script:vRAConnection.SslProtocol -ne 'Default') -and ($IsCoreCLR)) {

        $Params.Add("SslProtocol", $Script:vRAConnection.SslProtocol);
    }

    try {

        # --- Use either Invoke-WebRequest or Invoke-RestMethod
        if ($WebRequest.IsPresent) {

            Invoke-WebRequest @Params
        }
        else {
            $Page = 0
            Do {
                $Result = Invoke-RestMethod @Params
                Write-Output $Result

                # Check if endpoint supports pagination
                $Properties = $Result | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name
                If ($Properties -contains "last")
                {
                    If (-not $Result.last)
                    {
                        $Page ++
                        # Check if parameter is already specified in Uri
                        $AddParam = "?"
                        If ($FullURI -match "\?")
                        {
                            $AddParam = "&"
                        }
                        $Params.Uri = "$($FullURI)$($AddParam)page=$Page"
                    }
                    Else
                    {
                        $Escape = $true
                    }
                }
                Else
                {
                    $Escape = $true
                }
            } Until ($Escape)
        }
    }
    catch {

        throw $_
    }
    finally {

        if (!$IsCoreCLR) {

            <#
                Workaround for bug in Invoke-RestMethod. Thanks to the PowerNSX guys for pointing this one out
                https://bitbucket.org/nbradford/powernsx/src
            #>

            $ServicePoint = [System.Net.ServicePointManager]::FindServicePoint($FullURI)
            $ServicePoint.CloseConnectionGroup("") | Out-Null
        }
    }
}

<#
    - Function: Get-vAABlueprint
#>


function Get-vAABlueprint {
    <#
        .SYNOPSIS
        Get a vRA Blueprint
     
        .DESCRIPTION
        Get a vRA Blueprint
     
        .PARAMETER Id
        The ID of the Blueprint
     
        .PARAMETER Name
        The Name of the Blueprint
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAABlueprint
     
        .EXAMPLE
        Get-vAABlueprint -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAABlueprint -Name 'TestBlueprint'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/blueprint/api/blueprints'
    
            function CalculateOutput([PSCustomObject]$Blueprint) {
    
                [PSCustomObject] @{
                    Name = $Blueprint.name
                    Content = $Blueprint.content
                    Id = $Blueprint.id
                    CreatedAt = $Blueprint.createdAt
                    CreatedBy = $Blueprint.createdBy
                    UpdatedAt = $Blueprint.updatedAt
                    UpdatedBy = $Blueprint.updatedBy
                    OrgId = $Blueprint.orgId
                    ProjectId = $Blueprint.projectId
                    ProjectName = $Blueprint.projectName
                    Description = $Blueprint.description
                    Status = $Blueprint.status
                    TotalVersions = $Blueprint.totalVersions
                    TotalReleasedVersions = $Blueprint.totalReleasedVersions
                    RequestScopeOrg = $Blueprint.requestScopeOrg
                    Valid = $Blueprint.valid
                    ValidationMessages = $Blueprint.validationMessages
                    ContentSourceSyncMessages = $Blueprint.contentSourceSyncMessages
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get Blueprint by Id
                    'ById' {
    
                        foreach ($BlueprintId in $Id){
    
                            $URI = "$($APIUrl)/$($BlueprintId)"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach($Blueprint in $Response){
                                CalculateOutput $Blueprint
                            }
                        }
    
                        break
                    }
                    # --- Get Blueprint by Name
                    'ByName' {
    
                        foreach ($BlueprintName in $Name){
    
                            $URI = "$($APIUrl)"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($Blueprint in $Response.content) {
                                if($Blueprint.name -eq $BlueprintName){
                                    # Get individual blueprint link
                                    $BlueprintSelfLink = $blueprint.selfLink

                                    # Get full blueprint resource info
                                    $FullBlueprints = Invoke-vAARestMethod -Method GET -URI $BlueprintSelfLink -Verbose:$VerbosePreference
                                    foreach ($FullBlueprint in $FullBlueprints){
                                        CalculateOutput $FullBlueprint
                                    }
                                }
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all Blueprints
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($Blueprint in $Response.content) {
                            # Get individual blueprint link
                            $BlueprintSelfLink = $blueprint.selfLink

                            # Get full blueprint resource info
                            $FullBlueprints = Invoke-vAARestMethod -Method GET -URI $BlueprintSelfLink -Verbose:$VerbosePreference
                            foreach ($FullBlueprint in $FullBlueprints){
                                CalculateOutput $FullBlueprint
                            }
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: Get-vAABlueprintVersion
#>


function Get-vAABlueprintVersion {
    <#
        .SYNOPSIS
        Get a vRA Blueprint's Versions
     
        .DESCRIPTION
        Get a vRA Blueprint's Versions
     
        .PARAMETER Blueprint
        The vRA Blueprint object as returned by Get-vAABlueprint
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAABlueprint | Get-vAABlueprintVersion
     
        .EXAMPLE
        Get-vAABlueprintVersion -Blueprint (Get-vAABlueprint -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9')
     
        .EXAMPLE
        Get-vAABlueprintVersion -Blueprint (Get-vAABlueprint -Name 'TestBlueprint')
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="Blueprint")]
            [ValidateNotNullOrEmpty()]
            [PSCustomObject[]]$Blueprint
        )
    
        begin {
            $APIUrl = '/blueprint/api/blueprints'
    
            function CalculateOutput([PSCustomObject]$BlueprintVersion) {
    
                [PSCustomObject] @{
                    Id = $BlueprintVersion.id
                    CreatedAt = $BlueprintVersion.createdAt
                    CreatedBy = $BlueprintVersion.createdBy
                    UpdatedAt = $BlueprintVersion.updatedAt
                    UpdatedBy = $BlueprintVersion.updatedBy
                    OrganizationId = $BlueprintVersion.orgId
                    ProjectId = $BlueprintVersion.projectId
                    ProjectName = $BlueprintVersion.projectName
                    SelfLink = $BlueprintVersion.selfLink
                    BlueprintId = $BlueprintVersion.blueprintId
                    Name = $BlueprintVersion.name
                    Description = $BlueprintVersion.description
                    Version = $BlueprintVersion.version
                    Status = $BlueprintVersion.status
                    VersionDescription = $BlueprintVersion.versionDescription
                    VersionChangeLog = $BlueprintVersion.versionChangeLog
                    Valid = $BlueprintVersion.valid
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get BlueprintVersion from Blueprint object
                    'Blueprint' {
    
                        foreach ($Blueprintobj in $Blueprint){
    
                            $URI = "$($APIUrl)/$($Blueprintobj.Id)/versions"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
                            
                            foreach($version in $Response.content){
                                CalculateOutput $version
                            }
                        }
    
                        break
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: Get-vAACatalogItem
#>


function Get-vAACatalogItem {
    <#
        .SYNOPSIS
        Get a vRA Catalog Item
     
        .DESCRIPTION
        Get a vRA Catalog Item
     
        .PARAMETER Id
        The ID of the Catalog Item
     
        .PARAMETER Name
        The Name of the Catalog Item
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAACatalogItem
     
        .EXAMPLE
        Get-vAACatalogItem -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAACatalogItem -Name 'TestCatalogItem'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/catalog/api/items'
    
            function CalculateOutput([PSCustomObject]$CatalogItem) {
    
                [PSCustomObject] @{
                    Id = $CatalogItem.id
                    Name = $CatalogItem.name
                    Description = $CatalogItem.description
                    Type = $CatalogItem.type
                    ProjectIds = $CatalogItem.projectIds
                    CreatedAt = $CatalogItem.createdAt
                    CreatedBy = $CatalogItem.createdBy
                    LastUpdatedAt = $CatalogItem.lastUpdatedAt
                    LastUpdatedBy = $CatalogItem.lastUpdatedBy
                    IconId = $CatalogItem.iconId
                    BulkRequestLimit = $CatalogItem.bulkRequestLimit
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get Catalog Item by Id
                    'ById' {
    
                        foreach ($CatalogItemId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($CatalogItemId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($CatalogItem in $Response.content) {
    
                                CalculateOutput $CatalogItem
                            }
                        }
    
                        break
                    }
                    # --- Get Catalog Item by Name
                    'ByName' {
    
                        foreach ($CatalogItemName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($CatalogItemName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($CatalogItem in $Response.content){
    
                                CalculateOutput $CatalogItem
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all Catalog Items
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                        foreach ($CatalogItem in $Response.content){
    
                            CalculateOutput $CatalogItem
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: Get-vAACodeStreamExecution
#>


function Get-vAACodeStreamExecution {
<#
    .SYNOPSIS
    Retrieve vRA Code Stream Execution depending on input
 
    .DESCRIPTION
    Retrieve a list of vRA Code Stream Executions or a single Execution depending on input
 
    .PARAMETER Id
    The ID of the vRA Code Stream Execution
 
    .PARAMETER Pipeline
    The name of the Pipeline of the vRA Code Stream Execution
 
    .PARAMETER Project
    The name of the Project of the vRA Code Stream Execution
 
    .OUTPUTS
    System.Management.Automation.PSObject.
 
    .EXAMPLE
    Get-vAACodeStreamExecution
 
    .EXAMPLE
    Get-vAACodeStreamExecution -Id '96afe0f9-a2ac-4468-8671-a2ca6fdbca37'
 
    .EXAMPLE
    Get-vAACodeStreamExecution -Pipeline 'My Pipeline'
 
    .EXAMPLE
    Get-vAACodeStreamExecution -Project 'My Project'
 
#>

[CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Pipeline,

        [Parameter(Mandatory=$true,ParameterSetName="ByProject")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Project

    )
    Begin {

        $APIUrl = "/pipeline/api/executions"

        function CalculateOutput($ResponseObject) {
            foreach ($Record in $ResponseObject.documents.PsObject.Properties) {
                [PSCustomObject]@{
                    Name = $Record.value.name+" #"+$Record.value.index
                    Project = $Record.value.project
                    Id = $Record.value.id
                    LastUpdated = $Record.value.updatedAt
                    Status = $Record.value.status
                    StatusMessage = $Record.value.statusMessage
                    ExecutedBy = $Record.value._executedBy
                }
            }
        }
    }
    Process {

        try {

            switch ($PsCmdlet.ParameterSetName) {

                # --- Get Execution by its id
                'ById' {
                    foreach ($ExecutionId in $Id) {
                        $Response = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=id eq '$ExecutionId'" -Method GET
                        CalculateOutput $Response
                    }

                    break
                }

                # --- Get Execution by its pipeline name
                'ByName' {
                    foreach ($PipelineName in $Pipeline) {
                        $Response = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$PipelineName'" -Method GET
                        CalculateOutput $Response
                    }

                    break
                }

                # --- Get Execution by its project name
                'ByProject' {
                    foreach ($ProjectName in $Project) {
                        $Response = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=project eq '$ProjectName'" -Method GET
                        CalculateOutput $Response
                    }

                    break
                }

                # --- No parameters passed so return all executions
                'Standard' {
                    $Response = Invoke-vAARestMethod -URI $APIUrl -Method GET
                    CalculateOutput $Response
                }

            }


        }
        catch [Exception]{

            throw
        }
    }
    End {

    }
}


<#
    - Function: Get-vAACodeStreamPipeline
#>


function Get-vAACodeStreamPipeline {
<#
    .SYNOPSIS
    Retrieve vRA Code Stream Pipeline depending on input
 
    .DESCRIPTION
    Retrieve a list of vRA Code Stream Pipelines or a single Pipeline depending on input
 
    .PARAMETER Id
    The ID of the vRA Code Stream Pipeline
 
    .PARAMETER Pipeline
    The name of the Pipeline of the vRA Code Stream Pipeline
 
    .PARAMETER Project
    The name of the Project of the vRA Code Stream Pipeline
 
    .OUTPUTS
    System.Management.Automation.PSObject.
 
    .EXAMPLE
    Get-vAACodeStreamPipeline
 
    .EXAMPLE
    Get-vAACodeStreamPipeline -Id '96afe0f9-a2ac-4468-8671-a2ca6fdbca37'
 
    .EXAMPLE
    Get-vAACodeStreamPipeline -Pipeline 'My Pipeline'
 
    .EXAMPLE
    Get-vAACodeStreamPipeline -Project 'My Project'
 
#>

[CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Pipeline,

        [Parameter(Mandatory=$true,ParameterSetName="ByProject")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Project

    )
    Begin {

        $APIUrl = "/pipeline/api/pipelines"

        function CalculateOutput($ResponseObject) {
            foreach ($Record in $ResponseObject.documents.PsObject.Properties) {
                [PSCustomObject]@{
                    Name = $Record.value.name
                    Project = $Record.value.project
                    Id = $Record.value.id
                    LastUpdated = $Record.value.updatedAt
                    UpdatedBy = $Record.value._updatedBy
                    State = $Record.value.state
                }
            }
        }
    }
    Process {

        try {

            switch ($PsCmdlet.ParameterSetName) {

                # --- Get Pipeline by its id
                'ById' {
                    foreach ($PipelineId in $Id) {
                        $Response = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=id eq '$PipelineId'" -Method GET
                        CalculateOutput $Response
                    }

                    break
                }

                # --- Get Pipeline by its pipeline name
                'ByName' {
                    foreach ($PipelineName in $Pipeline) {
                        $Response = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$PipelineName'" -Method GET
                        CalculateOutput $Response
                    }

                    break
                }

                # --- Get Pipeline by its project name
                'ByProject' {
                    foreach ($ProjectName in $Project) {
                        $Response = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=project eq '$ProjectName'" -Method GET
                        CalculateOutput $Response
                    }

                    break
                }

                # --- No parameters passed so return all Pipelines
                'Standard' {
                    $Response = Invoke-vAARestMethod -URI $APIUrl -Method GET
                    CalculateOutput $Response
                }

            }


        }
        catch [Exception]{

            throw
        }
    }
    End {

    }
}


<#
    - Function: Get-vAACodeStreamVariable
#>


function Get-vAACodeStreamVariable {
<#
    .SYNOPSIS
    Retrieve vRA Code Stream Variable depending on input
 
    .DESCRIPTION
    Retrieve a list of vRA Code Stream Variables or a single Variable depending on input
 
    .PARAMETER Id
    The ID of the vRA Code Stream Variable
 
    .PARAMETER Variable
    The name of the Variable of the vRA Code Stream Variable
 
    .PARAMETER Project
    The name of the Project of the vRA Code Stream Variable
 
    .OUTPUTS
    System.Management.Automation.PSObject.
 
    .EXAMPLE
    Get-vAACodeStreamVariable
 
    .EXAMPLE
    Get-vAACodeStreamVariable -Id '96afe0f9-a2ac-4468-8671-a2ca6fdbca37'
 
    .EXAMPLE
    Get-vAACodeStreamVariable -Variable 'My Variable'
 
    .EXAMPLE
    Get-vAACodeStreamVariable -Project 'My Project'
 
#>

[CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Variable,

        [Parameter(Mandatory=$true,ParameterSetName="ByProject")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Project

    )
    Begin {

        $APIUrl = "/pipeline/api/variables"

        function CalculateOutput($ResponseObject) {
            foreach ($Record in $ResponseObject.documents.PsObject.Properties) {
                [PSCustomObject]@{
                    Name = $Record.value.name
                    Project = $Record.value.project
                    Id = $Record.value.id
                    Type = $Record.value.type
                    LastUpdated = $Record.value.updatedAt
                    CreatedBy = $Record.value._createdBy
                    Value = $Record.value.value
                }
            }
        }
    }
    Process {

        try {

            switch ($PsCmdlet.ParameterSetName) {

                # --- Get Variable by its id
                'ById' {
                    foreach ($VariableId in $Id) {
                        $Response = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=id eq '$VariableId'" -Method GET
                        CalculateOutput $Response
                    }

                    break
                }

                # --- Get Variable by its name
                'ByName' {
                    foreach ($VariableName in $Variable) {
                        $Response = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$VariableName'" -Method GET
                        CalculateOutput $Response
                    }

                    break
                }

                # --- Get Variable by its project name
                'ByProject' {
                    foreach ($ProjectName in $Project) {
                        $Response = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=project eq '$ProjectName'" -Method GET
                        CalculateOutput $Response
                    }

                    break
                }

                # --- No parameters passed so return all Variables
                'Standard' {
                    $Response = Invoke-vAARestMethod -URI $APIUrl -Method GET
                    CalculateOutput $Response
                }

            }


        }
        catch [Exception]{

            throw
        }
    }
    End {

    }
}


<#
    - Function: Remove-vAACodeStreamExecution
#>


function Remove-vAACodeStreamExecution {
    <#
        .SYNOPSIS
        Remove a vRA Code Stream Execution
 
        .DESCRIPTION
        Remove a vRA Code Stream Execution
 
        .PARAMETER Id
        The Id of the vRA Code Stream Execution
 
        .INPUTS
        System.String
 
        .EXAMPLE
        ReRemove-vAACodeStreamExecution -Id '4b3bd194-9b5f-40fd-9ed0-58d997237999'
 
        .EXAMPLE
        Get-vAACodeStreamExecution -Pipeline 'My Pipeline' | ReRemove-vAACodeStreamExecution
 
    #>

    [CmdletBinding(SupportsShouldProcess,ConfirmImpact="High",DefaultParameterSetName="ById")]

    Param (

    [parameter(Mandatory=$true, ValueFromPipelineByPropertyName, ParameterSetName="ById")]
    [ValidateNotNullOrEmpty()]
    [String[]]$Id

    )

    begin {}

    process {

        try {

            switch ($PSCmdlet.ParameterSetName) {

                'ById' {

                    foreach ($ExecutionId in $Id) {

                        if ($PSCmdlet.ShouldProcess($ExecutionId)){

                            $URI = "/pipeline/api/executions/$($ExecutionId)"

                            Invoke-vAARestMethod -Method DELETE -URI "$($URI)" -Verbose:$VerbosePreference | Out-Null
                        }
                    }

                    break
                }
            }
        }
        catch [Exception]{

            throw
        }
    }
}


<#
    - Function: Remove-vAACodeStreamVariable
#>


function Remove-vAACodeStreamVariable {
    <#
        .SYNOPSIS
        Remove a vRA Code Stream Variable
 
        .DESCRIPTION
        Remove a vRA Code Stream Variable
 
        .PARAMETER Id
        The Id of the vRA Code Stream Variable
 
        .INPUTS
        System.String
 
        .EXAMPLE
        Remove-vAACodeStreamVariable -Id '4b3bd194-9b5f-40fd-9ed0-58d997237999'
 
        .EXAMPLE
         -Variable 'My Variable' | Remove-vAACodeStreamVariable
 
    #>

    [CmdletBinding(SupportsShouldProcess,ConfirmImpact="High",DefaultParameterSetName="ById")]

    Param (

    [parameter(Mandatory=$true, ValueFromPipelineByPropertyName, ParameterSetName="ById")]
    [ValidateNotNullOrEmpty()]
    [String[]]$Id

    )

    begin {}

    process {

        try {

            switch ($PSCmdlet.ParameterSetName) {

                'ById' {

                    foreach ($VariableId in $Id) {

                        if ($PSCmdlet.ShouldProcess($VariableId)){

                            $URI = "/pipeline/api/variables/$($VariableId)"

                            Invoke-vAARestMethod -Method DELETE -URI "$($URI)" -Verbose:$VerbosePreference | Out-Null
                        }
                    }

                    break
                }
            }
        }
        catch [Exception]{

            throw
        }
    }
}


<#
    - Function: Update-vAACodeStreamVariable
#>


function Update-vAACodeStreamVariable {
    <#
        .SYNOPSIS
        Update a vRealize Automation Code Stream Variable
 
        .DESCRIPTION
        Update a vRealize Automation Code Stream Variable
 
        .PARAMETER Id
        vRealize Automation Code Stream Variable Id
 
        .PARAMETER Name
        Name of the vRealize Automation Code Stream Variable
 
        .PARAMETER Description
        A description of the vRealize Automation Code Stream Variable
 
        .PARAMETER Value
        vRealize Automation Code Stream Variable Value
 
        .PARAMETER Type
        vRealize Automation Code Stream Variable Type
 
        .PARAMETER JSON
        A JSON string with the body payload
 
        .INPUTS
        System.String
 
        .OUTPUTS
        System.Management.Automation.PSObject
 
        .EXAMPLE
        Update-vAACodeStreamVariable -Name "My Variable" -Type REGULAR -Id 05352fc5-24c2-4ead-b6c0-5373e60a1b3d -Description "Updated from PowervAA!" -Value "New value"
 
        .EXAMPLE
         -Variable "My Variable" | Update-vAACodeStreamVariable -Value "New value" -Description "New Description"
 
        .EXAMPLE
        $JSON = @"
            {
                "name": "My Variable",
                "description": "My variable description"
                "type": "REGULAR",
                "value": "testing1"
            }
    "@
 
        $JSON | Update-vAACodeStreamVariable -Id 05352fc5-24c2-4ead-b6c0-5373e60a1b3d
 
 
    #>

    [CmdletBinding(SupportsShouldProcess,ConfirmImpact="Low",DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

        Param (

            [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName,ParameterSetName="Standard")]
            [ValidateNotNullOrEmpty()]
            [String]$Name,

            [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName,ParameterSetName="Standard")]
            [parameter(ParameterSetName = "JSON")]
            [ValidateNotNullOrEmpty()]
            [String]$Id,

            [Parameter(Mandatory=$false,ValueFromPipelineByPropertyName,ParameterSetName="Standard")]
            [ValidateNotNullOrEmpty()]
            [String]$Description,

            [Parameter(Mandatory=$true,ValueFromPipelineByPropertyName,ParameterSetName="Standard")]
            [ValidateSet("REGULAR","SECRET","RESTRICTED")] 
            [ValidateNotNullOrEmpty()]
            [String]$Type,

            [Parameter(Mandatory=$true,ParameterSetName="Standard")]
            [ValidateNotNullOrEmpty()]
            [String]$Value,

            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ParameterSetName="JSON")]
            [ValidateNotNullOrEmpty()]
            [String]$JSON

        )

        begin { }

        process {

                if ($PSBoundParameters.ContainsKey("JSON")) {
                    $Body = $JSON
                } else {
                    if($Description) {
                        $Body = @"
                        {
                            "name": "$($Name)",
                            "description": "$($Description)",
                            "type": "$($Type)",
                            "value": "$($Value)"
                        }
"@

                    } else {
                    $Body = @"
                        {
                            "name": "$($Name)",
                            "type": "$($Type)",
                            "value": "$($Value)"
                        }
"@

                    }
                }

            # --- Update the Variable
            try {
                if ($PSCmdlet.ShouldProcess($Id)){

                    $URI = "/pipeline/api/variables/$($Id)"
                    $Variable = Invoke-vAARestMethod -Method PUT -URI $URI -Body $Body -Verbose:$VerbosePreference

                    [PSCustomObject] @{
                        Name = $Variable.name
                        Description = $Variable.description
                        Id = $Variable.id
                        Type = $Variable.type
                        Value = $Variable.value
                        Project = $Variable.project
                    }
                }
            }
            catch [Exception] {

                throw
            }
        }
        end {

        }
    }

<#
    - Function: Get-vAAContentSource
#>


function Get-vAAContentSource {
    <#
        .SYNOPSIS
        Get a vRA Content Source
     
        .DESCRIPTION
        Get a vRA Content Source
     
        .PARAMETER Id
        The ID of the Content Source
     
        .PARAMETER Name
        The Name of the Content Source
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAAContentSource
     
        .EXAMPLE
        Get-vAAContentSource -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAAContentSource -Name 'TestContentSource'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/content/api/sources'
    
            function CalculateOutput([PSCustomObject]$ContentSource) {
    
                [PSCustomObject] @{
                    Id = $ContentSource.id
                    Name = $ContentSource.name
                    TypeId = $ContentSource.typeId
                    CreatedAt = $ContentSource.createdAt
                    CreatedBy = $ContentSource.createdBy
                    LastUpdatedAt = $ContentSource.lastUpdatedAt
                    LastUpdatedBy = $ContentSource.lastUpdatedBy
                    Config = $ContentSource.config
                    SyncEnabled = $ContentSource.syncEnabled
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get Content Source by Id
                    'ById' {
    
                        foreach ($ContentSourceId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($ContentSourceId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($ContentSource in $Response.content) {
                                CalculateOutput $ContentSource
                            }
                        }
    
                        break
                    }
                    # --- Get Content Source by Name
                    'ByName' {
    
                        foreach ($ContentSourceName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($ContentSourceName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($ContentSource in $Response.content) {
                                CalculateOutput $ContentSource
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all Content Sources
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($ContentSource in $Response.content) {
                            CalculateOutput $ContentSource
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: Get-vAADeployment
#>


function Get-vAADeployment {
    <#
        .SYNOPSIS
        Get a vRA Deployment
     
        .DESCRIPTION
        Get a vRA Deployment
     
        .PARAMETER Id
        The ID of the Deployment
     
        .PARAMETER Name
        The Name of the Deployment
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAADeployment
     
        .EXAMPLE
        Get-vAADeployment -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAADeployment -Name 'TestDeployment'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/deployment/api/deployments'
    
            function CalculateOutput([PSCustomObject]$Deployment) {
    
                [PSCustomObject] @{
                    Id = $Deployment.id
                    Name = $Deployment.name
                    OrgId = $Deployment.orgId
                    CatalogItemId = $Deployment.catalogItemId
                    CatalogItemVersion = $Deployment.catalogItemVersion
                    BlueprintId = $Deployment.blueprintId
                    BlueprintVersion = $Deployment.blueprintVersion
                    IconId = $Deployment.iconId
                    CreatedAt = $Deployment.createdAt
                    CreatedBy = $Deployment.createdBy
                    LastUpdatedAt = $Deployment.lastUpdatedAt
                    LastUpdatedBy = $Deployment.lastUpdatedBy
                    LeaseExpireAt = $Deployment.leaseExpireAt
                    Inputs = $Deployment.inputs
                    ProjectId = $Deployment.projectId
                    Status = $Deployment.status
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get Deployment by Id
                    'ById' {
    
                        foreach ($DeploymentId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($DeploymentId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($Deployment in $Response.content) {
                                CalculateOutput $Deployment
                            }
                        }
    
                        break
                    }
                    # --- Get Deployment by Name
                    'ByName' {
    
                        foreach ($DeploymentName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($DeploymentName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($Deployment in $Response.content) {
                                CalculateOutput $Deployment
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all Deployments
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($Deployment in $Response.content) {
                            CalculateOutput $Deployment
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: Get-vAAAPIVersion
#>


function Get-vAAAPIVersion {
<#
    .SYNOPSIS
    Retrieve vRA API version information
 
    .DESCRIPTION
    Retrieve vRA API version information
 
    .OUTPUTS
    System.Management.Automation.PSObject.
 
    .EXAMPLE
    Get-vAAAPIVersion
 
#>

[CmdletBinding()][OutputType('System.Management.Automation.PSObject')]

    Param ()

    try {

        $URI = "/iaas/api/about"
        $Response = Invoke-vAARestMethod -URI $URI -Method GET

        [pscustomobject] @{

            APIVersion = $Response.latestApiVersion
            SupportedAPIs = $Response.supportedApis.apiversion
        }
    }
    catch [Exception]{

        throw
    }
}

<#
    - Function: Get-vAABlockDevice
#>


function Get-vAABlockDevice {
    <#
        .SYNOPSIS
        Retrieve vRA Block Device(s)[Hard Disks] depending on input
 
        .DESCRIPTION
        Retrieve a list of vRA Block Devices or a single Block Device depending on input
 
        .PARAMETER Id
        The ID of the vRA Block Device
 
        .PARAMETER Name
        The Name of the Block Device
 
        .OUTPUTS
        System.Management.Automation.PSObject.
 
        .EXAMPLE
        Get-vAABlockDevice
 
        .EXAMPLE
        Get-vAABlockDevice -Id 'b1dd48e71d74267559bb930934470'
 
        .EXAMPLE
        Get-vAABlockDevice -Name 'my-disk'
 
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

        Param (

            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,

            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name

        )
        Begin {

            $APIUrl = "/iaas/api/block-devices"

            function CalculateOutput([PSCustomObject]$Response) {

                foreach ($Record in $Response.content) {
                    [PSCustomObject]@{
                        Owner = $Record.owner
                        Links = $Record._links
                        ExternalZoneId = $Record.externalZoneId
                        ExternalRegionId = $Record.externalRegionId
                        Description = $Record.description
                        ExternalId = $Record.externalId
                        OrgId = $Record.orgId
                        Tags = $Record.tags
                        OrganizationId = $Record.organizationId
                        CapacityInGB = $Record.capacityInGB
                        CreatedAt = $Record.createdAt
                        CloudAccountIds = $Record.cloudAccountIds
                        CustomProperties = $Record.customProperties
                        DeploymentId = $Record.deploymentId
                        Name = $Record.name
                        Id = $Record.id
                        Persistent = $Record.persistent
                        ProjectId = $Record.projectId
                        UpdatedAt = $Record.updatedAt
                        Status = $Record.status
                    }
                }
            }
        }
        Process 
        {
            try {

                switch ($PsCmdlet.ParameterSetName) {

                    # --- Get Block Device by its id
                    'ById' {
                        foreach ($MachineId in $Id) {
                            $Response = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=id eq '$MachineId'" -Method GET
                            CalculateOutput $Response
                        }

                        break
                    }

                    # --- Get Block Device by its name
                    'ByName' {
                        foreach ($MachineName in $Name) {
                            $Response = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$MachineName'" -Method GET
                            CalculateOutput $Response
                        }

                        break
                    }

                    # --- No parameters passed so return all Block Devices
                    'Standard' {
                        $Response = Invoke-vAARestMethod -URI $APIUrl -Method GET
                        CalculateOutput $Response
                    }

                }


            }
            catch [Exception]{

                throw
            }
        }
        End {

        }
    }


<#
    - Function: Get-vAACloudAccount
#>


function Get-vAACloudAccount {
<#
    .SYNOPSIS
    Get a vRA Cloud Account.
 
    .DESCRIPTION
    Get a vRA Cloud Account.
 
    .PARAMETER Id
    The id of the Cloud Account
 
    .PARAMETER Name
    The name of the Cloud Account
 
    .PARAMETER Type
    Cloud Account Type, e.g. vSphere, Azure, AWS, GCP etc
 
    .INPUTS
    System.String
 
    .OUTPUTS
    System.Management.Automation.PSObject
 
    .EXAMPLE
    Get-vAACloudAccount
 
    .EXAMPLE
    Get-vAACloudAccount -Id d6f8b87ba95ab675597c97eefdd9c
 
    .EXAMPLE
    Get-vAACloudAccount -Name vSphere_test
 
    .EXAMPLE
    Get-vAACloudAccount -Type vSphere
 
#>

[CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Name,

        [Parameter(Mandatory=$false)]
        [ValidateSet('azure','aws','gcp','nsx-t','nsx-v','vmc','vsphere')]
        [String]$Type
    )

    Begin {
        $APIUrl = '/iaas/api/cloud-accounts'

        if ($PSBoundParameters.ContainsKey('Type')){

            $APIUrl = $APIUrl + "-$Type"
        }

        function CalculateOutput([PSCustomObject]$CloudAccount, [String]$Type) {

            if ($null -ne $Type){

                $CloudAccountType = $Type
            }
            else {

                $CloudAccountType = $CloudAccount.cloudAccountType
            }

            [PSCustomObject] @{

                Name = $CloudAccount.name
                Description = $CloudAccount.description
                Id = $CloudAccount.id
                CloudAccountType = $CloudAccountType
                EnabledRegionIds = $CloudAccount.enabledRegionIds
                CustomProperties = $CloudAccount.customProperties
                OrganizationId = $CloudAccount.organizationId
                Links = $CloudAccount._links
            }
        }
    }

    Process {

        try {

            switch ($PsCmdlet.ParameterSetName) {

                # --- Get Cloud Account by id
                'ById' {

                    foreach ($CloudAccountId in $Id) {

                        $URI = "$APIUrl/$($CloudAccountId)"

                        $CloudAccount = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        CalculateOutput $CloudAccount $Type
                    }

                    break
                }
                # --- Get Cloud Account by name
                'ByName' {

                    $URI = $APIUrl

                    $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                    foreach ($CloudAccountName in $Name) {

                        $CloudAccount = $Response.content | Where-Object {$_.name -eq $CloudAccountName}

                        if (!$CloudAccount) {

                            throw "Could not find Cloud Account with name: $($CloudAccountName)"

                        }

                        CalculateOutput $CloudAccount $Type
                    }

                    break
                }
                # --- No parameters passed so return all Cloud Accounts
                'Standard' {

                    $URI = $APIUrl

                    $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                    foreach ($CloudAccount in $Response.content) {

                        CalculateOutput $CloudAccount $Type
                    }
                }
            }
        }
        catch [Exception]{

            throw
        }
    }

    End {

    }
}


<#
    - Function: Get-vAACloudZone
#>


function Get-vAACloudZone {
<#
    .SYNOPSIS
    Get a vRA Cloud Zone
 
    .DESCRIPTION
    Get a vRA Cloud Zone
 
    .PARAMETER Id
    The ID of the Cloud Zone
 
    .PARAMETER Name
    The Name of the Cloud Zone
 
    .INPUTS
    System.String
 
    .OUTPUTS
    System.Management.Automation.PSObject
 
    .EXAMPLE
    Get-vAACloudZone
 
    .EXAMPLE
    Get-vAACloudZone -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
 
    .EXAMPLE
    Get-vAACloudZone -Name 'TestCloudZone'
 
#>

[CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Name
    )

    begin {
        $APIUrl = '/iaas/api/zones'

        function CalculateOutput([PSCustomObject]$CloudZone) {

            [PSCustomObject] @{

                Name = $CloudZone.name
                Description = $CloudZone.description
                Id = $CloudZone.id
                PlacementPolicy = $CloudZone.placementPolicy
                Tags = $CloudZone.tags
                TagsToMatch = $CloudZone.tagsToMatch
                CustomProperties = $CloudZone.customProperties
                Folder = $CloudZone.folder
                OrganizationId = $CloudZone.organizationId
                Links = $CloudZone._links
                UpdatedAt = $CloudZone.updatedAt
            }
        }
    }

    process {

        try {

            switch ($PsCmdlet.ParameterSetName) {

                # --- Get Cloud Zone by Id
                'ById' {

                    foreach ($CloudZoneId in $Id){

                        $URI = "$($APIUrl)?`$filter=id eq '$($CloudZoneId)'"
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($CloudZone in $Response.content) {

                            CalculateOutput $CloudZone
                        }
                    }

                    break
                }
                # --- Get Cloud Zone by Name
                'ByName' {

                    foreach ($CloudZoneName in $Name){

                        $URI = "$($APIUrl)?`$filter=name eq '$($CloudZoneName)'"
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($CloudZone in $Response.content){

                            CalculateOutput $CloudZone
                        }
                    }

                    break
                }
                # --- No parameters passed so return all Cloud Zones
                'Standard' {

                    $URI = $APIUrl
                    $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                    foreach ($CloudZone in $Response.content){

                        CalculateOutput $CloudZone
                    }
                }
            }
        }
        catch [Exception]{

            throw
        }
    }

    end {

    }
}


<#
    - Function: Get-vAAExternalNetworkIPRange
#>


function Get-vAAExternalNetworkIPRange {
    <#
        .SYNOPSIS
        Get a vRA External Network IP Range
     
        .DESCRIPTION
        Get a vRA External Network IP Range
     
        .PARAMETER Id
        The ID of the vRA External Network IP Range
     
        .PARAMETER Name
        The Name of the vRA External Network IP Range
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAAExternalNetworkIPRange
     
        .EXAMPLE
        Get-vAAExternalNetworkIPRange -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAAExternalNetworkIPRange -Name 'TestExternalNetworkIPRange'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/iaas/api/external-network-ip-ranges'
    
            function CalculateOutput([PSCustomObject]$ExternalNetworkIPRange) {
    
                [PSCustomObject] @{
                    Owner = $ExternalNetworkIPRange.owner
                    Description = $ExternalNetworkIPRange.description
                    Tags = $ExternalNetworkIPRange.tags
                    ExternalId = $ExternalNetworkIPRange.externalId
                    SubnetPrefixLength = $ExternalNetworkIPRange.subnetPrefixLength
                    Name = $ExternalNetworkIPRange.name
                    Id = $ExternalNetworkIPRange.id
                    CreatedAt = $ExternalNetworkIPRange.createdAt
                    UpdatedAt = $ExternalNetworkIPRange.updatedAt
                    OrganizationId = $ExternalNetworkIPRange.orgId
                    StartIPAddress = $ExternalNetworkIPRange.startIPAddress
                    EndIPAddress = $ExternalNetworkIPRange.endIPAddress
                    IPVersion = $ExternalNetworkIPRange.ipVersion
                    AddressSpaceId = $ExternalNetworkIPRange.addressSpaceId
                    DNSServerAddresses = $ExternalNetworkIPRange.dnsServerAddresses
                    DNSSearchDomains = $ExternalNetworkIPRange.dnsSearchDomains
                    Domain = $ExternalNetworkIPRange.domain
                    GatewayAddress = $ExternalNetworkIPRange.gatewayAddress
                    Links = $ExternalNetworkIPRange._links
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get External Network IP Range by Id
                    'ById' {
    
                        foreach ($ExternalNetworkIPRangeId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($ExternalNetworkIPRangeId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($ExternalNetworkIPRange in $Response.content) {
                                CalculateOutput $ExternalNetworkIPRange
                            }
                        }
    
                        break
                    }
                    # --- Get External Network IP Range by Name
                    'ByName' {
    
                        foreach ($ExternalNetworkIPRangeName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($ExternalNetworkIPRangeName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($ExternalNetworkIPRange in $Response.content) {
                                CalculateOutput $ExternalNetworkIPRange
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all External Network IP Ranges
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($ExternalNetworkIPRange in $Response.content) {
                            CalculateOutput $ExternalNetworkIPRange
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    


<#
    - Function: Get-vAAFabricAWSVolumeType
#>


function Get-vAAFabricAWSVolumeType {
    <#
        .SYNOPSIS
        Get a vRA Fabric AWS Volume Types
     
        .DESCRIPTION
        Get a vRA Fabric AWS Volume Types
     
        .INPUTS
        None
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAAFabricAWSVolumeTypes
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
        )
    
        begin {
            $APIUrl = '/iaas/api/fabric-aws-volume-types'
    
            function CalculateOutput([PSCustomObject]$FabricAWSVolumeTypes) {
    
                [PSCustomObject] @{
                    VolumeTypes = $FabricAWSVolumeTypes.volumeTypes
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Return all Fabric AWS Volume Types
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($FabricAWSVolumeTypes in $Response.content) {
                            CalculateOutput $FabricAWSVolumeTypes
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: Get-vAAFabricAzureStorageAccount
#>


function Get-vAAFabricAzureStorageAccount {
    <#
        .SYNOPSIS
        Get a vRA Fabric Azure Storage Account
 
        .DESCRIPTION
        Get a vRA Fabric Azure Storage Account
 
        .PARAMETER Id
        The ID of the Fabric Azure Storage Account
 
        .PARAMETER Name
        The Name of the Fabric Azure Storage Account
 
        .INPUTS
        None
 
        .OUTPUTS
        System.Management.Automation.PSObject
 
        .EXAMPLE
        Get-vAAFabricAzureStorageAccounts
 
        .EXAMPLE
        Get-vAAFabricAzureStorageAccounts -Id 1c3a50ca-1c38-42a3-a572-209d5dfdecf7
 
        .EXAMPLE
        Get-vAAFabricAzureStorageAccounts -Name "test-Azure-Storage-Account"
 
    #>

    [CmdletBinding(DefaultParameterSetName = "Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true, ParameterSetName = "ById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory = $true, ParameterSetName = "ByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Name
    )

    begin {
        $APIUrl = '/iaas/api/fabric-azure-storage-accounts'

        function CalculateOutput([PSCustomObject]$FabricAzureStorageAccounts) {

            [PSCustomObject] @{

                Type             = $FabricAzureStorageAccounts.type
                ExternalRegionId = $FabricAzureStorageAccounts.externalRegionId
                Name             = $FabricAzureStorageAccounts.name
                Id               = $FabricAzureStorageAccounts.id
                OrganizationId   = $FabricAzureStorageAccounts.organizationId
                CloudAccountIds  = $FabricAzureStorageAccounts.cloudAccountIds
                Links            = $FabricAzureStorageAccounts._links
            }
        }
    }

    process {

        try {

            switch ($PsCmdlet.ParameterSetName) {

                # --- Get Cloud Account by id
                'ById' {

                    foreach ($FabricAzureStorageAccountId in $Id) {

                        $URI = "$APIUrl/$($FabricAzureStorageAccountId)"

                        $FabricAzureStorageAccount = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        CalculateOutput $FabricAzureStorageAccount
                    }

                    break
                }
                # --- Get Cloud Account by name
                'ByName' {

                    $URI = $APIUrl

                    $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                    foreach ($FabricAzureStorageAccountName in $Name) {

                        $FabricAzureStorageAccounts = $Response.content | Where-Object { $_.name -eq $FabricAzureStorageAccountName }

                        if (!$FabricAzureStorageAccounts) {

                            throw "Could not find Cloud Account with name: $($FabricAzureStorageAccounts)"

                        }

                        CalculateOutput $FabricAzureStorageAccounts
                    }

                    break
                }
                # --- Return all Fabric AWS Volume Types
                'Standard' {

                    $URI = $APIUrl

                    $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                    foreach ($FabricAzureStorageAccounts in $Response.content) {

                        CalculateOutput $FabricAzureStorageAccounts
                    }
                }
            }
        }
        catch [Exception] {

            throw
        }
    }

    end {

    }
}


<#
    - Function: Get-vAAFabricCompute
#>


function Get-vAAFabricCompute {
    <#
        .SYNOPSIS
        Get a vRA Fabric Compute
     
        .DESCRIPTION
        Get a vRA Fabric Compute
     
        .PARAMETER Id
        The ID of the Fabric Compute
     
        .PARAMETER Name
        The Name of the Fabric Compute
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAAFabricCompute
     
        .EXAMPLE
        Get-vAAFabricCompute -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAAFabricCompute -Name 'TestFabricCompute'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/deployment/api/fabric-computes'
    
            function CalculateOutput([PSCustomObject]$FabricCompute) {
    
                [PSCustomObject] @{
                    ExternalRegionId = $FabricCompute.externalRegionId
                    Tags = $FabricCompute.tags
                    Type = $FabricCompute.type
                    CustomProperties = $FabricCompute.customProperties
                    ExternalId = $FabricCompute.externalId
                    Name = $FabricCompute.name
                    Id = $FabricCompute.id
                    CreatedAt = $FabricCompute.createdAt
                    UpdatedAt = $FabricCompute.updatedAt
                    OrganizationId = $FabricCompute.organizationId
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get FabricCompute by Id
                    'ById' {
    
                        foreach ($FabricComputeId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($FabricComputeId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($FabricCompute in $Response.content) {
                                CalculateOutput $FabricCompute
                            }
                        }
    
                        break
                    }
                    # --- Get FabricCompute by Name
                    'ByName' {
    
                        foreach ($FabricComputeName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($FabricComputeName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($FabricCompute in $Response.content) {
                                CalculateOutput $FabricCompute
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all FabricComputes
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($FabricCompute in $Response.content) {
                            CalculateOutput $FabricCompute
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: Get-vAAFabricImage
#>


function Get-vAAFabricImage {
    <#
        .SYNOPSIS
        Get a vRA FabricImages
     
        .DESCRIPTION
        Get a vRA FabricImages
     
        .PARAMETER Id
        The ID of the FabricImages
     
        .PARAMETER Name
        The Name of the FabricImages
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAAFabricImages
     
        .EXAMPLE
        Get-vAAFabricImages -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAAFabricImages -Name 'TestFabricImages'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/deployment/api/fabric-images'
    
            function CalculateOutput([PSCustomObject]$FabricImages) {
    
                [PSCustomObject] @{
                    OSFamily = $FabricImages.osFamily
                    ExternalRegionId = $FabricImages.externalRegionId
                    CustomProperties = $FabricImages.customProperties
                    IsPrivate = $FabricImages.isPrivate
                    ExternalId = $FabricImages.externalId
                    Name = $FabricImages.name
                    Description = $FabricImages.description
                    Id = $FabricImages.id
                    UpdatedAt = $FabricImages.updatedAt
                    OrganizationId = $FabricImages.organizationId
                    Links = $FabricImages._links
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get Fabric Image by Id
                    'ById' {
    
                        foreach ($FabricImagesId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($FabricImagesId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($FabricImages in $Response.content) {
                                CalculateOutput $FabricImages
                            }
                        }
    
                        break
                    }
                    # --- Get Fabric Image by Name
                    'ByName' {
    
                        foreach ($FabricImagesName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($FabricImagesName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($FabricImages in $Response.content) {
                                CalculateOutput $FabricImages
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all Fabric Images
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($FabricImages in $Response.content) {
                            CalculateOutput $FabricImages
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: Get-vAAFabricNetwork
#>


function Get-vAAFabricNetwork {
    <#
        .SYNOPSIS
        Get a vRA Fabric Network
     
        .DESCRIPTION
        Get a vRA Fabric Network
     
        .PARAMETER Id
        The ID of the Fabric Network
     
        .PARAMETER Name
        The Name of the Fabric Network
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAAFabricNetwork
     
        .EXAMPLE
        Get-vAAFabricNetwork -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAAFabricNetwork -Name 'TestFabricNetwork'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/iaas/api/fabric-networks'
    
            function CalculateOutput([PSCustomObject]$FabricNetwork) {
    
                [PSCustomObject] @{
                    ExternalRegionId = $FabricNetwork.externalRegionId
                    CloudAccountIds = $FabricNetwork.cloudAccountIds
                    ExternalId = $FabricNetwork.externalId
                    Name = $FabricNetwork.name
                    Id = $FabricNetwork.id
                    CreatedAt = $FabricNetwork.createdAt
                    UpdatedAt = $FabricNetwork.updatedAt
                    OrganizationId = $FabricNetwork.organizationId
                    Links = $FabricNetwork._links
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get Fabric Network by Id
                    'ById' {
    
                        foreach ($FabricNetworkId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($FabricNetworkId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($FabricNetwork in $Response.content) {
                                CalculateOutput $FabricNetwork
                            }
                        }
    
                        break
                    }
                    # --- Get Fabric Network by Name
                    'ByName' {
    
                        foreach ($FabricNetworkName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($FabricNetworkName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($FabricNetwork in $Response.content) {
                                CalculateOutput $FabricNetwork
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all Fabric Networks
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($FabricNetwork in $Response.content) {
                            CalculateOutput $FabricNetwork
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: Get-vAAFlavorProfile
#>


function Get-vAAFlavorProfile {
    <#
        .SYNOPSIS
        Get a vRA Flavor Profile
     
        .DESCRIPTION
        Get a vRA Flavor Profile
     
        .PARAMETER Id
        The ID of the vRA Flavor Profile
     
        .PARAMETER Name
        The Name of the vRA Flavor Profile
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAAFlavorProfile
     
        .EXAMPLE
        Get-vAAFlavorProfile -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAAFlavorProfile -Name 'TestFlavorProfile'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/iaas/api/flavor-profiles'
    
            function CalculateOutput([PSCustomObject]$FlavorProfile) {
    
                [PSCustomObject] @{
                    FlavorMappings = $FlavorProfile.flavorMappings
                    ExternalRegionId = $FlavorProfile.externalRegionId
                    Name = $FlavorProfile.name
                    Id = $FlavorProfile.id
                    UpdatedAt = $FlavorProfile.updatedAt
                    OrganizationId = $FlavorProfile.organizationId
                    Links = $FlavorProfile._links
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get Flavor Profile by Id
                    'ById' {
    
                        foreach ($FlavorProfileId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($FlavorProfileId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($FlavorProfile in $Response.content) {
                                CalculateOutput $FlavorProfile
                            }
                        }
    
                        break
                    }
                    # --- Get Flavor Profile by Name
                    'ByName' {
    
                        foreach ($FlavorProfileName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($FlavorProfileName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($FlavorProfile in $Response.content) {
                                CalculateOutput $FlavorProfile
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all Flavor Profiles
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($FlavorProfile in $Response.content) {
                            CalculateOutput $FlavorProfile
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: Get-vAAImageProfile
#>


function Get-vAAImageProfile {
    <#
        .SYNOPSIS
        Get a vRA Image Profile
     
        .DESCRIPTION
        Get a vRA Image Profile
     
        .PARAMETER Id
        The ID of the vRA Image Profile
     
        .PARAMETER Name
        The Name of the vRA Image Profile
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAAImageProfile
     
        .EXAMPLE
        Get-vAAImageProfile -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAAImageProfile -Name 'TestImageProfile'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/iaas/api/image-profiles'
    
            function CalculateOutput([PSCustomObject]$ImageProfile) {
    
                [PSCustomObject] @{
                    ImageMappings = $ImageProfile.imageMappings.mapping  ## Pull out mappings from nested JSON object
                    ImageMapNames = ($ImageProfile.imageMappings.mapping | get-member -MemberType NoteProperty).Name  ## List mappings by their key name for easier access
                    ExternalRegionId = $ImageProfile.externalRegionId
                    Name = $ImageProfile.name
                    Id = $ImageProfile.id
                    UpdatedAt = $ImageProfile.updatedAt
                    OrgId = $ImageProfile.orgId
                    Links = $ImageProfile._links
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get Image Profile by Id
                    'ById' {
    
                        foreach ($ImageProfileId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($ImageProfileId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($ImageProfile in $Response.content) {
                                CalculateOutput $ImageProfile
                            }
                        }
    
                        break
                    }
                    # --- Get Image Profile by Name
                    'ByName' {
    
                        foreach ($ImageProfileName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($ImageProfileName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($ImageProfile in $Response.content) {
                                CalculateOutput $ImageProfile
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all Image Profiles
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($ImageProfile in $Response.content) {
                            CalculateOutput $ImageProfile
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: Get-vAALoadBalancer
#>


function Get-vAALoadBalancer {
    <#
        .SYNOPSIS
        Get a vRA Load Balancer
     
        .DESCRIPTION
        Get a vRA Load Balancer
     
        .PARAMETER Id
        The ID of the vRA Load Balancer
     
        .PARAMETER Name
        The Name of the vRA Load Balancer
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAALoadBalancer
     
        .EXAMPLE
        Get-vAALoadBalancer -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAALoadBalancer -Name 'TestLoadBalancer'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/iaas/api/load-balancers'
    
            function CalculateOutput([PSCustomObject]$LoadBalancer) {
    
                [PSCustomObject] @{
                    Address = $LoadBalancer.address
                    Routes = $LoadBalancer.routes
                    ExternalRegionId = $LoadBalancer.externalRegionId
                    CloudAccountIds = $LoadBalancer.cloudAccountIds
                    Tags = $LoadBalancer.tags
                    CustomProperties = $LoadBalancer.customProperties
                    ExternalId = $LoadBalancer.externalId
                    Name = $LoadBalancer.name
                    Id = $LoadBalancer.id
                    UpdatedAt = $LoadBalancer.updatedAt
                    OrgId = $LoadBalancer.orgId
                    Links = $LoadBalancer._links
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get Load Balancer by Id
                    'ById' {
    
                        foreach ($LoadBalancerId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($LoadBalancerId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($LoadBalancer in $Response.content) {
                                CalculateOutput $LoadBalancer
                            }
                        }
    
                        break
                    }
                    # --- Get Load Balancer by Name
                    'ByName' {
    
                        foreach ($LoadBalancerName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($LoadBalancerName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($LoadBalancer in $Response.content) {
                                CalculateOutput $LoadBalancer
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all Load Balancers
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($LoadBalancer in $Response.content) {
                            CalculateOutput $LoadBalancer
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: Get-vAAMachine
#>


function Get-vAAMachine {
<#
    .SYNOPSIS
    Retrieve vRA Machine(s) depending on input
 
    .DESCRIPTION
    Retrieve a list of vRA Machines or a single machine depending on input
 
    .PARAMETER Id
    The ID of the vRA Machine
 
    .PARAMETER Name
    The Name of the vRA Machine
 
    .OUTPUTS
    System.Management.Automation.PSObject.
 
    .EXAMPLE
    Get-vAAMachine
 
    .EXAMPLE
    Get-vAAMachine -Id 'b1dd48e71d74267559bb930934470'
 
    .EXAMPLE
    Get-vAAMachine -Name 'iaas01'
 
#>

[CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Name

    )
    Begin {

        $APIUrl = "/iaas/api/machines"

        function CalculateOutput([PSCustomObject]$Response) {

            foreach ($Record in $Response.content) {
                [PSCustomObject]@{
                    Name = $Record.name
                    PowerState = $Record.powerState
                    IPAddress = $Record.address
                    ExternalRegionId = $Record.externalRegionId
                    CloudAccountIDs = $Record.cloudAccountIds
                    ExternalId = $Record.externalId
                    Id = $Record.id
                    DateCreated = $Record.createdAt
                    LastUpdated = $Record.updatedAt
                    OrganizationId = $Record.organizationId
                    Properties = $Record.customProperties
                    Tags = $Record.tags
                }
            }
        }
    }
    Process {

        try {

            switch ($PsCmdlet.ParameterSetName) {

                # --- Get Machine by its id
                'ById' {
                    foreach ($MachineId in $Id) {
                        $Response = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=id eq '$MachineId'" -Method GET
                        CalculateOutput $Response
                    }

                    break
                }

                # --- Get Machine by its name
                'ByName' {
                    foreach ($MachineName in $Name) {
                        $Response = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$MachineName'" -Method GET
                        CalculateOutput $Response
                    }

                    break
                }

                # --- No parameters passed so return all machines
                'Standard' {
                    $Response = Invoke-vAARestMethod -URI $APIUrl -Method GET
                    CalculateOutput $Response
                }

            }


        }
        catch [Exception]{

            throw
        }
    }
    End {

    }
}


<#
    - Function: Get-vAAMachineDisk
#>


function Get-vAAMachineDisk {
<#
    .SYNOPSIS
    Retrieve a vRA Machine's Disks
 
    .DESCRIPTION
    Retrieve the disks for a vRA Machine
 
    .PARAMETER Id
    The ID of the vRA Machine
 
    .PARAMETER Name
    The Name of the vRA Machine
 
    .PARAMETER DiskId
    The Id of the individual Disk to retrieve
 
    .OUTPUTS
    System.Management.Automation.PSObject.
 
    .EXAMPLE
    Get-vAAMachineDisk -Id 'b1dd48e71d74267559bb930934470'
 
    .EXAMPLE
    Get-vAAMachineDisk -Name 'iaas01'
 
    .EXAMPLE
    GET-vAAMachineDisk -Name 'iaas01' -DiskId b1dd48e71d74267559bb930919aa8,b1dd48e71d74267559bb930915840
 
#>

[CmdletBinding(DefaultParameterSetName="ByName")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter(Mandatory=$false)]
        [ValidateNotNullOrEmpty()]
        [String[]]$DiskId

    )
    Begin {

        $APIUrl = "/iaas/api/machines"

        function CalculateOutput([PSCustomObject]$Response) {

            # --- The output comes in two flavors, a list or a single item, we are checking for list here
            if ($Response.content) {
                foreach ($Record in $Response.content) {
                    [PSCustomObject]@{
                        Name = $Record.name
                        Status = $Record.status
                        Owner = $Record.owner
                        ExternalRegionId = $Record.externalRegionId
                        ExternalZoneId = $Record.externalZoneId
                        Description = $Record.description
                        Tags = $Record.tags
                        CapacityInGB = $Record.capacityInGB
                        CloudAccountIDs = $Record.cloudAccountIds
                        ExternalId = $Record.externalId
                        Id = $Record.id
                        DateCreated = $Record.createdAt
                        LastUpdated = $Record.updatedAt
                        OrganizationId = $Record.orgId
                        Properties = $Record.customProperties
                        ProjectId = $Record.projectId
                        Persistent = $Record.persistent
                    }
                }
            } else {
                [PSCustomObject]@{
                    Name = $Response.name
                    Status = $Response.status
                    Owner = $Response.owner
                    ExternalRegionId = $Response.externalRegionId
                    ExternalZoneId = $Response.externalZoneId
                    Description = $Response.description
                    Tags = $Response.tags
                    CapacityInGB = $Response.capacityInGB
                    CloudAccountIDs = $Response.cloudAccountIds
                    ExternalId = $Response.externalId
                    Id = $Response.id
                    DateCreated = $Response.createdAt
                    LastUpdated = $Response.updatedAt
                    OrganizationId = $Response.orgId
                    Properties = $Response.customProperties
                    ProjectId = $Response.projectId
                    Persistent = $Response.persistent
                }
            }

        }
    }
    Process {

        try {

            switch ($PsCmdlet.ParameterSetName) {

                # --- Get Machine Disk by its id
                'ById' {

                    # --- Check to see if the DiskId's were optionally present
                    if ($DiskId) {

                        foreach($Disk in $DiskId) {

                            $Response = Invoke-vAARestMethod -URI "$APIUrl`/$Id`/disks`/$Disk" -Method GET

                            CalculateOutput $Response

                        }

                    } else {

                        $Response = Invoke-vAARestMethod -URI "$APIUrl`/$Id`/disks" -Method GET

                        CalculateOutput $Response

                    }

                    break
                }

                # --- Get Machine Disk by its name
                # --- Will need to retrieve the machine first, then use ID to get final output
                'ByName' {

                    $MachineResponse = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$Name'`&`$select=id" -Method GET
                    $MachineId = $MachineResponse.content[0].id

                    # --- Check to see if the DiskId's were optionally present
                    if ($DiskId) {

                        foreach($Disk in $DiskId) {

                            $Response = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId`/disks`/$Disk" -Method GET

                            CalculateOutput $Response

                        }


                    } else {

                        $Response = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId`/disks" -Method GET

                        CalculateOutput $Response

                    }


                    break
                }

            }

        }
        catch [Exception]{

            throw
        }
    }
    End {

    }
}


<#
    - Function: Get-vAANetwork
#>


function Get-vAANetwork {
    <#
        .SYNOPSIS
        Get a vRA Network
     
        .DESCRIPTION
        Get a vRA Network
     
        .PARAMETER Id
        The ID of the vRA Network
     
        .PARAMETER Name
        The Name of the vRA Network
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAANetwork
     
        .EXAMPLE
        Get-vAANetwork -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAANetwork -Name 'TestNetwork'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/iaas/api/networks'
    
            function CalculateOutput([PSCustomObject]$Network) {
    
                [PSCustomObject] @{
                    Cidr = $Network.cidr
                    ExternalZoneId = $Network.externalZoneId
                    ExternalRegionId = $Network.externalRegionId
                    CloudAccountIds = $Network.cloudAccountIds
                    Tags = $Network.tags
                    CustomProperties = $Network.customProperties
                    ExternalId = $Network.externalId
                    Name = $Network.name
                    Id = $Network.id
                    UpdatedAt = $Network.updatedAt
                    OrganizationId = $Network.orgId
                    Links = $Network._links
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get Network by Id
                    'ById' {
    
                        foreach ($NetworkId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($NetworkId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($Network in $Response.content) {
                                CalculateOutput $Network
                            }
                        }
    
                        break
                    }
                    # --- Get Network by Name
                    'ByName' {
    
                        foreach ($NetworkName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($NetworkName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($Network in $Response.content) {
                                CalculateOutput $Network
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all Networks
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($Network in $Response.content) {
                            CalculateOutput $Network
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }

<#
    - Function: Get-vAANetworkDomain
#>


function Get-vAANetworkDomain {
    <#
        .SYNOPSIS
        Get a vRA Network Domain
     
        .DESCRIPTION
        Get a vRA Network Domain
     
        .PARAMETER Id
        The ID of the vRA Network Domain
     
        .PARAMETER Name
        The Name of the vRA Network Domain
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAANetworkDomain
     
        .EXAMPLE
        Get-vAANetworkDomain -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAANetworkDomain -Name 'TestNetworkDomain'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/iaas/api/network-domains'
    
            function CalculateOutput([PSCustomObject]$NetworkDomain) {
    
                [PSCustomObject] @{
                    ExternalRegionId = $NetworkDomain.externalRegionId
                    Tags = $NetworkDomain.tags
                    CustomProperties = $NetworkDomain.customProperties
                    CloudAccountIds = $NetworkDomain.cloudAccountIds
                    ExternalId = $NetworkDomain.externalId
                    Name = $NetworkDomain.name
                    Id = $NetworkDomain.id
                    CreatedAt = $NetworkDomain.createdAt
                    UpdatedAt = $NetworkDomain.updatedAt
                    OrganizationId = $NetworkDomain.orgId
                    Links = $NetworkDomain._links
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get NetworkDomain by Id
                    'ById' {
    
                        foreach ($NetworkDomainId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($NetworkDomainId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($NetworkDomain in $Response.content) {
                                CalculateOutput $NetworkDomain
                            }
                        }
    
                        break
                    }
                    # --- Get NetworkDomain by Name
                    'ByName' {
    
                        foreach ($NetworkDomainName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($NetworkDomainName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($NetworkDomain in $Response.content) {
                                CalculateOutput $NetworkDomain
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all NetworkDomains
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($NetworkDomain in $Response.content) {
                            CalculateOutput $NetworkDomain
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: Get-vAANetworkIPRange
#>


function Get-vAANetworkIPRange {
    <#
        .SYNOPSIS
        Get a vRA Network IP Ranges
     
        .DESCRIPTION
        Get a vRA Network IP Ranges
     
        .PARAMETER Id
        The ID of the vRA Network IP Ranges
     
        .PARAMETER Name
        The Name of the vRA Network IP Ranges
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAANetworkIPRange
     
        .EXAMPLE
        Get-vAANetworkIPRange -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAANetworkIPRange -Name 'TestNetworkIPRange'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/iaas/api/network-ip-ranges'
    
            function CalculateOutput([PSCustomObject]$NetworkIPRange) {
    
                [PSCustomObject] @{
                    Owner = $NetworkIPRange.owner
                    Description = $NetworkIPRange.description
                    Tags = $NetworkIPRange.tags
                    ExternalId = $NetworkIPRange.externalId
                    Name = $NetworkIPRange.name
                    Id = $NetworkIPRange.id
                    CreatedAt = $NetworkIPRange.createdAt
                    UpdatedAt = $NetworkIPRange.updatedAt
                    OrganizationId = $NetworkIPRange.orgId
                    StartIPAddress = $NetworkIPRange.startIPAddress
                    EndIPAddress = $NetworkIPRange.endIPAddress
                    IPVersion = $NetworkIPRange.ipVersion
                    Links = $NetworkIPRange._links
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get Network IP Range by Id
                    'ById' {
    
                        foreach ($NetworkIPRangeId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($NetworkIPRangeId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($NetworkIPRange in $Response.content) {
                                CalculateOutput $NetworkIPRange
                            }
                        }
    
                        break
                    }
                    # --- Get Network IP Range by Name
                    'ByName' {
    
                        foreach ($NetworkIPRangeName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($NetworkIPRangeName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($NetworkIPRange in $Response.content) {
                                CalculateOutput $NetworkIPRange
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all Network IP Ranges
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($NetworkIPRange in $Response.content) {
                            CalculateOutput $NetworkIPRange
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
}

<#
    - Function: Get-vAANetworkProfile
#>


function Get-vAANetworkProfile {
    <#
        .SYNOPSIS
        Get a vRA Network Profile
     
        .DESCRIPTION
        Get a vRA Network Profile
     
        .PARAMETER Id
        The ID of the Network Profile
     
        .PARAMETER Name
        The Name of the Network Profile
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAANetworkProfile
     
        .EXAMPLE
        Get-vAANetworkProfile -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAANetworkProfile -Name 'TestNetworkProfile'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/iaas/api/network-profiles'
    
            function CalculateOutput([PSCustomObject]$NetworkProfile) {
    
                [PSCustomObject] @{
                    ExternalRegionId = $NetworkProfile.externalRegionId
                    IsolationType = $NetworkProfile.isolationType
                    CustomProperties = $NetworkProfile.customProperties
                    Name = $NetworkProfile.name
                    Id = $NetworkProfile.id
                    UpdatedAt = $NetworkProfile.updatedAt
                    OrganizationId = $NetworkProfile.organizationId
                    Links = $NetworkProfile._links
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get Network Profile by Id
                    'ById' {
    
                        foreach ($NetworkProfileId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($NetworkProfileId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($NetworkProfile in $Response.content) {
                                CalculateOutput $NetworkProfile
                            }
                        }
    
                        break
                    }
                    # --- Get Network Profile by Name
                    'ByName' {
    
                        foreach ($NetworkProfileName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($NetworkProfileName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($NetworkProfile in $Response.content) {
                                CalculateOutput $NetworkProfile
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all Network Profiles
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($NetworkProfile in $Response.content) {
                            CalculateOutput $NetworkProfile
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    


<#
    - Function: Get-vAAProject
#>


function Get-vAAProject {
<#
    .SYNOPSIS
    Get a vRA Project
 
    .DESCRIPTION
    Get a vRA Project
 
    .PARAMETER Id
    The ID of the Project
 
    .PARAMETER Name
    The Name of the Project
 
    .INPUTS
    System.String
 
    .OUTPUTS
    System.Management.Automation.PSObject
 
    .EXAMPLE
    Get-vAAProject
 
    .EXAMPLE
    Get-vAAProject -Id '3492a6e8-4e70-1293-b6c4-39037ba693f9'
 
    .EXAMPLE
    Get-vAAProject -Name 'Test Project'
 
#>

[CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Name
    )

    begin {
        $APIUrl = '/iaas/api/projects'

        function CalculateOutput([PSCustomObject]$Project) {

            [PSCustomObject] @{

                Name = $Project.name
                Description = $Project.description
                Id = $Project.id
                Administrators = $Project.administrators
                Members = $Project.members
                Viewers = $Project.viewers
                Zones = $Project.zones
                SharedResources = $Project.sharedResources
                OperationTimeout = $Project.operationTimeout
                PlacementPolicy = $Project.placementPolicy
                CustomProperties = $Project.customProperties
                OrganizationId = $Project.organizationId
                Links = $Project._links
            }
        }
    }

    process {

        try {

            switch ($PsCmdlet.ParameterSetName) {

                # --- Get Project by id
                'ById' {

                    foreach ($ProjectId in $Id){

                        $URI = "$($APIUrl)?`$filter=id eq '$($ProjectId)'"
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($Project in $Response.content) {

                            CalculateOutput $Project
                        }
                    }

                    break
                }
                # --- Get Project by name
                'ByName' {

                    foreach ($ProjectName in $Name){

                        $URI = "$($APIUrl)?`$filter=name eq '$($ProjectName)'"
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($Project in $Response.content){

                            CalculateOutput $Project
                        }
                    }

                    break
                }
                # --- No parameters passed so return all Projects
                'Standard' {

                    $URI = $APIUrl
                    $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                    foreach ($Project in $Response.content){

                        CalculateOutput $Project
                    }
                }
            }
        }
        catch [Exception]{

            throw
        }
    }

    end {

    }
}


<#
    - Function: Get-vAARegion
#>


function Get-vAARegion {
    <#
        .SYNOPSIS
        Get a vRA Region
     
        .DESCRIPTION
        Get a vRA Region
     
        .PARAMETER Id
        The ID of the vRA Region
     
        .PARAMETER Name
        The Name of the vRA Region
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAARegion
     
        .EXAMPLE
        Get-vAARegion -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAARegion -Name 'TestRegion'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/iaas/api/regions'
    
            function CalculateOutput([PSCustomObject]$Region) {
    
                [PSCustomObject] @{
                    ExternalRegionId = $Region.externalRegionId
                    Name = $Region.name
                    CloudAccountId = $Region.cloudAccountId
                    Id = $Region.id
                    UpdatedAt = $Region.updatedAt
                    OrgId = $Region.orgId
                    Links = $Region._links
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get Region by Id
                    'ById' {
    
                        foreach ($RegionId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($RegionId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($Region in $Response.content) {
                                CalculateOutput $Region
                            }
                        }
    
                        break
                    }
                    # --- Get Region by Name
                    'ByName' {
    
                        foreach ($RegionName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($RegionName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($Region in $Response.content) {
                                CalculateOutput $Region
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all Regions
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($Region in $Response.content) {
                            CalculateOutput $Region
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: Get-vAARegionEnumerationvSphere
#>


function Get-vAARegionEnumerationvSphere {
    <#
        .SYNOPSIS
        Retrieve the External Regions Ids for vSphere environment given
 
        .DESCRIPTION
        Retrieve the External Regions Ids for vSphere environment given
 
        .PARAMETER HostName
        vSphere hostname in which this cloud account is created from
 
        .PARAMETER Username
        Username to use when connecting to the vSphere host
 
        .PARAMETER Password
        Password to use when connecting to the vSphere host
 
        .PARAMETER Credential
        Credential object to connect to the vSphere host with
        For domain accounts ensure to specify the Username in the format username@domain, not Domain\Username
 
        .PARAMETER AcceptSelfSignedCertificate
        If set, a self-signed certificate will be accepted
 
        .INPUTS
        System.String
        System.Switch
 
        .OUTPUTS
        System.Management.Automation.PSObject
 
        .EXAMPLE
        Get-vAARegionEnumerationvSphere -HostName "vc.mycompany.com" -Username "administrator@mycompany.com" -Password ("cndhjslacd90ascdbasyoucbdh" | ConvertTo-SecureString -AsPlainText -Force) -AcceptSelfSignedCertificate
 
        .EXAMPLE
        Get-vAARegionEnumerationvSphere -HostName "vc.mycompany.com" -Credential (get-credential) -AcceptSelfSignedCertificate
 
    #>

    [CmdletBinding(DefaultParameterSetName = "Username")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory = $false, ParameterSetName = "Username")]
        [Parameter(Mandatory = $false, ParameterSetName = "Credential")]
        [ValidateNotNullOrEmpty()]
        [String]$HostName,

        [Parameter(Mandatory = $true, ParameterSetName = "Username")]
        [ValidateNotNullOrEmpty()]
        [String]$Username,

        [Parameter(Mandatory = $true, ParameterSetName = "Username")]
        [ValidateNotNullOrEmpty()]
        [SecureString]$Password,

        [Parameter(Mandatory=$true,ParameterSetName="Credential")]
        [ValidateNotNullOrEmpty()]
        [Management.Automation.PSCredential]$Credential,

        [Parameter(Mandatory = $false, ParameterSetName = "Username")]
        [Parameter(Mandatory = $false, ParameterSetName = "Credential")]
        [Switch]$AcceptSelfSignedCertificate

    )

    begin {

        $APIUrl = "/iaas/api/cloud-accounts-vsphere/region-enumeration"

        if ($AcceptSelfSignedCertificate.IsPresent) {

            $AcceptSelfSignedCertificateStatus = 'true'
        }
        else {

            $AcceptSelfSignedCertificateStatus = 'false'
        }

        # --- Convert Secure Credentials to a format for sending in the JSON payload
        if ($PSBoundParameters.ContainsKey("Credential")){

            $Username = $Credential.UserName
            $JSONPassword = $Credential.GetNetworkCredential().Password
        }

        if ($PSBoundParameters.ContainsKey("Password")){

            $JSONPassword = (New-Object System.Management.Automation.PSCredential("username", $Password)).GetNetworkCredential().Password
        }

    }

    process {
        # --- Create new Azure Cloud Account
        try {

            $Body = @"
            {
                "hostName": "$($HostName)",
                "acceptSelfSignedCertificate": $($AcceptSelfSignedCertificateStatus),
                "password": "$($JSONPassword)",
                "username": "$($Username)"
            }
"@


            $Enumeration = Invoke-vAARestMethod -Method POST -URI $APIUrl -Body $Body -Verbose:$VerbosePreference

            if($null -ne $Enumeration -and $Enumeration.PSObject.Properties.name -match "externalRegionIds") {
                $Enumeration.externalRegionIds
            } else {
                return @()
            }
        }
        catch [Exception] {

            throw
        }
    }
    end {

    }
}


<#
    - Function: Get-vAARequest
#>


function Get-vAARequest {
    <#
        .SYNOPSIS
        Retrieve a vRA Request
 
        .DESCRIPTION
        Retrieve a vRA Request or list of requests
 
        .PARAMETER RequestId
        Optional - the id of the request you would like to view the detials
 
        .OUTPUTS
        System.Management.Automation.PSObject.
 
        .EXAMPLE
        Get-vAARequest
 
        .EXAMPLE
        Get-vAARequest -RequestId '305337a3-bb92-4638-a618-bf31e8cd1785'
 
    #>

    [CmdletBinding()][OutputType('System.Management.Automation.PSObject')]

        Param (

            [Parameter(Mandatory=$false, ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$RequestId

        )
        Begin {

            $APIUrl = "/iaas/api/request-tracker"

            function CalculateOutput([PSCustomObject]$Response) {

                if ($Response.content) {
                    foreach ($Record in $Response.content) {
                        [PSCustomObject]@{
                            Name = $Record.name
                            Progress = $Record.progress
                            Id = $Record.id
                            Status = $Record.status
                            Message = $Record.message
                            Resources = $Record.resources
                        }
                    }
                } else {
                    [PSCustomObject]@{
                        Name = $Response.name
                        Progress = $Response.progress
                        Id = $Response.id
                        Status = $Response.status
                        Message = $Response.message
                        Resources = $Response.resources
                    }
                }
            }
        }
        Process {

            try {

                switch ($PsCmdlet.ParameterSetName) {

                    # --- Get Request by its id
                    'ById' {

                        # --- Check to see if the RequestIds's were optionally present
                        $Response = Invoke-vAARestMethod -URI "$APIUrl/$RequestId" -Method GET

                        CalculateOutput $Response

                        break
                    }

                    default {
                        # --- Check to see if the RequestId's were optionally present
                        $Response = Invoke-vAARestMethod -URI "$APIUrl" -Method GET

                        CalculateOutput $Response

                        break
                    }

                }
            }
            catch [Exception]{

                throw
            }
        }
        End {

        }
    }


<#
    - Function: Get-vAASecurityGroup
#>


function Get-vAASecurityGroup {
    <#
        .SYNOPSIS
        Get a vRA Security Group
     
        .DESCRIPTION
        Get a vRA Security Group
     
        .PARAMETER Id
        The ID of the vRA Security Group
     
        .PARAMETER Name
        The Name of the vRA Security Group
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAASecurityGroup
     
        .EXAMPLE
        Get-vAASecurityGroup -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAASecurityGroup -Name 'TestSecurityGroup'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/iaas/api/security-groups'
    
            function CalculateOutput([PSCustomObject]$SecurityGroup) {
    
                [PSCustomObject] @{
                    Rules = $SecurityGroup.rules
                    ExternalRegionId = $SecurityGroup.externalRegionId
                    CloudAccountIds = $SecurityGroup.cloudAccountIds
                    Tags = $SecurityGroup.tags
                    CustomProperties = $SecurityGroup.customProperties
                    ExternalId = $SecurityGroup.externalId
                    Name = $SecurityGroup.name
                    Id = $SecurityGroup.id
                    CreatedAt = $SecurityGroup.createdAt
                    UpdatedAt = $SecurityGroup.updatedAt
                    organizationId = $SecurityGroup.orgId
                    Links = $SecurityGroup._links
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get Security Group by Id
                    'ById' {
    
                        foreach ($SecurityGroupId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($SecurityGroupId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($SecurityGroup in $Response.content) {
                                CalculateOutput $SecurityGroup
                            }
                        }
    
                        break
                    }
                    # --- Get Security Group by Name
                    'ByName' {
    
                        foreach ($SecurityGroupName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($SecurityGroupName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($SecurityGroup in $Response.content) {
                                CalculateOutput $SecurityGroup
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all Security Groups
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($SecurityGroup in $Response.content) {
                            CalculateOutput $SecurityGroup
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: Get-vAAStorageProfile
#>


function Get-vAAStorageProfile {
    <#
        .SYNOPSIS
        Get a vRA Storage Profile
     
        .DESCRIPTION
        Get a vRA Storage Profile
     
        .PARAMETER Id
        The ID of the vRA Storage Profile
     
        .PARAMETER Name
        The Name of the vRA Storage Profile
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAAStorageProfile
     
        .EXAMPLE
        Get-vAAStorageProfile -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAAStorageProfile -Name 'TestStorageProfile'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/iaas/api/storage-profiles'
    
            function CalculateOutput([PSCustomObject]$StorageProfile) {
    
                [PSCustomObject] @{
                    Owner = $StorageProfile.owner
                    Links = $StorageProfile._links
                    SupportsEncryption = $StorageProfile.supportsEncryption
                    ExternalRegionId = $StorageProfile.externalRegionId
                    Description = $StorageProfile.description
                    OrganizationId = $StorageProfile.orgId
                    Tags = $StorageProfile.tags
                    CreatedAt = $StorageProfile.createdAt
                    DiskProperties = $StorageProfile.diskProperties
                    Name = $StorageProfile.name
                    Id = $StorageProfile.id
                    DefaultItem = $StorageProfile.defaultItem
                    UpdatedAt = $StorageProfile.updatedAt
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get Storage Profile by Id
                    'ById' {
    
                        foreach ($StorageProfileId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($StorageProfileId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($StorageProfile in $Response.content) {
                                CalculateOutput $StorageProfile
                            }
                        }
    
                        break
                    }
                    # --- Get Storage Profile by Name
                    'ByName' {
    
                        foreach ($StorageProfileName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($StorageProfileName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($StorageProfile in $Response.content) {
                                CalculateOutput $StorageProfile
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all Storage Profiles
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($StorageProfile in $Response.content) {
                            CalculateOutput $StorageProfile
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: Get-vAATag
#>


function Get-vAATag {
    <#
        .SYNOPSIS
        Get all vRA Tags
     
        .DESCRIPTION
        Get all vRA Tags
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAATag
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
        )
    
        begin {
            $APIUrl = '/iaas/api/tags'
    
            function CalculateOutput([PSCustomObject]$Tag) {
    
                [PSCustomObject] @{
                    Key = $Tag.key
                    Value = $Tag.value
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
                    # --- No parameters passed so return all Tags
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($Tag in $Response.content) {
                            CalculateOutput $Tag
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: Get-vAAvSphereFabricDatastore
#>


function Get-vAAvSphereFabricDatastore {
    <#
        .SYNOPSIS
        Get a only vSphere Fabric Datastore from vRA
     
        .DESCRIPTION
        Get a only vSphere Fabric Datastore from vRA
     
        .PARAMETER Id
        The ID of the vSphere Fabric Datastore
     
        .PARAMETER Name
        The Name of the vSphere Fabric Datastore
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAAvSphereFabricDatastore
     
        .EXAMPLE
        Get-vAAvSphereFabricDatastore -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAAvSphereFabricDatastore -Name 'TestFabricDatastore'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/iaas/api/fabric-vsphere-datastores'
    
            function CalculateOutput([PSCustomObject]$FabricDatastore) {
    
                [PSCustomObject] @{
                    Type = $FabricDatastore.type
                    ExternalRegionId = $FabricDatastore.externalRegionId
                    FreeSizeGB = $FabricDatastore.freeSizeGB
                    CloudAccountIds = $FabricDatastore.cloudAccountIds
                    ExternalId = $FabricDatastore.externalId
                    Name = $FabricDatastore.name
                    Id = $FabricDatastore.id
                    CreatedAt = $FabricDatastore.createdAt
                    UpdatedAt = $FabricDatastore.updatedAt
                    OrganizationId = $FabricDatastore.organizationId
                    Links = $FabricDatastore._links
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get Fabric Datastore by Id
                    'ById' {
    
                        foreach ($FabricDatastoreId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($FabricDatastoreId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($FabricDatastore in $Response.content) {
                                CalculateOutput $FabricDatastore
                            }
                        }
    
                        break
                    }
                    # --- Get Fabric Datastore by Name
                    'ByName' {
    
                        foreach ($FabricDatastoreName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($FabricDatastoreName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($FabricDatastore in $Response.content) {
                                CalculateOutput $FabricDatastore
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all Fabric Datastores
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($FabricDatastore in $Response.content) {
                            CalculateOutput $FabricDatastore
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: Get-vAAvSphereFabricNetwork
#>


function Get-vAAvSphereFabricNetwork {
<#
    .SYNOPSIS
    Retrieve vRA vSphere Fabric Network(s) depending on input
 
    .DESCRIPTION
    Retrieve a list of vRA vSphere Fabric Networks or a single network depending on input
 
    .PARAMETER Id
    The ID of the vRA vSphere Fabric Network
 
    .PARAMETER Name
    The Name of the vRA vSphere Fabric Network
 
    .PARAMETER CloudAccountName
    The name of the vRA Cloud account to search for (optional)
 
    .PARAMETER CloudAccountId
    The ID of the vRA Cloud Account to search for (optional)
 
    .OUTPUTS
    System.Management.Automation.PSObject.
 
    .EXAMPLE
    Get-vAAvSphereFrabricNetwork
 
    .EXAMPLE
    Get-vAAvSphereFrabricNetwork -Id 'b1dd48e71d74267559bb930934470'
 
    .EXAMPLE
    Get-vAAvSphereFrabricNetwork -Name 'my-fabric-network'
 
#>

[CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'CloudAccountName',Justification = 'False positive as rule does not scan child scopes')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'CloudAccountId',Justification = 'False positive as rule does not scan child scopes')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Name,

        [Parameter(Mandatory=$false)]
        [ValidateNotNullOrEmpty()]
        [String[]]$CloudAccountName,

        [Parameter(Mandatory=$false)]
        [ValidateNotNullOrEmpty()]
        [String[]]$CloudAccountId

    )
    Begin {

        $APIUrl = "/iaas/api/fabric-networks-vsphere"

        function CalculateOutput([PSCustomObject]$FabricNetworks) {

            foreach ($FabricNetwork in $FabricNetworks.content) {
                [PSCustomObject]@{
                    ExternalRegionId = $FabricNetwork.externalRegionId
                    DefaultIpv6Gateway = $FabricNetwork.defaultIpv6Gateway
                    Description = $FabricNetwork.description
                    ExternalId = $FabricNetwork.externalId
                    DefaultGateway = $FabricNetwork.defaultGateway
                    OrgId = $FabricNetwork.orgId
                    Tags = $FabricNetwork.tags
                    OrganizationId = $FabricNetwork.organizationId
                    CreatedAt = $FabricNetwork.createdAt
                    Ipv6Cidr = $FabricNetwork.ipv6Cidr
                    CloudAccountIds = $FabricNetwork.cloudAccountIds
                    IsDefault = $FabricNetwork.isDefault
                    Domain = $FabricNetwork.domain
                    DnsServerAddresses = $FabricNetwork.dnsServerAddresses
                    Name = $FabricNetwork.name
                    IsPublic = $FabricNetwork.isPublic
                    Cidr = $FabricNetwork.cidr
                    Id = $FabricNetwork.id
                    UpdatedAt = $FabricNetwork.updatedAt
                    DnsSearchDomains = $FabricNetwork.dnsSearchDomains
                }
            }
        }

        function buildAccountQuery([String[]]$CloudAccountName,
                                    [String[]]$CloudAccountId) {
            $accountIdString = ''
            $cloudAccountIds = @()

            if ($null -ne $CloudAccountName -and "" -ne $CloudAccountName) {
                # pull the ID's from each cloud account
                $cloudAccountIds = Get-vAACloudAccount -Name $CloudAccountName | Select-Object Id | ForEach-Object { $_.Id }
            }
            if ($null -ne $CloudAccountId) {
                $cloudAccountIds = $cloudAccountIds + @($CloudAccountId)
            }
            foreach ($id in $cloudAccountIds) {
                $accountIdString = $accountIdString + ",'$id'"
            }
            Write-Verbose $accountIdString
            if ($accountIdString -ne '') {
                return "cloudAccountIds.item any $($accountIdString.substring(1))"
            } else {
                return ""
            }
        }
    }
    Process {

        try {

            switch ($PsCmdlet.ParameterSetName) {

                # --- Get Network by its id
                'ById' {
                    foreach ($networkId in $Id) {
                        $Response = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=id eq '$networkId'`&`$top=1000" -Method GET
                        CalculateOutput $Response
                    }

                    break
                }

                # --- Get Network by its name
                'ByName' {
                    $acctQuery = buildAccountQuery -CloudAccountName $CloudAccountName -CloudAccountId $CloudAccountId
                    foreach ($networkName in $Name) {
                        if ($null -ne $acctQuery -and '' -ne $acctQuery) {
                            $Response = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$networkName' and $acctQuery`&`$top=1000" -Method GET
                        } else {
                            $Response = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$networkName'`&`$top=1000" -Method GET
                        }
                        CalculateOutput $Response
                    }

                    break
                }

                # --- No parameters passed so return all networks
                'Standard' {
                    $acctQuery = buildAccountQuery -CloudAccountName $CloudAccountName -CloudAccountId $CloudAccountId
                    if ($null -ne $acctQuery -and '' -ne $acctQuery) {
                        $Response = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=$acctQuery`&`$top=1000" -Method GET
                        CalculateOutput $Response
                    } else {
                        $Response = Invoke-vAARestMethod -URI "$APIUrl`?`$top=1000" -Method GET
                        CalculateOutput $Response
                    }
                }

            }


        }
        catch [Exception]{

            throw
        }
    }
    End {

    }
}


<#
    - Function: Get-vAAvSphereFabricStoragePolicy
#>


function Get-vAAvSphereFabricStoragePolicy {
    <#
        .SYNOPSIS
        Get a only vSphere Fabric Storage Policy from vRA
     
        .DESCRIPTION
        Get a only vSphere Fabric Storage Policy from vRA
     
        .PARAMETER Id
        The ID of the vSphere Fabric Storage Policy
     
        .PARAMETER Name
        The Name of the vSphere Fabric Storage Policy
     
        .INPUTS
        System.String
     
        .OUTPUTS
        System.Management.Automation.PSObject
     
        .EXAMPLE
        Get-vAAvSphereFabricStoragePolicy
     
        .EXAMPLE
        Get-vAAvSphereFabricStoragePolicy -Id '3492a6e8-r5d4-1293-b6c4-39037ba693f9'
     
        .EXAMPLE
        Get-vAAvSphereFabricStoragePolicy -Name 'TestFabricStoragePolicy'
     
    #>

    [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
    
        Param (
    
            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,
    
            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name
        )
    
        begin {
            $APIUrl = '/iaas/api/fabric-vsphere-storage-policies'
    
            function CalculateOutput([PSCustomObject]$FabricStoragePolicy) {
    
                [PSCustomObject] @{
                    ExternalRegionId = $FabricStoragePolicy.externalRegionId
                    CloudAccountIds = $FabricStoragePolicy.cloudAccountIds
                    ExternalId = $FabricStoragePolicy.externalId
                    Name = $FabricStoragePolicy.name
                    Description = $FabricStoragePolicy.description
                    Id = $FabricStoragePolicy.id
                    CreatedAt = $FabricStoragePolicy.createdAt
                    UpdatedAt = $FabricStoragePolicy.updatedAt
                    OrganizationId = $FabricStoragePolicy.organizationId
                    Links = $FabricStoragePolicy._links
                }
            }
        }
    
        process {
    
            try {
    
                switch ($PsCmdlet.ParameterSetName) {
    
                    # --- Get vSphere Fabric Storage Policy by Id
                    'ById' {
    
                        foreach ($FabricStoragePolicyId in $Id){
    
                            $URI = "$($APIUrl)?`$filter=id eq '$($FabricStoragePolicyId)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($FabricStoragePolicy in $Response.content) {
                                CalculateOutput $FabricStoragePolicy
                            }
                        }
    
                        break
                    }
                    # --- Get vSphere Fabric Storage Policy by Name
                    'ByName' {
    
                        foreach ($FabricStoragePolicyName in $Name){
    
                            $URI = "$($APIUrl)?`$filter=name eq '$($FabricStoragePolicyName)'"
                            $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference
    
                            foreach ($FabricStoragePolicy in $Response.content) {
                                CalculateOutput $FabricStoragePolicy
                            }
                        }
    
                        break
                    }
                    # --- No parameters passed so return all vSphere Fabric Storage Policies
                    'Standard' {
    
                        $URI = $APIUrl
                        $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        foreach ($FabricStoragePolicy in $Response.content) {
                            CalculateOutput $FabricStoragePolicy
                        }
                    }
                }
            }
            catch [Exception]{
    
                throw
            }
        }
    
        end {
    
        }
    }
    

<#
    - Function: New-vAACloudAccountAzure
#>


function New-vAACloudAccountAzure {
<#
    .SYNOPSIS
    Create a vRA Cloud Account for Azure
 
    .DESCRIPTION
    Create a vRA Cloud Account for Azure
 
    .PARAMETER Name
    The name of the Cloud Account for Azure
 
    .PARAMETER Description
    A description of the Cloud Account for Azure
 
    .PARAMETER SubscriptionId
    Azure SubscriptionId
 
    .PARAMETER TenantId
    Azure TenantId
 
    .PARAMETER ClientApplicationId
    Azure ClientApplicationId
 
    .PARAMETER ClientApplicationSecretKey
    Azure ClientApplicationSecretKey
 
    .PARAMETER RegionIds
    Azure RegionIds to enable
 
    .PARAMETER CreateDefaultZones
    Enable CreateDefaultZones
 
    .PARAMETER JSON
    A JSON string with the body payload
 
    .INPUTS
    System.String
    System.Switch
 
    .OUTPUTS
    System.Management.Automation.PSObject
 
    .EXAMPLE
    New-vAACloudAccountAzure -Name "Azure Test" -SubscriptionId "7326edb0-1234-012e-22d8-76f9faf6982" -TenantId "e7c5cdf4-21d1-312e-bddb-8765949cfdab" -ClientApplicationId "123e710b-4e10-33dc-b9b2-de3d9b1fe234" -ClientApplicationSecretKey "X9Y;bYRpe:eds-TY[blCB1he6PmarC1W" -RegionIds "northeurope","japaneast"
 
    .EXAMPLE
    $JSON = @"
 
        {
            "name": "Azure Test",
            "description": "Azure Test",
            "subscriptionId": "7326edb0-1234-012e-22d8-76f9faf6982",
            "tenantId": "e7c5cdf4-21d1-312e-bddb-8765949cfdab",
            "clientApplicationId": "123e710b-4e10-33dc-b9b2-de3d9b1fe234",
            "clientApplicationSecretKey": "X8Y:bYRpe:wzW-FC[blCB1he7PmarC0W",
            "regionIds": [ "northeurope","japaneast" ],
            "createDefaultZones": false
        }
"@
 
    $JSON | New-vAACloudAccountAzure
 
 
#>

[CmdletBinding(SupportsShouldProcess,ConfirmImpact="Low",DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$Description,

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$SubscriptionId,

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$TenantId,

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$ClientApplicationId,

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$ClientApplicationSecretKey,

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String[]]$RegionIds,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [Switch]$CreateDefaultZones,

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ParameterSetName="JSON")]
        [ValidateNotNullOrEmpty()]
        [String]$JSON

    )

    begin {
        if ($CreateDefaultZones.IsPresent) {

            $CreateDefaultZonesStatus = 'true'
        }
        else {

            $CreateDefaultZonesStatus = 'false'
        }
    }

    process {

            if ($PSBoundParameters.ContainsKey("JSON")) {

                $Data = ($JSON | ConvertFrom-Json)

                $Body = $JSON
                $Name = $Data.name
            }
            else {

                # Format RegionIds with surrounding quotes and join into single string
                $RegionIdsAddQuotes = $RegionIDs | ForEach-Object {"`"$_`""}
                $RegionIdsFormatForBodyText = $RegionIdsAddQuotes -join ","

                $Body = @"
                    {
                        "name": "$($Name)",
                        "description": "$($Description)",
                        "subscriptionId": "$($SubscriptionId)",
                        "tenantId": "$($TenantId)",
                        "clientApplicationId": "$($ClientApplicationId)",
                        "clientApplicationSecretKey": "$($ClientApplicationSecretKey)",
                        "regionIds": [ $($RegionIdsFormatForBodyText) ],
                        "createDefaultZones": $($CreateDefaultZonesStatus)
                    }
"@

            }

        # --- Create new Azure Cloud Account
        try {
            if ($PSCmdlet.ShouldProcess($Name)){

                $URI = "/iaas/api/cloud-accounts-azure"
                $CloudAccount = Invoke-vAARestMethod -Method POST -URI $URI -Body $Body -Verbose:$VerbosePreference

                [PSCustomObject] @{

                    Name = $CloudAccount.name
                    Description = $CloudAccount.description
                    Id = $CloudAccount.id
                    CloudAccountType = 'azure'
                    SubscriptionId = $CloudAccount.subscriptionId
                    TenantId = $CloudAccount.tenantId
                    ClientApplicationId = $CloudAccount.clientApplicationId
                    EnabledRegionIds = $CloudAccount.enabledRegionIds
                    CustomProperties = $CloudAccount.customProperties
                    OrganizationId = $CloudAccount.organizationId
                    Links = $CloudAccount._links
                }
            }
        }
        catch [Exception] {

            throw
        }
    }
    end {

    }
}

<#
    - Function: New-vAACloudAccountGCP
#>


function New-vAACloudAccountGCP {
<#
    .SYNOPSIS
    Create a vRA Cloud Account for GCP
 
    .DESCRIPTION
    Create a vRA Cloud Account for GCP
 
    .PARAMETER Name
    The name of the Cloud Account for GCP
 
    .PARAMETER Description
    A description of the Cloud Account for GCP
 
    .PARAMETER ProjectId
    GCP Project Id
 
    .PARAMETER PrivateKeyId
    GCP Private Key Id
 
    .PARAMETER PrivateKey
    GCP Private Key
 
    .PARAMETER ClientEmail
    GCP Client Email
 
    .PARAMETER RegionIds
    GCP RegionIds to enable
 
    .PARAMETER CreateDefaultZones
    Enable CreateDefaultZones
 
    .PARAMETER JSON
    A JSON string with the body payload
 
    .INPUTS
    System.String
    System.Switch
 
    .OUTPUTS
    System.Management.Automation.PSObject
 
    .EXAMPLE
    $privateKey = @"
-----BEGIN PRIVATE KEY-----
\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDbw8OMwHfait
cx\nKRqp7k2IppvEyuKTPPCNygZvb9HZ6LWV84GWt+RLJ+k5ZmhJ9254qNcV5RUn
sKcF\nhLPD1IPPOGlLTUZ492lH+3k6Uh3RxoGo2fdOuc1SVa/GXREXB0KXj5lYYw
Vjvsu/\n5QYUWwJbUSVd52Q1O4d0toezA/zw54NM5Ijv6P1J2bJ7szODCbh7obb5
J7vtsjfi\n6cik3frRaf13yX/GGghPXOockJ3s7MM4rgfJHSHuQVWOkPaJPiGFd2
d4XMpizAU2\n2hMGbFiAmONgl2HPaw3mqEP3owv1F7ZQ0TWUB1iq3T8xddkacsmB
hyzL4KgPKocR\ng6fh3sjJAgMBAAECggEAFYn+FkM96/w8I5wW+i06SaikrzjAVL
R+EjOJBm6D95LM\ni1YaryI2XJxciizsj0VSPT61F/cEKAfzEsIjGVAwnAR4I3J/
M/dxyOWPh+UI+ai2\nSA2W5M8mncl6qRsxg9uJDhA7tBM+cbx/PT9N5XxXAoq1Oh
sl8eaz+78xFR1Qsu6b\nSwAmL6I2iRR/qijsGYPPyKruEZU3AZg+OETgoHe97F/i
T/dXyIh2YAtaC+g7lpK9\nOA8XavfYHF7tmQ8MnIT0Ez9u2WC5VHJas8+fnQdxkj
o6jwWTgp36hkGcRt+HGLqW\nWDEdzw7TAMTy6KZLZNq39lIwFv24hoyFLECL9o9N
JQKBgQD/gFa3BS/utfmC+oBu\nPIGk/HCTPiQ9bj3leDC8vzmAj3Sohz54xNjvrX
J7XhYGJB3kI+uzjgY0qh45Z/18\ng/bxCEbCW6hgYEkGJu9Pf8hO1E0sMVo3wEFs
ZKymR51+8aqOb27bS/IN5GmLuMby\nZDGZJHELLOjk7PcHJDMo2wsWpQKBgQDcMZ
G/jWLQQJjOGii/I+u7cAB2zOCeBV4w\nlTHEREzOWPZj9gblvBXFlXtaPPpopLdT
RF+rGlP96Dgx0o4wZTT94oL41eYntDBZ\nwY8FJDdPC08AjtYT15ramdc/K+3q+1
QVfG63vC+iSyRP9YBrGFV2bZ8sntQmpC1a\naZMBhz/0VQKBgDlwE45vZxgl5qKw
R+EATzDU40XmqWT5/IYyn9o+ruGc3l/oj328\n2vv+pQbg3tigk+uuu5UQ74o1WD
gVjaHJVOFYt/eHfXG1E5WDeTcHGsHavkKaEasI\n2GxSsZFr9hcMowgEOwqnpxHC
cIvNjUP+jDveL/i8kxKrxtjfJXUg0PxVAoGASjjf\nQy1acI5Fs7t3nq5yCJWC06
Oa10lB7aggRTAohLnSG/HTc18KC7cOhGVnlxxmu0eh\n4+AVDdJYFts9mKyUxzuy
IEShtyJy5d5r4jTJ+/f44lxDZx7XEPaoap/ZK8saFcAC\n5iYl/FPN4rIDXpYuQK
RE8lp7cqcGrqJFrk8zzJ0CgYEAoWa1k6fkuO4XgopiDOgj\n7/sZr6k3fPp9dJYm
roPjeLPtR1AFJJ4NBHlX+r06nZeovTpm3dKPmg01FXV5mUYq\nW1me90GFekjz6W
N/2DOnL7ChnG8ZJp45SKq26g6D+OU5rg83KuNMJQ0w3dXuR2ch\nnLxRJH0dt7oA
44aMzP39X/s=\n
-----END PRIVATE KEY-----
"@
 
    New-vAACloudAccountGCP -Name "GCP Test" -ProjectId "third-folio-255713" -PrivateKeyId "6226de83c0c6c267f4c80fc9c5ac7dda0293ed9e" -PrivateKey $privateKey -clientEmail "321743978432-compute@developer.gserviceaccount.com" -RegionIds "europe-west1","us-west1"
 
    .EXAMPLE
    $JSON = @"
 
        {
            "name": "GCP Test",
            "description": "GCP Test",
            "projectId": "third-folio-255713",
            "privateKeyId": "6226de83c0c6c267f4c80fc9c5ac7dda0293ed9e",
            "privateKey": "-----BEGIN PRIVATE KEY-----\nMIICXgIHAASBgSDHikastc8+I81zCg/qWW8dMr8mqvXQ3qbPAmu0RjxoZVI47tvs\nkYlFAXOf0sPrhO2nUuooJngnHV0639iTHELLOvckNaW2RTHEREdQ5Rq5u+uV3pMk\n7w7Vs4n3urQ4jnqt7rTXbC1DNa/PFeAZatbf7ffBBy0IGO0zc128IshYcwIDAQAB\nAoGBALTNl2JxTvq4SDW/3VH0fZkQXWH1MM10oeMbB2qO5beWb11FGaOO77nGKfWc\nbYgfp5Ogrql2yhBvLAXnxH8bcqqwORtFhlyV68U1y4R+8WxDNh0aevxH8hRS/1X5\n963DJm1JlU0E+vStiktN0tC3ebH5hE+1OxbIHSZ+WOWLYX7JAkEA5uigRgKp8ScG\nauUijvdOLZIhHWq9y5Wz+nOHUuDw8P7wOTKU34QJAoWEe771p9Pf/GTA/kr0BQnP\nQvWUDxGzJwJBAN05C6krwPeryFKrKtjOGJIbiIoY72wRnoNcdEEs3HDRhf48YWFo\nriRbZylzzzNFy/gmzT6XJQTfktGqq+FZD9UCQGIJaGrxHJgfmpDuAhMzGsUsYtTr\niRox0D1Iqa7dhE693t5aBG010OF6MLqdZA1CXrn5SRtuVVaCSLZEL/2J5UcCQQDA\nd3MXucNnN4NPuS/L9HMYJWD7lPoosaORcgyK77bSSNgk+u9WSjbH1uYIAIPSffUZ\nbti+jc2dUg5wb+aeZlgJAkEAurrpmpqj5vg087ZngKfFGR5rozDiTsK5DceTV97K\na1Y+Nzl+XWTxDBWk4YPh2ZlKv402hZEfWBYxUDn5ZkH/bw==\n-----END PRIVATE KEY-----\n",
            "clientEmail": "321743978432-compute@developer.gserviceaccount.com",
            "regionIds": [ "europe-west1","us-west1" ],
            "createDefaultZones": false
        }
"@
 
    $JSON | New-vAACloudAccountGCP
 
 
#>

[CmdletBinding(SupportsShouldProcess,ConfirmImpact="Low",DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$Description,

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$ProjectId,

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$PrivateKeyId,

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$PrivateKey,

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$ClientEmail,

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String[]]$RegionIds,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [Switch]$CreateDefaultZones,

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ParameterSetName="JSON")]
        [ValidateNotNullOrEmpty()]
        [String]$JSON

    )

    begin {
        if ($CreateDefaultZones.IsPresent) {

            $CreateDefaultZonesStatus = 'true'
        }
        else {

            $CreateDefaultZonesStatus = 'false'
        }
    }

    process {

            if ($PSBoundParameters.ContainsKey("JSON")) {

                $Data = ($JSON | ConvertFrom-Json)

                $Body = $JSON
                $Name = $Data.name
            }
            else {

                # Format RegionIds with surrounding quotes and join into single string
                $RegionIdsAddQuotes = $RegionIDs | ForEach-Object {"`"$_`""}
                $RegionIdsFormatForBodyText = $RegionIdsAddQuotes -join ","

                $Body = @"
                    {
                        "name": "$($Name)",
                        "description": "$($Description)",
                        "projectId": "$($ProjectId)",
                        "privateKeyId": "$($PrivateKeyId)",
                        "privateKey": "$($PrivateKey)",
                        "clientEmail": "$($ClientEmail)",
                        "regionIds": [ $($RegionIdsFormatForBodyText) ],
                        "createDefaultZones": $($CreateDefaultZonesStatus)
                    }
"@

            }

        # --- Create new GCP Cloud Account
        try {
            if ($PSCmdlet.ShouldProcess($Name)){

                $URI = "/iaas/api/cloud-accounts-gcp"
                $CloudAccount = Invoke-vAARestMethod -Method POST -URI $URI -Body $Body -Verbose:$VerbosePreference

                [PSCustomObject] @{

                    Name = $CloudAccount.name
                    Description = $CloudAccount.description
                    Id = $CloudAccount.id
                    CloudAccountType = 'gcp'
                    ProjectId = $CloudAccount.projectId
                    PrivateKeyId = $CloudAccount.privateKeyId
                    ClientEmail = $CloudAccount.clientEmail
                    EnabledRegionIds = $CloudAccount.enabledRegionIds
                    CustomProperties = $CloudAccount.customProperties
                    OrganizationId = $CloudAccount.organizationId
                    Links = $CloudAccount._links
                }
            }
        }
        catch [Exception] {

            throw
        }
    }
    end {

    }
}

<#
    - Function: New-vAACloudAccountvSphere
#>


function New-vAACloudAccountvSphere {
    <#
        .SYNOPSIS
        Create a vRA Cloud Account for vSphere
 
        .DESCRIPTION
        Create a vRA Cloud Account for vSphere
 
        .PARAMETER Name
        The name of the Cloud Account for vSphere
 
        .PARAMETER Description
        A description of the Cloud Account for vSphere
 
        .PARAMETER HostName
        vSphere hostname in which this cloud account is created from
 
        .PARAMETER Username
        Username to use when connecting to the vSphere host
 
        .PARAMETER Password
        Password to use when connecting to the vSphere host
 
        .PARAMETER Credential
        Credential object to connect to the vSphere host with
        For domain accounts ensure to specify the Username in the format username@domain, not Domain\Username
 
        .PARAMETER DCId
        Optional - Identifier of a data collector vm deployed in the on-prem infrastructure
 
        .PARAMETER AssociatedCloudAccountIds
        Optional - Any associated cloud accounts you would like to build into
 
        .PARAMETER RegionIds
        Optional - vSphere RegionIds to enable (note: if not supplied, all regions available will be added to the cloud account)
 
        .PARAMETER CreateDefaultZones
        Enable CreateDefaultZones
 
        .PARAMETER AcceptSelfSignedCertificate
        If set, a self-signed certificate will be accepted
 
        .PARAMETER JSON
        A JSON string with the body payload
 
        .INPUTS
        System.String
        System.Switch
 
        .OUTPUTS
        System.Management.Automation.PSObject
 
        .EXAMPLE
        New-vAACloudAccountvSphere -Name "vSphere Test" -HostName "vc.mycompany.com" -Username "administrator@mycompany.com" -Password ("cndhjslacd90ascdbasyoucbdh" | ConvertTo-SecureString -AsPlainText -Force) -RegionIds "Datacenter:datacenter-2" -CreateDefaultZones -AcceptSelfSignedCertificate
 
        .EXAMPLE
        New-vAACloudAccountvSphere -Name "vSphere Test" -HostName "vc.mycompany.com" -Credential (get-credential) -CreateDefaultZones -AcceptSelfSignedCertificate
 
        .EXAMPLE
        $JSON = @"
 
            {
                "hostName": "vc.mycompany.com",
                "acceptSelfSignedCertificate": false,
                "associatedCloudAccountIds": "[ "42f3e0d199d134755684cd935435a" ]",
                "password": "cndhjslacd90ascdbasyoucbdh",
                "createDefaultZones": true,
                "dcid": "23959a1e-18bc-4f0c-ac49-b5aeb4b6eef4",
                "name": "string",
                "description": "string",
                "regionIds": "[ "Datacenter:datacenter-2" ]",
                "username": "administrator@mycompany.com"
            }
 
"@
 
        $JSON | New-vAACloudAccountvSphere
 
 
    #>

    [CmdletBinding(SupportsShouldProcess, ConfirmImpact = "Low", DefaultParameterSetName = "Username")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory = $false, ParameterSetName = "Username")]
        [Parameter(Mandatory = $false, ParameterSetName = "Credential")]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter(Mandatory = $false, ParameterSetName = "Username")]
        [Parameter(Mandatory = $false, ParameterSetName = "Credential")]
        [ValidateNotNullOrEmpty()]
        [String]$Description,

        [Parameter(Mandatory = $false, ParameterSetName = "Username")]
        [Parameter(Mandatory = $false, ParameterSetName = "Credential")]
        [ValidateNotNullOrEmpty()]
        [String]$HostName,

        [Parameter(Mandatory = $true, ParameterSetName = "Username")]
        [ValidateNotNullOrEmpty()]
        [String]$Username,

        [Parameter(Mandatory = $true, ParameterSetName = "Username")]
        [ValidateNotNullOrEmpty()]
        [SecureString]$Password,

        [Parameter(Mandatory=$true,ParameterSetName="Credential")]
        [ValidateNotNullOrEmpty()]
        [Management.Automation.PSCredential]$Credential,

        [Parameter(Mandatory = $false, ParameterSetName = "Username")]
        [Parameter(Mandatory = $false, ParameterSetName = "Credential")]
        [ValidateNotNullOrEmpty()]
        [String]$DCId,

        [Parameter(Mandatory = $false, ParameterSetName = "Username")]
        [Parameter(Mandatory = $false, ParameterSetName = "Credential")]
        [ValidateNotNullOrEmpty()]
        [String[]]$AssociatedCloudAccountIds,

        [Parameter(Mandatory = $false, ParameterSetName = "Username")]
        [Parameter(Mandatory = $false, ParameterSetName = "Credential")]
        [ValidateNotNullOrEmpty()]
        [String[]]$RegionIds,

        [Parameter(Mandatory = $false, ParameterSetName = "Username")]
        [Parameter(Mandatory = $false, ParameterSetName = "Credential")]
        [Switch]$CreateDefaultZones,

        [Parameter(Mandatory = $false, ParameterSetName = "Username")]
        [Parameter(Mandatory = $false, ParameterSetName = "Credential")]
        [Switch]$AcceptSelfSignedCertificate,

        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ParameterSetName = "JSON")]
        [ValidateNotNullOrEmpty()]
        [String]$JSON

    )

    begin {

        $APIUrl = "/iaas/api/cloud-accounts-vsphere"

        if ($CreateDefaultZones.IsPresent) {

            $CreateDefaultZonesStatus = 'true'
        }
        else {

            $CreateDefaultZonesStatus = 'false'
        }

        if ($AcceptSelfSignedCertificate.IsPresent) {

            $AcceptSelfSignedCertificateStatus = 'true'
        }
        else {

            $AcceptSelfSignedCertificateStatus = 'false'
        }

        # --- Convert Secure Credentials to a format for sending in the JSON payload
        if ($PSBoundParameters.ContainsKey("Credential")){

            $Username = $Credential.UserName
            $JSONPassword = $Credential.GetNetworkCredential().Password
        }

        if ($PSBoundParameters.ContainsKey("Password")){

            $JSONPassword = (New-Object System.Management.Automation.PSCredential("username", $Password)).GetNetworkCredential().Password
        }
        function CalculateOutput([PSCustomObject]$CloudAccount) {
            [PSCustomObject] @{
                Name                = $CloudAccount.name
                HostName            = $CloudAccount.HostName
                Username            = $CloudAccount.username
                Description         = $CloudAccount.description
                Id                  = $CloudAccount.id
                CloudAccountType    = 'vsphere'
                EnabledRegionIds    = $CloudAccount.enabledRegionIds
                CustomProperties    = $CloudAccount.customProperties
                OrganizationId      = $CloudAccount.organizationId
                Links               = $CloudAccount._links
            }
        }
    }

    process {
        # --- Create new Azure Cloud Account
        try {
            if ($PSBoundParameters.ContainsKey("JSON")) {

                $Data = ($JSON | ConvertFrom-Json)
                $Body = $JSON
                # have to handle if regionid's were not provided
                if ($null -eq $Data.regionIds) {
                    # region ids were not natively passed
                    $RegionIdProcessing = ProcessReqionIds
                    $Data | Add-Member -NotePropertyName regionIds -NotePropertyValue $RegionIdProcessing -Force
                    $JSON = $Data | ConvertTo-Json
                    Write-Verbose $JSON
                }
                $Body = $JSON
                $Name = $Data.name
            }
            else {

                # Format AssociatedCloudAccountIds with surrounding quotes and join into single string
                $AssociatedCloudAccountIdsAddQuotes = $AssociatedCloudAccountIds | ForEach-Object { "`"$_`"" }
                $AssociatedCloudAccountIdsFormatForBodyText = $AssociatedCloudAccountIdsAddQuotes -join ","

                if ($null -eq $RegionIds) {
                    # process to see if regions were given, if not, we pull all of them
                    if ($PSBoundParameters.ContainsKey("Credential")){
                        $RegionIDs = Get-vAARegionEnumerationvSphere -HostName $HostName  -Credential $Credential -AcceptSelfSignedCertificate:$($AcceptSelfSignedCertificate)
                    } else {
                        # assume username and password
                        $RegionIDs = Get-vAARegionEnumerationvSphere -HostName $HostName  -Username $Username -Password $Password -AcceptSelfSignedCertificate:$($AcceptSelfSignedCertificate)
                    }
                }

                # Format RegionIds with surrounding quotes and join into single string
                $RegionIdsAddQuotes = $RegionIDs | ForEach-Object { "`"$_`"" }
                $RegionIdsFormatForBodyText = $RegionIdsAddQuotes -join ","

                $Body = @"
                            {
                                "hostName": "$($HostName)",
                                "acceptSelfSignedCertificate": $($AcceptSelfSignedCertificateStatus),
                                "associatedCloudAccountIds": [ $($AssociatedCloudAccountIdsFormatForBodyText) ],
                                "password": "$($JSONPassword)",
                                "createDefaultZones": $($CreateDefaultZonesStatus),
                                "dcid": "$($DCId)",
                                "name": "$($Name)",
                                "description": "$($Description)",
                                "regionIds": [ $($RegionIdsFormatForBodyText) ],
                                "username": "$($Username)"
                            }
"@

            }


            if ($PSCmdlet.ShouldProcess($Name)) {

                $CloudAccount = Invoke-vAARestMethod -Method POST -URI $APIUrl -Body $Body -Verbose:$VerbosePreference

                CalculateOutput $CloudAccount
            }
        }
        catch [Exception] {

            throw
        }
    }
    end {

    }
}


<#
    - Function: New-vAAMachineAttachedDisk
#>


function New-vAAMachineAttachedDisk {
<#
    .SYNOPSIS
    Retrieve a vRA Machine's Disks
 
    .DESCRIPTION
    Retrieve the disks for a vRA Machine
 
    .PARAMETER Id
    The ID of the vRA Machine
 
    .PARAMETER Name
    The Name of the vRA Machine
 
    .PARAMETER blockDeviceId
    The Id of the individual Disk to attach (Block Device ID)
 
    .PARAMETER DeviceName
    The name we wish to give the device as we attach it to the machine
 
    .PARAMETER DeviceDescription
    A description we can associate with the disk after attaching it to the machine
 
    .PARAMETER WaitForCompletion
    If this flag is added, this function will wait for the request to complete and will return the created Virtual Disk
 
    .PARAMETER CompletionTimeout
    The default of this paramter is 2 minutes (120 seconds), but this parameter can be overriden here
 
    .PARAMETER Force
    Force this change
 
    .OUTPUTS
    System.Management.Automation.PSObject.
 
    .EXAMPLE
    New-vAAMachineAttachedDisk -Id 'b1dd48e71d74267559bb930934470' -BlockDeviceId'123456'
 
    .EXAMPLE
    New-vAAMachineAttachedDisk -Name 'iaas01' -BlockDeviceId'123456'
 
    .EXAMPLE
    New-vAAMachineAttachedDisk -Name 'iaas01' -BlockDeviceId'123456' -WaitForCompletion
 
    .EXAMPLE
    New-vAAMachineAttachedDisk -Name 'iaas01' -BlockDeviceId'123456' -WaitForCompletion -CompletionTimeout 300
 
    .EXAMPLE
    New-vAAMachineAttachedDisk -Name 'iaas01' -BlockDeviceId'123456' -DeviceName 'Disk 17' -DeviceDescription 'This is a disk attached from script'
 
#>

[CmdletBinding(SupportsShouldProcess,ConfirmImpact="High",DefaultParameterSetName="ByName")][OutputType('System.Management.Automation.PSObject')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'WaitForCompletion',Justification = 'False positive as rule does not scan child scopes')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'CompletionTimeout',Justification = 'False positive as rule does not scan child scopes')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter(Mandatory=$true,ParameterSetName="ByName")]
        [Parameter(Mandatory=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$BlockDeviceId,

        [Parameter(Mandatory=$false)]
        [ValidateNotNullOrEmpty()]
        [String[]]$DeviceName,

        [Parameter(Mandatory=$false)]
        [ValidateNotNullOrEmpty()]
        [String[]]$DeviceDescription,

        [Parameter()]
        [switch]$WaitForCompletion,

        [Parameter()]
        [int]$CompletionTimeout = 120,

        [Parameter()]
        [switch]$Force

    )
    Begin {

        $APIUrl = "/iaas/api/machines"

        function CalculateOutput([String[]]$BlockDeviceId,[int]$CompletionTimeout,[switch]$WaitForCompletion,[PSCustomObject]$RestResponse) {

            if ($WaitForCompletion.IsPresent) {
                # if the wait for completion flag is given, the output will be different, we will wait here
                # we will use the built-in function to check status
                $ElapsedTime = 0
                    do {
                        $RequestResponse = Get-vAARequest -RequestId $RestResponse.id
                        if ($RequestResponse.Status -eq "FINISHED") {
                            foreach ($Resource in $RequestResponse.Resources) {
                                $Response = Invoke-vAARestMethod -URI "$Resource/disks/$BlockDeviceId" -Method GET
                                [PSCustomObject]@{
                                    Name = $Response.name
                                    Status = $Response.status
                                    Owner = $Response.owner
                                    ExternalRegionId = $Response.externalRegionId
                                    ExternalZoneId = $Response.externalZoneId
                                    Description = $Response.description
                                    Tags = $Response.tags
                                    CapacityInGB = $Response.capacityInGB
                                    CloudAccountIDs = $Response.cloudAccountIds
                                    ExternalId = $Response.externalId
                                    Id = $Response.id
                                    DateCreated = $Response.createdAt
                                    LastUpdated = $Response.updatedAt
                                    OrganizationId = $Response.orgId
                                    Properties = $Response.customProperties
                                    ProjectId = $Response.projectId
                                    Persistent = $Response.persistent
                                    RequestId = $Response.id
                                    RequestStatus = "FINISHED"
                                }
                            }
                            break # leave loop as we are done here
                        }
                        $ElapsedTime += 5
                        Start-Sleep -Seconds 5
                    } while ($ElapsedTime -lt $CompletionTimeout)

                    if ($ElapsedTime -gt $CompletionTimeout -or $ElapsedTime -eq $CompletionTimeout) {
                        # we have errored out
                        [PSCustomObject]@{
                            Name = $RestResponse.name
                            Progress = $RestResponse.progress
                            Resources = $RestResponse.resources
                            RequestId = $RestResponse.id
                            Message = "We waited for completion, but we hit a timeout at $CompletionTimeout seconds. You may use Get-vAARequest -RequestId $($RestResponse.id) to continue checking status. Here was the original response: $($RestResponse.message)"
                            RequestStatus = $RestResponse.status
                        }
                    }
            } else {
                [PSCustomObject]@{
                    Name = $RestResponse.name
                    Progress = $RestResponse.progress
                    Resources = $RestResponse.resources
                    RequestId = $RestResponse.id
                    Message = $RestResponse.message
                    RequestStatus = $RestResponse.status
                }
            }
        }
    }
    Process {

        try {

            $Body = @"
                {
                    "blockDeviceId": "$($BlockDeviceId)",
                    "name": "$($DeviceName)",
                    "description": "$($DeviceDescription)"
                }
"@

            Write-Verbose -Message $Body

            switch ($PsCmdlet.ParameterSetName) {

                # --- Get Machine Attached Disk by its id
                'ById' {
                    if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($Id)){
                        # --- Check to see if the DiskId's were optionally present
                        $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$Id`/disks" -Method GET -Body $Body

                        CalculateOutput $BlockDeviceId $CompletionTimeout $WaitForCompletion $RestResponse
                    }
                    break
                }

                # --- Get Machine Attached Disk by its name
                # --- Will need to retrieve the machine first, then use ID to get final output
                'ByName' {
                    if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($Name)){
                        $MachineResponse = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$Name'`&`$select=id" -Method GET
                        $MachineId = $MachineResponse.content[0].id

                        $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId`/disks" -Method POST -Body $Body

                        CalculateOutput $BlockDeviceId $CompletionTimeout $WaitForCompletion $RestResponse
                    }
                    break
                }

            }
        }
        catch [Exception]{

            throw
        }
    }
    End {

    }
}


<#
    - Function: New-vAANetworkProfile
#>


function New-vAANetworkProfile {
<#
    .SYNOPSIS
    Create a vRA Network Profile
 
    .DESCRIPTION
    Create a vRA Network Profile
 
    .PARAMETER Name
    The name of the Network Profile
 
    .PARAMETER Description
    A description of the Network Profile
 
    .PARAMETER Description
    A description of the Network Profile
 
    .PARAMETER IsolationNetworkDomainCIDR
    CIDR of the isolation network domain
 
    .PARAMETER IsolationNetworkDomainId
    The Id of the network domain used for creating isolated networks.
 
    .PARAMETER FabricNetworkIds
    Id's of the Fabric networks you would like to associate with this profile
 
    .PARAMETER RegionId
    The Id of the region for which this profile is created
 
    .PARAMETER SecurityGroupIds
    A list of security group Ids which are assigned to the network profile
 
    .PARAMETER Name
    A human-friendly name used as an identifier in APIs that support this option.
 
    .PARAMETER IsolationExternalFabricNetworkId
    The Id of the fabric network used for outbound access.
 
    .PARAMETER IsolationType
    Specifies the isolation type e.g. none, subnet or security group
 
    .PARAMETER IsolatedNetworkCIDRPrefix
    The CIDR prefix length to be used for the isolated networks that are created with the network profile.
 
    .PARAMETER LoadBalancerIds
    A list of load balancers which are assigned to the network profile.
 
    .PARAMETER Tags
    A array of tags to tag the created network profile with
 
    .PARAMETER JSON
    A JSON string with the body payload
 
    .INPUTS
    System.String
    System.Switch
    PSCustomObject
 
    .OUTPUTS
    System.Management.Automation.PSObject
 
    .EXAMPLE
    $ProfileArguments = @{
 
        Name = 'My Profile'
        Description = 'Test Profile'
        RegionId = '9e49'
        fabricNetworkIds = '6543','6542'
        Tags = 'placement:coems','mytag2:2'
    }
 
    New-vAANetworkProfile @ProfileArguments
 
    .EXAMPLE
    $JSON = @"
       {
        "description": "string",
        "isolationNetworkDomainCIDR": "10.10.10.0/24",
        "isolationNetworkDomainId": "1234",
        "fabricNetworkIds": "[ \"6543\" ]",
        "regionId": "9e49",
        "securityGroupIds": "[ \"6545\" ]",
        "name": "string",
        "isolationExternalFabricNetworkId": "1234",
        "isolationType": "SUBNET",
        "isolatedNetworkCIDRPrefix": 24,
        "loadBalancerIds": "[ \"6545\" ]",
        "Tags": [ "placement:coems", "mytag2:2"]
        }
"@
 
    $JSON | New-vAANetworkProfile
#>

[CmdletBinding(SupportsShouldProcess,ConfirmImpact="Low",DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$Description,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$IsolationNetworkDomainCIDR,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$IsolationNetworkDomainId,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String[]]$FabricNetworkIds,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$RegionId,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String[]]$SecurityGroupIds,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$IsolationExternalFabricNetworkId,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$IsolationType,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [int]$IsolatedNetworkCIDRPrefix,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String[]]$LoadBalancerIds,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Tags,

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ParameterSetName="JSON")]
        [ValidateNotNullOrEmpty()]
        [String]$JSON

    )

    begin {
        function CalculateOutput([PSCustomObject]$NetworkProfile) {

            [PSCustomObject] @{

                Owner = $NetworkProfile.owner
                Links = $NetworkProfile._links
                ExternalRegionId = $NetworkProfile.externalRegionId
                Description = $NetworkProfile.description
                IsolationNetworkDomainCIDR = $NetworkProfile.isolationNetworkDomainCIDR
                OrgId = $NetworkProfile.orgId
                Tags = $NetworkProfile.tags
                OrganizationId = $NetworkProfile.organizationId
                CreatedAt = $NetworkProfile.createdAt
                CustomProperties = $NetworkProfile.customProperties
                Name = $NetworkProfile.name
                Id = $NetworkProfile.id
                IsolationType = $NetworkProfile.isolationType
                IsolatedNetworkCIDRPrefix = $NetworkProfile.isolatedNetworkCIDRPrefix
                UpdatedAt = $NetworkProfile.updatedAt

        }
    }
}

    process {

            if ($PSBoundParameters.ContainsKey("JSON")) {

                $Data = ($JSON | ConvertFrom-Json)

                $Body = $JSON
                $Name = $Data.name
            }
            else {

                $FabricNetworkIdJson = ($FabricNetworkIds | ForEach-Object {"`"$_`""}) -join ","
                $SecurityGroupIdJson = ($SecurityGroupIds | ForEach-Object {"`"$_`""}) -join ","
                $LoadBalancerIdJson = ($LoadBalancerIds | ForEach-Object {"`"$_`""}) -join ","
                if($FabricNetworkIdJson -eq "`"`"") {
                    $FabricNetworkIdJson = $null
                }
                if($SecurityGroupIdJson -eq "`"`"") {
                    $SecurityGroupIdJson = $null
                }
                if($LoadBalancerIdJson -eq "`"`"") {
                    $LoadBalancerIdJson = $null
                }

                # handle Tags
                $TagsJson = "null"
                if ($null -ne $Tags) {
                    $TagsJson = ($Tags | ForEach-Object { 
                        $TagSplit = $_.Split(":")
                        [PSCustomObject]@{
                            key = $TagSplit[0]
                            value = $TagSplit[1]
                        }   
                    }) | ConvertTo-Json -Depth 5 -Compress
                }
                

                $Body = @"
                    {
                        "name": "$($Name)",
                        "description": "$($Description)",
                        "isolationNetworkDomainCIDR": "$($IsolationNetworkDomainCIDR)",
                        "isolationNetworkDomainId": "$($IsolationNetworkDomainId)",
                        "fabricNetworkIds": [ $($FabricNetworkIdJson) ],
                        "regionId": "$($RegionId)",
                        "securityGroupIds": [ $($SecurityGroupIdJson) ],
                        "isolationExternalFabricNetworkId": "$($IsolationExternalFabricNetworkId)",
                        "isolationType": "$($IsolationType)",
                        "loadBalancerIds": [ $($LoadBalancerIdJson) ],
                        "tags": [$($TagsJson)]
                    }
"@

                Write-Verbose $Body
                $JSONObject = $Body | ConvertFrom-Json

                if ($IsolatedNetworkCIDRPrefix -gt 0) {
                    $JSONObject | Add-Member -NotePropertyName isolatedNetworkCIDRPrefix -NotePropertyValue $IsolatedNetworkCIDRPrefix
                }

                $Body = $JSONObject | ConvertTo-Json -Depth 5
            }

        # --- Create new Network Profile
        try {
            if ($PSCmdlet.ShouldProcess($Name)){

                $URI = "/iaas/api/network-profiles"
                $Response = Invoke-vAARestMethod -Method POST -URI $URI -Body $Body -Verbose:$VerbosePreference
                CalculateOutput $Response
                
            }
        }
        catch [Exception] {

            throw
        }
    }
    end {

    }
}


<#
    - Function: New-vAAProject
#>


function New-vAAProject {
<#
    .SYNOPSIS
    Create a vRA Cloud Project
 
    .DESCRIPTION
    Create a vRA Cloud Project
 
    .PARAMETER Name
    The name of the Project
 
    .PARAMETER Description
    A description of the Project
 
    .PARAMETER Zones
    PSCustomObject(s) with properties for a Cloud Zone
 
    .PARAMETER Viewers
    Viewers to add to the Project
 
    .PARAMETER Members
    Members to add to the Project
 
    .PARAMETER Administrators
    Administrators to add to the Project
 
    .PARAMETER OperationTimeout
    Operation Timeout
 
    .PARAMETER SharedResources
    Deployments are shared between all users in the project
 
    .PARAMETER PlacementPolicy
    Placement Policy - Valid values: "DEFAULT" or "SPREAD"
 
    .PARAMETER CustomProperties
    Specify the custom properties that should be added to all requests in this project
 
    .PARAMETER JSON
    A JSON string with the body payload
 
    .INPUTS
    System.String
    System.Switch
    PSCustomObject
 
    .OUTPUTS
    System.Management.Automation.PSObject
 
    .EXAMPLE
    $CloudZone = [PSCustomObject] @{
 
        zoneId = 'e6b9d1r2d2115a7558039ae2387c'
        priority = 1
        maxNumberInstances = 10
        memoryLimitMb = 107374
    }
 
    $CustomProperties = @{}
    $CustomProperties.Add('Property1', "Value1")
    $CustomProperties.Add('Property2', "Value2")
 
    $ProjectArguments = @{
 
        Name = 'Test Project'
        Description = 'Test Project'
        Zones = $CloudZone
        Viewers = 'viewer1@test.com'
        Members = 'user1@test.com','user2@test.com'
        Administrators = 'admin1@test.com','admin2@test.com'
        OperationTimeout = 3600
        SharedResources = $true
        CustomProperties = $CustomProperties
    }
 
    New-vAAProject @ProjectArguments
 
    .EXAMPLE
    $JSON = @"
        {
            "name": "Test Project",
            "description": "Test Project",
            "zones": [
                {
                    "zoneId": "e6b9d1r2d2115a7558039ae2387c",
                    "priority": 1,
                    "maxNumberInstances": 10,
                    "memoryLimitMB": 107374
                },
                {
                    "zoneId": "r2d2026e33c3648334bcb67eac669",
                    "priority": 2,
                    "maxNumberInstances": 100,
                    "memoryLimitMB": 107374
                }
            ],
            "members": [
                {
                    "email": "user1@test.com"
                },
                {
                    "email": "user2@test.com"
                }
            ],
            "administrators": [
                {
                    "email": "admin1@test.com"
                },
                {
                    "email": "admin2@test.com"
                }
            ],
            "constraints": {},
            "operationTimeout": 3600,
            "sharedResources": true
        }
"@
 
    $JSON | New-vAAProject
#>

[CmdletBinding(SupportsShouldProcess,ConfirmImpact="Low",DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$Description,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [PSCustomObject[]]$Zones,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Viewers,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Members,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Administrators,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [Int]$OperationTimeout,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [Switch]$SharedResources,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateSet("DEFAULT", "SPREAD", IgnoreCase = $false)]
        [String]$PlacementPolicy,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [Hashtable]$CustomProperties,

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ParameterSetName="JSON")]
        [ValidateNotNullOrEmpty()]
        [String]$JSON

    )

    begin {

        if ($SharedResources.IsPresent) {

            $SharedResourcesStatus = 'true'
        }
        else {

            $SharedResourcesStatus = 'false'
        }
    }

    process {

            if ($PSBoundParameters.ContainsKey("JSON")) {

                $Data = ($JSON | ConvertFrom-Json)

                $Body = $JSON
                $Name = $Data.name
            }
            else {


                $Body = @"
                    {
                        "name": "$($Name)",
                        "description": "$($Description)",
                        "zoneAssignmentConfigurations": [],
                        "viewers": [],
                        "members": [],
                        "administrators": [],
                        "operationTimeout": $($OperationTimeout),
                        "sharedResources": $($SharedResourcesStatus)
                    }
"@


                $JSONObject = $Body | ConvertFrom-Json

                # --- Add Cloud Zones
                foreach ($Zone in $Zones){

                    $JSONObject.zoneAssignmentConfigurations += $Zone
                }

                # --- Add Viewers
                if ($PSBoundParameters.ContainsKey("Viewers")){

                    foreach ($Viewer in $Viewers){

                        $Addition = @"
                        {
                            "email": "$($Viewer)"
                        }
"@

                        $AdditionObject = $Addition | ConvertFrom-Json
                        $JSONObject.viewers += $AdditionObject
                    }
                }

                # --- Add Members
                if ($PSBoundParameters.ContainsKey("Members")){

                    foreach ($Member in $Members){

                        $Addition = @"
                        {
                            "email": "$($Member)"
                        }
"@

                        $AdditionObject = $Addition | ConvertFrom-Json
                        $JSONObject.members += $AdditionObject
                    }
                }

                # --- Add Administrators
                if ($PSBoundParameters.ContainsKey("Administrators")){

                    foreach ($Administrator in $Administrators){

                        $Addition = @"
                        {
                            "email": "$($Administrator)"
                        }
"@

                        $AdditionObject = $Addition | ConvertFrom-Json
                        $JSONObject.administrators += $AdditionObject
                    }
                }

                # --- Add Placement Policy
                if ($PSBoundParameters.ContainsKey("PlacementPolicy")){

                    $JSONObject | Add-Member -MemberType NoteProperty -Name 'placementPolicy' -Value $PlacementPolicy
                }

                # --- Add Custom Properties
                if ($PSBoundParameters.ContainsKey("CustomProperties")){

                    $JSONObject | Add-Member -MemberType NoteProperty -Name 'customProperties' -Value $CustomProperties
                }

                $Body = $JSONObject | ConvertTo-Json -Depth 5
            }

        # --- Create new Project
        try {
            if ($PSCmdlet.ShouldProcess($Name)){

                $URI = "/iaas/api/projects"
                $Project = Invoke-vAARestMethod -Method POST -URI $URI -Body $Body -Verbose:$VerbosePreference

                [PSCustomObject] @{

                    Name = $Project.name
                    Description = $Project.description
                    Id = $Project.id
                    Administrators = $Project.administrators
                    Members = $Project.members
                    Viewers = $Project.viewers
                    Zones = $Project.zones
                    SharedResources = $Project.sharedResources
                    OperationTimeout = $Project.operationTimeout
                    PlacementPolicy = $Project.placementPolicy
                    CustomProperties = $Project.customProperties
                    OrganizationId = $Project.organizationId
                    Links = $Project._links
                }
            }
        }
        catch [Exception] {

            throw
        }
    }
    end {

    }
}

<#
    - Function: New-vAAVirtualDisk
#>


function New-vAAVirtualDisk {
    <#
        .SYNOPSIS
        Retrieve a vRA Machine's Disks
 
        .DESCRIPTION
        Retrieve the disks for a vRA Machine
 
        .PARAMETER Name
        The Name you would like to give the new disk/volume
 
        .PARAMETER Encrypted
        Switch indicating if the device will be encrypted during build
 
        .PARAMETER CapacityInGB
        Integer value indicating capacity of the disk in GB
 
        .PARAMETER DeviceDescription
        A description we can associate with the disk after creating it
 
        .PARAMETER Persistent
        Another switch indicating the disk to be a persistent disk
 
        .PARAMETER ProjectId
        The id of the project in which to build the disk/volume in
 
        .PARAMETER ProjectName
        As an alternate, a project name can be given for this operation
 
        .PARAMETER WaitForCompletion
        If this flag is added, this function will wait for the request to complete and will reutnr the created Virtual Disk
 
        .PARAMETER CompletionTimeout
        The default of this paramter is 2 minutes (120 seconds), but this parameter can be overriden here
 
        .PARAMETER Force
        Force the creation
 
        .OUTPUTS
        System.Management.Automation.PSObject.
 
        .EXAMPLE
        New-vAAVirtualDisk -Name 'test_disk_1' -CapacityInGB 10 -ProjectId 'b1dd48e71d74267559bb930934470'
 
        .EXAMPLE
        New-vAAVirtualDisk -Name 'test_disk_1' -CapacityInGB 10 -ProjectName 'GOLD'
 
        .EXAMPLE
        New-vAAVirtualDisk -Name 'test_disk_1' -CapacityInGB 10 -ProjectName 'GOLD' -WaitForCompletion
 
        .EXAMPLE
        New-vAAVirtualDisk -Name 'test_disk_1' -CapacityInGB 10 -ProjectName 'GOLD' -WaitForCompletion -CompletionTimeout 300
 
        .EXAMPLE
        New-vAAVirtualDisk -Name 'test_disk_1' -CapacityInGB 10 -ProjectId 'b1dd48e71d74267559bb930934470' -Persistent -Encrypted
 
    #>

    [CmdletBinding(SupportsShouldProcess,ConfirmImpact="High",DefaultParameterSetName="ByName")][OutputType('System.Management.Automation.PSObject')]
    [Alias("New-vAABlockDevice")]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'WaitForCompletion',Justification = 'False positive as rule does not scan child scopes')]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'CompletionTimeout',Justification = 'False positive as rule does not scan child scopes')]

        Param (

            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [Parameter(Mandatory=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String]$Name,

            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [Parameter(Mandatory=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [int]$CapacityInGB,

            [Parameter(Mandatory=$true,ParameterSetName="ById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$ProjectId,

            [Parameter(Mandatory=$true,ParameterSetName="ByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$ProjectName,

            [Parameter(Mandatory=$false)]
            [ValidateNotNullOrEmpty()]
            [String[]]$DeviceDescription,

            [Parameter()]
            [switch]$Persistent,

            [Parameter()]
            [switch]$Encrypted,

            [Parameter()]
            [switch]$WaitForCompletion,

            [Parameter()]
            [int]$CompletionTimeout = 120,

            [Parameter()]
            [switch]$Force

        )
        Begin {

            $APIUrl = "/iaas/api/block-devices"

            function CalculateOutput([int]$CompletionTimeout,[switch]$WaitForCompletion,[PSCustomObject]$RestResponse) {

                if ($WaitForCompletion.IsPresent) {
                    # if the wait for completion flag is given, the output will be different, we will wait here
                    # we will use the built-in function to check status
                    $ElapsedTime = 0
                    do {
                        $RequestResponse = Get-vAARequest -RequestId $RestResponse.id
                        if ($RequestResponse.Status -eq "FINISHED") {
                            foreach ($Resource in $RequestResponse.Resources) {
                                $Response = Invoke-vAARestMethod -URI "$Resource" -Method GET
                                [PSCustomObject]@{
                                    Name = $Response.name
                                    Status = $Response.status
                                    Owner = $Response.owner
                                    ExternalRegionId = $Response.externalRegionId
                                    ExternalZoneId = $Response.externalZoneId
                                    Description = $Response.description
                                    Tags = $Response.tags
                                    CapacityInGB = $Response.capacityInGB
                                    CloudAccountIDs = $Response.cloudAccountIds
                                    ExternalId = $Response.externalId
                                    Id = $Response.id
                                    DateCreated = $Response.createdAt
                                    LastUpdated = $Response.updatedAt
                                    OrganizationId = $Response.orgId
                                    Properties = $Response.customProperties
                                    ProjectId = $Response.projectId
                                    Persistent = $Response.persistent
                                }
                            }
                            break # leave loop as we are done here
                        }
                        $ElapsedTime += 5
                        Start-Sleep -Seconds 5
                    } while ($ElapsedTime -lt $CompletionTimeout)
                } else {
                    [PSCustomObject]@{
                        Name = $RestResponse.name
                        Progress = $RestResponse.progress
                        Id = $RestResponse.id
                        Status = $RestResponse.status
                    }
                }

            }
        }
        Process {

            try {


                switch ($PsCmdlet.ParameterSetName) {

                    # --- Create Virtual Disk by the Project ID
                    'ById' {
                        if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($ProjectId)){
                            $Body = @"
                                {
                                    "capacityInGB": $($CapacityInGB),
                                    "encrypted": $($Encrypted.IsPresent),
                                    "name": "$($Name)",
                                    "description": "$($DeviceDescription)",
                                    "persistent": $($Persistent.IsPresent),
                                    "projectId": "$($ProjectId)"
                                }
"@

                            $RestResponse = Invoke-vAARestMethod -URI "$APIUrl" -Method POST -Body $Body

                            CalculateOutput $CompletionTimeout $WaitForCompletion $RestResponse
                        }
                        break
                    }

                    # --- Get Project by its name
                    # --- Will need to retrieve the Project first, then use ID to get final output
                    'ByName' {
                        if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($ProjectName)){
                            $ProjResponse = Invoke-vAARestMethod -URI "/iaas/api/projects`?`$filter=name eq '$ProjectName'`&`$select=id" -Method GET
                            $ProjId = $ProjResponse.content[0].id

                            $Body = @"
                                {
                                    "capacityInGB": $($CapacityInGB),
                                    "encrypted": $($Encrypted.IsPresent),
                                    "name": "$($Name)",
                                    "description": "$($DeviceDescription)",
                                    "persistent": $($Persistent.IsPresent),
                                    "projectId": "$($ProjId)"
                                }
"@

                            Write-Verbose $Body
                            $RestResponse = Invoke-vAARestMethod -URI "$APIUrl" -Method POST -Body $Body

                            CalculateOutput $CompletionTimeout $WaitForCompletion $RestResponse
                        }
                        break
                    }

                }
            }
            catch [Exception]{

                throw
            }
        }
        End {

        }
    }


<#
    - Function: Remove-vAACloudAccount
#>


function Remove-vAACloudAccount {
    <#
        .SYNOPSIS
        Remove a Cloud Account
 
        .DESCRIPTION
        Remove a Cloud Account
 
        .PARAMETER Id
        The Id of the Cloud Account
 
        .PARAMETER Name
        The name of the Cloud Account
 
        .INPUTS
        System.String
 
        .EXAMPLE
        Remove-vAACloudAccount -Name CloudAccount1
 
        .EXAMPLE
        Remove-vAACloudAccount -Id '4b3bd194-9b5f-40fd-9ed0-58d997237999'
 
        .EXAMPLE
        Get-vAACloudAccount -Name CloudAccount1 | Remove-vAACloudAccount
 
    #>

    [CmdletBinding(SupportsShouldProcess,ConfirmImpact="High",DefaultParameterSetName="ById")]

    Param (

    [parameter(Mandatory=$true, ValueFromPipelineByPropertyName, ParameterSetName="ById")]
    [ValidateNotNullOrEmpty()]
    [String[]]$Id,

    [parameter(Mandatory=$true, ParameterSetName="ByName")]
    [ValidateNotNullOrEmpty()]
    [String[]]$Name

    )

    begin {}

    process {

        try {

            switch ($PSCmdlet.ParameterSetName) {

                'ById' {

                    foreach ($CloudAccountId in $Id) {

                        if ($PSCmdlet.ShouldProcess($CloudAccountId)){

                            $URI = "/iaas/api/cloud-accounts/$($CloudAccountId)"

                            Invoke-vAARestMethod -Method DELETE -URI "$($URI)" -Verbose:$VerbosePreference | Out-Null
                        }
                    }

                    break
                }

                'ByName' {

                    foreach ($CloudAccountName in $Name) {

                        if ($PSCmdlet.ShouldProcess($CloudAccountName)){

                            $CloudAccountId = (Get-vAACloudAccount -Name $CloudAccountName).id
                            $URI = "/iaas/api/cloud-accounts/$($CloudAccountId)"

                            Invoke-vAARestMethod -Method DELETE -URI "$($URI)" -Verbose:$VerbosePreference | Out-Null
                        }
                    }

                    break
                }
            }
        }
        catch [Exception]{

            throw
        }
    }
}

<#
    - Function: Remove-vAAProject
#>


function Remove-vAAProject {
    <#
        .SYNOPSIS
        Remove a Cloud Project
 
        .DESCRIPTION
        Remove a Cloud Project
 
        .PARAMETER Id
        The Id of the Cloud Project
 
        .PARAMETER Name
        The Name of the Cloud Project
 
        .INPUTS
        System.String
 
        .EXAMPLE
        Remove-vAAProject -Name Project1
 
        .EXAMPLE
        Remove-vAAProject -Id '4b3bd194-9b5f-40fd-9ed0-58d997237999'
 
        .EXAMPLE
        Get-vAAProject -Name Project1 | Remove-vAAProject
 
    #>

    [CmdletBinding(SupportsShouldProcess,ConfirmImpact="High",DefaultParameterSetName="ById")]

    Param (

    [parameter(Mandatory=$true, ValueFromPipelineByPropertyName, ParameterSetName="ById")]
    [ValidateNotNullOrEmpty()]
    [String[]]$Id,

    [parameter(Mandatory=$true, ParameterSetName="ByName")]
    [ValidateNotNullOrEmpty()]
    [String[]]$Name

    )

    begin {}

    process {

        try {

            switch ($PSCmdlet.ParameterSetName) {

                'ById' {

                    foreach ($ProjectId in $Id) {

                        if ($PSCmdlet.ShouldProcess($ProjectId)){

                            $URI = "/iaas/api/projects/$($ProjectId)"

                            Invoke-vAARestMethod -Method DELETE -URI "$($URI)" -Verbose:$VerbosePreference | Out-Null
                        }
                    }

                    break
                }

                'ByName' {

                    foreach ($ProjectName in $Name) {

                        if ($PSCmdlet.ShouldProcess($ProjectName)){

                            $ProjectId = (Get-vAAProject -Name $ProjectName).id
                            $URI = "/iaas/api/projects/$($ProjectId)"

                            Invoke-vAARestMethod -Method DELETE -URI "$($URI)" -Verbose:$VerbosePreference | Out-Null
                        }
                    }

                    break
                }
            }
        }
        catch [Exception]{

            throw
        }
    }
}

<#
    - Function: Resize-vAAMachine
#>


function Resize-vAAMachine {
<#
    .SYNOPSIS
    Resize a vRA Machine with the given CPU and Memory inputs
 
    .DESCRIPTION
    Resize a vRA Machine with the given CPU and Memory inputs
 
    .PARAMETER Id
    The ID of the vRA Machine
 
    .PARAMETER Name
    The Name of the vRA Machine
 
    .PARAMETER CPU
    The desired resulting cpu count for the machine
 
    .PARAMETER Memory
    The desired resulting memory in MB for the machine
 
    .PARAMETER Flavor
    As an alternative, you can provide a flavor instead of a cpu or memory option
 
    .PARAMETER WaitForCompletion
    If this flag is added, this function will wait for the resize operation to complete
 
    .PARAMETER CompletionTimeout
    The default of this paramter is 2 minutes (120 seconds), but this parameter can be overriden here
 
    .PARAMETER Force
    Force this change
 
    .OUTPUTS
    System.Management.Automation.PSObject.
 
    .EXAMPLE
    Resize-vAAMachine -Id 'b1dd48e71d74267559bb930934470' -CPU 4 -Memory 8192
 
    .EXAMPLE
    Resize-vAAMachine -Name 'iaas01' -CPU 4 -Memory 8192
 
    .EXAMPLE
    Resize-vAAMachine -Id 'b1dd48e71d74267559bb930934470' -Flavor Small
 
    .EXAMPLE
    Resize-vAAMachine -Name 'iaas01' -Flavor Small
 
    .EXAMPLE
    Resize-vAAMachine -Name 'iaas01' -Flavor Small -WaitForCompletion
 
    .EXAMPLE
    Resize-vAAMachine -Name 'iaas01' -Flavor Small -WaitForCompletion -CompletionTimeout 300
 
#>

[CmdletBinding(DefaultParameterSetName="ResizeByName", SupportsShouldProcess, ConfirmImpact='High')][OutputType('System.Management.Automation.PSObject')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'WaitForCompletion',Justification = 'False positive as rule does not scan child scopes')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'CompletionTimeout',Justification = 'False positive as rule does not scan child scopes')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ResizeById")]
        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ResizeFlavorById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ResizeByName")]
        [Parameter(Mandatory=$true,ParameterSetName="ResizeFlavorByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Name,

        [Parameter(Mandatory=$true,ParameterSetName="ResizeFlavorById")]
        [Parameter(Mandatory=$true,ParameterSetName="ResizeFlavorByName")]
        [ValidateNotNullOrEmpty()]
        [String]$Flavor,

        [Parameter(Mandatory=$true,ParameterSetName="ResizeByName")]
        [Parameter(Mandatory=$true,ParameterSetName="ResizeById")]
        [ValidateNotNullOrEmpty()]
        [int]$CPU,

        [Parameter(Mandatory=$true,ParameterSetName="ResizeByName")]
        [Parameter(Mandatory=$true,ParameterSetName="ResizeById")]
        [ValidateNotNullOrEmpty()]
        [int]$Memory,

        [Parameter()]
        [switch]$WaitForCompletion,

        [Parameter()]
        [int]$CompletionTimeout = 120,

        [Parameter()]
        [switch]$Force

    )
    Begin {

        $APIUrl = "/iaas/api/machines"

        function CalculateOutput([int]$CompletionTimeout,[switch]$WaitForCompletion,[PSCustomObject]$RestResponse) {
            if ($WaitForCompletion.IsPresent) {
                # if the wait for completion flag is given, the output will be different, we will wait here
                # we will use the built-in function to check status
                $ElapsedTime = 0
                do {
                    $RequestResponse = Get-vAARequest -RequestId $RestResponse.id
                    if ($RequestResponse.Status -eq "FINISHED") {
                        foreach ($Resource in $RequestResponse.Resources) {
                            $Record = Invoke-vAARestMethod -URI "$Resource" -Method GET
                            [PSCustomObject]@{
                                Name = $Record.name
                                PowerState = $Record.powerState
                                IPAddress = $Record.address
                                ExternalRegionId = $Record.externalRegionId
                                CloudAccountIDs = $Record.cloudAccountIds
                                ExternalId = $Record.externalId
                                Id = $Record.id
                                DateCreated = $Record.createdAt
                                LastUpdated = $Record.updatedAt
                                OrganizationId = $Record.organizationId
                                Properties = $Record.customProperties
                                RequestId = $Response.id
                                RequestStatus = "FINISHED"
                            }
                        }
                        break # leave loop as we are done here
                    }
                    $ElapsedTime += 5
                    Start-Sleep -Seconds 5
                } while ($ElapsedTime -lt $CompletionTimeout)

                if ($ElapsedTime -gt $CompletionTimeout -or $ElapsedTime -eq $CompletionTimeout) {
                    # we have errored out
                    [PSCustomObject]@{
                        Name = $RestResponse.name
                        Progress = $RestResponse.progress
                        Resources = $RestResponse.resources
                        RequestId = $RestResponse.id
                        Message = "We waited for completion, but we hit a timeout at $CompletionTimeout seconds. You may use Get-vAARequest -RequestId $($RestResponse.id) to continue checking status. Here was the original response: $($RestResponse.message)"
                        RequestStatus = $RestResponse.status
                    }
                }
            } else {
                [PSCustomObject]@{
                    Name = $RestResponse.name
                    Progress = $RestResponse.progress
                    Resources = $RestResponse.resources
                    RequestId = $RestResponse.id
                    Message = $RestResponse.message
                    RequestStatus = $RestResponse.status
                }
            }
        }
    }
    Process {

        try {


                switch ($PsCmdlet.ParameterSetName) {

                    # --- Resize by Flavor, do not need cpu and memory
                    'ResizeFlavorById' {

                        foreach ($MachineId in $Id) {
                            if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($MachineId)) {
                                $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId/operations/resize?name=$Flavor" -Method POST
                                CalculateOutput $CompletionTimeout $WaitForCompletion $RestResponse
                            }
                        }
                        break
                    }

                    # --- Resize by Flavor, do not need cpu and memory
                    'ResizeFlavorByName' {

                        foreach ($Machine in $Name) {
                            if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($Machine)) {
                            $MachineResponse = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$Machine'`&`$select=id" -Method GET
                            $MachineId = $MachineResponse.content[0].Id

                            $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId/operations/resize?name=$Flavor" -Method POST
                            CalculateOutput $CompletionTimeout $WaitForCompletion $RestResponse
                            }
                        }
                        break
                    }

                    # --- Resize with cpu and memory for given machine by its id
                    'ResizeById' {

                        foreach ($MachineId in $Id) {
                            if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($MachineId)) {
                                $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId/operations/resize?memoryInMB=$Memory`&cpuCount=$CPU" -Method POST
                                CalculateOutput $CompletionTimeout $WaitForCompletion $RestResponse
                            }
                        }
                        break
                    }

                    # --- Resize with cpu and memory for given machine by its name
                    'ResizeByName' {

                        foreach ($Machine in $Name) {
                            if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($Machine)) {
                                $MachineResponse = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$Machine'`&`$select=id" -Method GET
                                $MachineId = $MachineResponse.content[0].Id

                                $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId/operations/resize?memoryInMB=$Memory`&cpuCount=$CPU" -Method POST
                                CalculateOutput $CompletionTimeout $WaitForCompletion $RestResponse
                            }
                        }
                        break
                    }

                }
        }
        catch [Exception]{

            throw
        }
    }
    End {

    }
}


<#
    - Function: Resize-vAAVirtualDisk
#>


function Resize-vAAVirtualDisk {
<#
    .SYNOPSIS
    Resize a vRA Virtual Disk with the given capacity
 
    .DESCRIPTION
    Resize a vRA Virtual Disk with the given capacity
 
    .PARAMETER Id
    The ID of the vRA Virtual Disk
 
    .PARAMETER CapacityInGB
    The desired resulting capacity in GB
 
    .PARAMETER WaitForCompletion
    If this flag is added, this function will wait for the resize operation to complete
 
    .PARAMETER CompletionTimeout
    The default of this paramter is 2 minutes (120 seconds), but this parameter can be overriden here
 
    .PARAMETER Force
    Force this change
 
    .OUTPUTS
    System.Management.Automation.PSObject.
 
    .EXAMPLE
    Resize-vAAVirtualDisk -Id 'b1dd48e71d74267559bb930934470' -CapacityInGB 400
 
    .EXAMPLE
    Resize-vAAVirtualDisk -Id 'b1dd48e71d74267559bb930934470' -CapacityInGB 400 -WaitForCompletion
 
    .EXAMPLE
    Resize-vAAVirtualDisk -Id 'b1dd48e71d74267559bb930934470' -CapacityInGB 400 -WaitForCompletion -CompletionTimeout 300
 
#>

[CmdletBinding(DefaultParameterSetName="ResizeById", SupportsShouldProcess, ConfirmImpact='High')][OutputType('System.Management.Automation.PSObject')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'WaitForCompletion',Justification = 'False positive as rule does not scan child scopes')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'CompletionTimeout',Justification = 'False positive as rule does not scan child scopes')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [int]$CapacityInGB,

        [Parameter()]
        [switch]$WaitForCompletion,

        [Parameter()]
        [int]$CompletionTimeout = 120,

        [Parameter()]
        [switch]$Force

    )
    Begin {

        $APIUrl = "/iaas/api/block-devices"

        function CalculateOutput([int]$Timeout,[switch]$WFC,[PSCustomObject]$RestResponse) {
            if ($WFC.IsPresent) {
                # if the wait for completion flag is given, the output will be different, we will wait here
                # we will use the built-in function to check status
                Write-Verbose "WaitForCompletion"
                $ElapsedTime = 0
                do {
                    $RequestResponse = Get-vAARequest -RequestId $RestResponse.id
                    Write-Verbose $RequestResponse
                    if ($RequestResponse.Status -eq "FINISHED") {
                        foreach ($Resource in $RequestResponse.Resources) {
                            $Record = Invoke-vAARestMethod -URI "$Resource" -Method GET
                            Write-Verbose $Record
                            [PSCustomObject]@{
                                Name = $Record.name
                                capacityInGB = $Record.capacityInGB
                                type = $Record.type
                                ExternalRegionId = $Record.externalRegionId
                                CloudAccountIDs = $Record.cloudAccountIds
                                ExternalId = $Record.externalId
                                Id = $Record.id
                                DateCreated = $Record.createdAt
                                LastUpdated = $Record.updatedAt
                                OrganizationId = $Record.organizationId
                                Properties = $Record.customProperties
                                RequestId = $Response.id
                                RequestStatus = "FINISHED"
                            }
                        }
                        break # leave loop as we are done here
                    }
                    $ElapsedTime += 5
                    Start-Sleep -Seconds 5
                } while ($ElapsedTime -lt $Timeout)

                if ($ElapsedTime -gt $Timeout -or $ElapsedTime -eq $Timeout) {
                    # we have errored out
                    [PSCustomObject]@{
                        Name = $RestResponse.name
                        Progress = $RestResponse.progress
                        Resources = $RestResponse.resources
                        RequestId = $RestResponse.id
                        Message = "We waited for completion, but we hit a timeout at $Timeout seconds. You may use Get-vAARequest -RequestId $($RestResponse.id) to continue checking status. Here was the original response: $($RestResponse.message)"
                        RequestStatus = $RestResponse.status
                    }
                }
            } else {
                Write-Verbose "No Wait Time"
                [PSCustomObject]@{
                    Name = $RestResponse.name
                    Progress = $RestResponse.progress
                    RequestId = $RestResponse.id
                    RequestStatus = $RestResponse.status
                    selfLink = $RestResponse.selfLink
                }
            }
        }
    }
    Process {

        try {
            foreach ($BlockId in $Id) {
                if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($MachineId)) {
                    $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$BlockId`?capacityInGB=$CapacityInGB" -Method POST
                    CalculateOutput -Timeout $CompletionTimeout  -RestResponse $RestResponse -WFC $WaitForCompletion
                }
            }
        }
        catch [Exception]{

            throw
        }
    }
    End {

    }
}


<#
    - Function: Restart-vAAMachine
#>


function Restart-vAAMachine {
<#
    .SYNOPSIS
    Restart a vRA Machine
 
    .DESCRIPTION
    Restart a vRA Machine
 
    .PARAMETER Id
    The ID of the vRA Machine
 
    .PARAMETER Name
    The Name of the vRA Machine
 
    .PARAMETER WaitForCompletion
    If this flag is added, this function will wait for the power state of the machine to = ON. (note: machine may still be completing OS boot procedure when this function is complete)
 
    .PARAMETER CompletionTimeout
    The default of this paramter is 2 minutes (120 seconds), but this parameter can be overriden here
 
    .PARAMETER Force
    Force this change
 
    .OUTPUTS
    System.Management.Automation.PSObject.
 
    .EXAMPLE
    Restart-vAAMachine -Id 'b1dd48e71d74267559bb930934470'
 
    .EXAMPLE
    Restart-vAAMachine -Name 'iaas01'
 
    .EXAMPLE
    Restart-vAAMachine -Name 'iaas01' -WaitForCompletion
 
    .EXAMPLE
    Restart-vAAMachine -Name 'iaas01' -WaitForCompletion -CompletionTimeout 300
 
#>

[CmdletBinding(SupportsShouldProcess, ConfirmImpact="High", DefaultParameterSetName="ResetByName")][OutputType('System.Management.Automation.PSObject')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'WaitForCompletion',Justification = 'False positive as rule does not scan child scopes')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'CompletionTimeout',Justification = 'False positive as rule does not scan child scopes')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ResetById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ResetByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Name,

        [Parameter()]
        [switch]$WaitForCompletion,

        [Parameter()]
        [int]$CompletionTimeout = 120,

        [Parameter()]
        [switch]$Force

    )
    Begin {

        $APIUrl = "/iaas/api/machines"

        function CalculateOutput([int]$CompletionTimeout,[switch]$WaitForCompletion,[PSCustomObject]$RestResponse) {
            if ($WaitForCompletion.IsPresent) {
                # if the wait for completion flag is given, the output will be different, we will wait here
                # we will use the built-in function to check status
                $ElapsedTime = 0
                do {
                    $RequestResponse = Get-vAARequest -RequestId $RestResponse.id
                    if ($RequestResponse.Status -eq "FINISHED") {
                        foreach ($Resource in $RequestResponse.Resources) {
                            $Record = Invoke-vAARestMethod -URI "$Resource" -Method GET
                            [PSCustomObject]@{
                                Name = $Record.name
                                PowerState = $Record.powerState
                                IPAddress = $Record.address
                                ExternalRegionId = $Record.externalRegionId
                                CloudAccountIDs = $Record.cloudAccountIds
                                ExternalId = $Record.externalId
                                Id = $Record.id
                                DateCreated = $Record.createdAt
                                LastUpdated = $Record.updatedAt
                                OrganizationId = $Record.organizationId
                                Properties = $Record.customProperties
                                RequestId = $Response.id
                                RequestStatus = "FINISHED"
                            }
                        }
                        break # leave loop as we are done here
                    }
                    $ElapsedTime += 5
                    Start-Sleep -Seconds 5
                } while ($ElapsedTime -lt $CompletionTimeout)

                if ($ElapsedTime -gt $CompletionTimeout -or $ElapsedTime -eq $CompletionTimeout) {
                    # we have errored out
                    [PSCustomObject]@{
                        Name = $RestResponse.name
                        Progress = $RestResponse.progress
                        Resources = $RestResponse.resources
                        RequestId = $RestResponse.id
                        Message = "We waited for completion, but we hit a timeout at $CompletionTimeout seconds. You may use Get-vAARequest -RequestId $($RestResponse.id) to continue checking status. Here was the original response: $($RestResponse.message)"
                        RequestStatus = $RestResponse.status
                    }
                }
            } else {
                [PSCustomObject]@{
                    Name = $RestResponse.name
                    Progress = $RestResponse.progress
                    Resources = $RestResponse.resources
                    RequestId = $RestResponse.id
                    Message = $RestResponse.message
                    RequestStatus = $RestResponse.status
                }
            }

        }
    }
    Process {

        try {

                switch ($PsCmdlet.ParameterSetName) {

                    # --- Restart the given machine by its id
                    'ResetById' {

                        foreach ($MachineId in $Id) {
                                if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($MachineId)) {
                                $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId/operations/reset" -Method POST
                                CalculateOutput $CompletionTimeout $WaitForCompletion $RestResponse
                            }
                        }
                        break
                    }

                    # --- Restart the given machine by its name
                    'ResetByName' {

                        foreach ($Machine in $Name) {
                            if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($Machine)) {
                                $MachineResponse = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$Machine'`&`$select=id" -Method GET
                                $MachineId = $MachineResponse.content[0].Id

                                $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId/operations/reset" -Method POST
                                CalculateOutput $CompletionTimeout $WaitForCompletion $RestResponse
                            }
                        }

                        break
                    }

                }
        }
        catch [Exception]{

            throw
        }
    }
    End {

    }
}


<#
    - Function: Restart-vAAMachineGuestOS
#>


function Restart-vAAMachineGuestOS {
<#
    .SYNOPSIS
    Request a guest os restart
 
    .DESCRIPTION
    Request the guest OS to restart
 
    .PARAMETER Id
    The ID of the vRA Machine
 
    .PARAMETER Name
    The Name of the vRA Machine
 
    .PARAMETER WaitForCompletion
    If this flag is added, this function will wait for the power state of the machine to = ON. (note: machine may still be completing OS boot procedure when this function is complete)
 
    .PARAMETER CompletionTimeout
    The default of this paramter is 2 minutes (120 seconds), but this parameter can be overriden here
 
    .PARAMETER Force
    Force this change
 
    .OUTPUTS
    System.Management.Automation.PSObject.
 
    .EXAMPLE
    Restart-vAAMachineGuestOS -Id 'b1dd48e71d74267559bb930934470'
 
    .EXAMPLE
    Restart-vAAMachineGuestOS -Name 'iaas01'
 
    .EXAMPLE
    Restart-vAAMachineGuestOS -Name 'iaas01' -WaitForCompletion
 
    .EXAMPLE
    Restart-vAAMachineGuestOS -Name 'iaas01' -WaitForCompletion -CompletionTimeout 300
 
#>

[CmdletBinding(SupportsShouldProcess, ConfirmImpact="High", DefaultParameterSetName="RebootByName")][OutputType('System.Management.Automation.PSObject')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'WaitForCompletion',Justification = 'False positive as rule does not scan child scopes')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'CompletionTimeout',Justification = 'False positive as rule does not scan child scopes')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="RebootById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="RebootByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Name,

        [Parameter()]
        [switch]$WaitForCompletion,

        [Parameter()]
        [int]$CompletionTimeout = 120,

        [Parameter()]
        [switch]$Force

    )
    Begin {

        $APIUrl = "/iaas/api/machines"

        function CalculateOutput([int]$CompletionTimeout,[switch]$WaitForCompletion,[PSCustomObject]$RestResponse) {
            if ($WaitForCompletion.IsPresent) {
                # if the wait for completion flag is given, the output will be different, we will wait here
                # we will use the built-in function to check status
                $ElapsedTime = 0
                do {
                    $RequestResponse = Get-vAARequest -RequestId $RestResponse.id
                    if ($RequestResponse.Status -eq "FINISHED") {
                        foreach ($Resource in $RequestResponse.Resources) {
                            $Record = Invoke-vAARestMethod -URI "$Resource" -Method GET
                            [PSCustomObject]@{
                                Name = $Record.name
                                PowerState = $Record.powerState
                                IPAddress = $Record.address
                                ExternalRegionId = $Record.externalRegionId
                                CloudAccountIDs = $Record.cloudAccountIds
                                ExternalId = $Record.externalId
                                Id = $Record.id
                                DateCreated = $Record.createdAt
                                LastUpdated = $Record.updatedAt
                                OrganizationId = $Record.organizationId
                                Properties = $Record.customProperties
                                RequestId = $Response.id
                                RequestStatus = "FINISHED"
                            }
                        }
                        break # leave loop as we are done here
                    }
                    $ElapsedTime += 5
                    Start-Sleep -Seconds 5
                } while ($ElapsedTime -lt $CompletionTimeout)

                if ($ElapsedTime -gt $CompletionTimeout -or $ElapsedTime -eq $CompletionTimeout) {
                    # we have errored out
                    [PSCustomObject]@{
                        Name = $RestResponse.name
                        Progress = $RestResponse.progress
                        Resources = $RestResponse.resources
                        RequestId = $RestResponse.id
                        Message = "We waited for completion, but we hit a timeout at $CompletionTimeout seconds. You may use Get-vAARequest -RequestId $($RestResponse.id) to continue checking status. Here was the original response: $($RestResponse.message)"
                        RequestStatus = $RestResponse.status
                    }
                }
            } else {
                [PSCustomObject]@{
                    Name = $RestResponse.name
                    Progress = $RestResponse.progress
                    Resources = $RestResponse.resources
                    RequestId = $RestResponse.id
                    Message = $RestResponse.message
                    RequestStatus = $RestResponse.status
                }
            }

        }
    }
    Process {

        try {

                switch ($PsCmdlet.ParameterSetName) {

                    # --- Restart the given machine by its id
                    'RebootById' {

                        foreach ($MachineId in $Id) {
                            if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($MachineId)) {
                                $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId/operations/reboot" -Method POST
                                CalculateOutput $CompletionTimeout $WaitForCompletion $RestResponse
                            }
                        }
                        break
                    }

                    # --- Restart the given machine by its name
                    'RebootByName' {

                        foreach ($Machine in $Name) {
                            if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($Machine)) {
                                $MachineResponse = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$Machine'`&`$select=id" -Method GET
                                $MachineId = $MachineResponse.content[0].Id

                                $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId/operations/reboot" -Method POST
                                CalculateOutput $CompletionTimeout $WaitForCompletion $RestResponse
                            }
                        }
                        break
                    }

                }

        }
        catch [Exception]{

            throw
        }
    }
    End {

    }
}


<#
    - Function: Set-vAAProject
#>


function Set-vAAProject {
<#
    .SYNOPSIS
    Update a vRA Cloud Project
 
    .DESCRIPTION
    Update a vRA Cloud Project
 
    .PARAMETER Id
    The ID of the Project to update
 
    .PARAMETER Name
    The Name of the Project to update
 
    .PARAMETER NewName
    The Name to rename the Project to
 
    .PARAMETER Description
    A description of the Project
 
    .PARAMETER Zones
    PSCustomObject(s) with properties for a Cloud Zone
 
    .PARAMETER Members
    Members to set to the Project
 
    .PARAMETER Administrators
    Administrators to set to the Project
 
    .PARAMETER Viewers
    Viewers to set to the Project
 
    .PARAMETER OperationTimeout
    Operation Timeout in seconds
 
    .PARAMETER SharedResources
    Deployments are shared between all users in the project
 
    .PARAMETER PlacementPolicy
    Placement Policy - Valid values: "DEFAULT" or "SPREAD"
 
    .PARAMETER CustomProperties
    Specify the custom properties that should be added to all requests in this project
    Note the vRA API does not appear to support removing existing Custom Properties
    Custom Properties specifed here will be added to those already existing
 
    .PARAMETER JSON
    A JSON string with the body payload
 
    .INPUTS
    System.String
    System.Switch
    PSCustomObject
 
    .OUTPUTS
    System.Management.Automation.PSObject
 
    .EXAMPLE
    $CloudZone = [PSCustomObject] @{
 
        zoneId = 'e6b9d1r2d2115a7558039ae2387c'
        priority = 1
        maxNumberInstances = 10
        memoryLimitMb = 107374
    }
 
    $CustomProperties = @{}
    $CustomProperties.Add('Property1', "Value1")
    $CustomProperties.Add('Property2', "Value2")
 
    $ProjectArguments = @{
        Id = 'i84848484848484'
        Name = 'Test Project'
        Description = 'Test Project'
        Zones = $CloudZone
        Members = 'user1@test.com','user2@test.com'
        Administrators = 'admin1@test.com','admin2@test.com'
        OperationTimeout = 3600
        SharedResources = 'true'
        CustomProperties = $CustomProperties
    }
 
    Set-vAAProject @ProjectArguments
 
    .EXAMPLE
    $JSON = @"
        {
            "id": "i8585858585858"
            "name": "Test Project",
            "description": "Test Project",
            "zones": [
                {
                    "zoneId": "e6b9d1r2d2115a7558039ae2387c",
                    "priority": 1,
                    "maxNumberInstances": 10,
                    "memoryLimitMB": 107374
                },
                {
                    "zoneId": "r2d2026e33c3648334bcb67eac669",
                    "priority": 2,
                    "maxNumberInstances": 100,
                    "memoryLimitMB": 107374
                }
            ],
            "members": [
                {
                    "email": "user1@test.com"
                },
                {
                    "email": "user2@test.com"
                }
            ],
            "administrators": [
                {
                    "email": "admin1@test.com"
                },
                {
                    "email": "admin2@test.com"
                }
            ],
            "constraints": {},
            "operationTimeout": 3600,
            "sharedResources": true
        }
"@
 
    $JSON | Set-vAAProject
#>

[CmdletBinding(SupportsShouldProcess,ConfirmImpact="Low",DefaultParameterSetName="ById")][OutputType('System.Management.Automation.PSObject')]
[Alias("Update-vAAProject")]

    Param (

        [Parameter(Mandatory=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String]$NewName,

        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String]$Description,

        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [PSCustomObject[]]$Zones,

        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [String[]]$Members,

        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [String[]]$Administrators,

        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [String[]]$Viewers,

        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [Int]$OperationTimeout,

        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [ValidateSet("true", "false", IgnoreCase = $false)]
        [String]$SharedResources,

        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [ValidateSet("DEFAULT", "SPREAD", IgnoreCase = $false)]
        [String]$PlacementPolicy,

        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [Hashtable]$CustomProperties,

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ParameterSetName="JSON")]
        [ValidateNotNullOrEmpty()]
        [String]$JSON
    )

    begin {

        function CalculateOutput([PSCustomObject]$Project) {
            [PSCustomObject] @{
                Name = $Project.name
                Description = $Project.description
                Id = $Project.id
                Administrators = $Project.administrators
                Members = $Project.members
                Viewers = $Project.viewers
                Zones = $Project.zones
                SharedResources = $Project.sharedResources
                OperationTimeout = $Project.operationTimeout
                PlacementPolicy = $Project.placementPolicy
                CustomProperties = $Project.customProperties
                OrganizationId = $Project.organizationId
                Links = $Project._links
            }
        }
    }

    process {

        switch ($PsCmdlet.ParameterSetName) {

            # --- Update Project by id
            'ById' {
                if ($null -eq $Name) {
                    # If the user does not provide a name keep the existing
                    $ExistingProject = Get-vAAProject -Id $Id
                    if (!$ExistingProject){

                        throw "Project with id $($Id) does not exist"
                    }
                    $Name = $ExistingProject.Name
                }
            }

            # --- Update Project by name
            'ByName' {
                # We need the id to do the patch
                $ExistingProject = Get-vAAProject -Name $Name
                if (!$ExistingProject){

                    throw "Project with name $($Name) does not exist"
                }
                $Id = $ExistingProject.Id
            }

            # --- Update Project by JSON
            'JSON' {
                $Data = $JSON | ConvertFrom-Json

                $Body = $JSON
                $Name = $Data.name

                if ([bool]($myObject.PSobject.Properties.name -match "Id")) {
                    $Id = $Data.Id
                } else {
                    $ExistingProject = Get-vAAProject -Name $Name
                    if (!$ExistingProject){

                        throw "Project with name $($Name) does not exist"
                    }
                    $Id = $ExistingProject.Id
                }

            }
        }

        if (-not $PSBoundParameters.ContainsKey("JSON")) {

            $Project = [PSCustomObject]@{}

            if ($PSBoundParameters.ContainsKey("NewName")){

                Write-Verbose -Message "Updating Name: $($ExistingProject.name) >> $($NewName)"
                $Project | Add-Member -MemberType NoteProperty -Name 'name' -Value $NewName
            }

            if ($PSBoundParameters.ContainsKey("Description")){

                Write-Verbose -Message "Updating Description: $($ExistingProject.description) >> $($Description)"
                $Project | Add-Member -MemberType NoteProperty -Name 'description' -Value $Description
            }

            if ($PSBoundParameters.ContainsKey("Zones")){

                Write-Verbose -Message "Updating Zones: $($ExistingProject.Zones) >> $($Zones)"
                if (!$Zones){

                    $EmptyZones = @()
                    $Project | Add-Member -MemberType NoteProperty -Name 'zoneAssignmentConfigurations' -Value $EmptyZones
                }
                else {

                    $Project | Add-Member -MemberType NoteProperty -Name 'zoneAssignmentConfigurations' -Value $Zones
                }
            }

            if ($PSBoundParameters.ContainsKey("Members")){

                Write-Verbose -Message "Updating Members: $($ExistingProject.Members.email) >> $($Members)"
                if (!$Members){

                    $Members = @()
                    $Project | Add-Member -MemberType NoteProperty -Name 'members' -Value $Members
                }
                else {
                    $MembersArray = @()
                    foreach ($Member in $Members){
                        $MembersArray += [PSCustomObject]@{email=$Member}
                    }
                    $Project | Add-Member -MemberType NoteProperty -Name 'members' -Value $MembersArray
                }
            }

            if ($PSBoundParameters.ContainsKey("Administrators")){

                Write-Verbose -Message "Updating Administrators: $($ExistingProject.Administrators.email) >> $($Administrators)"
                if (!$Administrators){

                    $Administrators = @()
                    $Project | Add-Member -MemberType NoteProperty -Name 'administrators' -Value $Administrators
                }
                else {
                    $AdministratorsArray = @()
                    foreach ($Administrator in $Administrators){
                        $AdministratorsArray += [PSCustomObject]@{email=$Administrator}
                    }
                    $Project | Add-Member -MemberType NoteProperty -Name 'administrators' -Value $AdministratorsArray
                }
            }

            if ($PSBoundParameters.ContainsKey("Viewers")){

                Write-Verbose -Message "Updating Viewers: $($ExistingProject.Viewers.email) >> $($Viewers)"
                if (!$Viewers){

                    $Viewers = @()
                    $Project | Add-Member -MemberType NoteProperty -Name 'viewers' -Value $Viewers
                }
                else {
                    $ViewersArray = @()
                    foreach ($Viewer in $Viewers){
                        $ViewersArray += [PSCustomObject]@{email=$Viewer}
                    }
                    $Project | Add-Member -MemberType NoteProperty -Name 'viewers' -Value $ViewersArray
                }
            }

            if ($PSBoundParameters.ContainsKey("OperationTimeout")){

                Write-Verbose -Message "Updating OperationTimeout: $($ExistingProject.OperationTimeout) >> $($OperationTimeout)"
                $Project | Add-Member -MemberType NoteProperty -Name 'operationTimeout' -Value $OperationTimeout
            }

            if ($PSBoundParameters.ContainsKey("SharedResources")){

                Write-Verbose -Message "Updating SharedResources: $($ExistingProject.SharedResources) >> $($SharedResources)"
                $Project | Add-Member -MemberType NoteProperty -Name 'sharedResources' -Value $SharedResources
            }

            if ($PSBoundParameters.ContainsKey("PlacementPolicy")){

                Write-Verbose -Message "Updating PlacementPolicy: $($ExistingProject.PlacementPolicy) >> $($PlacementPolicy)"
                $Project | Add-Member -MemberType NoteProperty -Name 'placementPolicy' -Value $PlacementPolicy
            }

            if ($PSBoundParameters.ContainsKey("CustomProperties")){

                $Project | Add-Member -MemberType NoteProperty -Name 'customProperties' -Value $CustomProperties
            }

            $Body = $Project | ConvertTo-Json -Depth 5
            Write-Verbose "JSON Body is : $($Body)"
        }

        # --- Update The Project
        try {
            if ($PSCmdlet.ShouldProcess($Name)){

                $URI = "/iaas/api/projects"
                $Response = Invoke-vAARestMethod -Method PATCH -URI "$URI`/$Id" -Body $Body -Verbose:$VerbosePreference

                CalculateOutput $Response
            }
        }
        catch [Exception] {

            throw
        }
    }
    end {

    }
}

<#
    - Function: Start-vAAMachine
#>


function Start-vAAMachine {
    <#
        .SYNOPSIS
        Power-On a vRA Machine
 
        .DESCRIPTION
        Power-On a vRA Machine
 
        .PARAMETER Id
        The ID of the vRA Machine
 
        .PARAMETER Name
        The Name of the vRA Machine
 
        .PARAMETER WaitForCompletion
        If this flag is added, this function will wait for the power state of the machine to = ON (note: machine may still be completing OS boot procedure when this function is complete)
 
        .PARAMETER CompletionTimeout
        The default of this paramter is 2 minutes (120 seconds), but this parameter can be overriden here
 
        .PARAMETER Force
        Force this change
 
        .OUTPUTS
        System.Management.Automation.PSObject.
 
        .EXAMPLE
        Start-vAAMachine -Id 'b1dd48e71d74267559bb930934470'
 
        .EXAMPLE
        Start-vAAMachine -Name 'iaas01'
 
        .EXAMPLE
        Start-vAAMachine -Name 'iaas01' -WaitForCompletion
 
        .EXAMPLE
        Start-vAAMachine -Name 'iaas01' -WaitForCompletion -CompletionTimeout 300
 
    #>

    [CmdletBinding(DefaultParameterSetName="PowerOnByName", SupportsShouldProcess, ConfirmImpact="Low")][OutputType('System.Management.Automation.PSObject')]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'WaitForCompletion',Justification = 'False positive as rule does not scan child scopes')]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'CompletionTimeout',Justification = 'False positive as rule does not scan child scopes')]

        Param (

            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="PowerOnById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,

            [Parameter(Mandatory=$true,ParameterSetName="PowerOnByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name,

            [Parameter()]
            [switch]$WaitForCompletion,

            [Parameter()]
            [int]$CompletionTimeout = 120,

            [Parameter()]
            [switch]$Force

        )
        Begin {

            $APIUrl = "/iaas/api/machines"

            function CalculateOutput([int]$CompletionTimeout,[switch]$WaitForCompletion,[PSCustomObject]$RestResponse) {

                if ($WaitForCompletion.IsPresent) {
                    # if the wait for completion flag is given, the output will be different, we will wait here
                    # we will use the built-in function to check status
                    $ElapsedTime = 0
                    do {
                        $RequestResponse = Get-vAARequest -RequestId $RestResponse.id
                        if ($RequestResponse.Status -eq "FINISHED") {
                            foreach ($Resource in $RequestResponse.Resources) {
                                $Record = Invoke-vAARestMethod -URI "$Resource" -Method GET
                                [PSCustomObject]@{
                                    Name = $Record.name
                                    PowerState = $Record.powerState
                                    IPAddress = $Record.address
                                    ExternalRegionId = $Record.externalRegionId
                                    CloudAccountIDs = $Record.cloudAccountIds
                                    ExternalId = $Record.externalId
                                    Id = $Record.id
                                    DateCreated = $Record.createdAt
                                    LastUpdated = $Record.updatedAt
                                    OrganizationId = $Record.organizationId
                                    Properties = $Record.customProperties
                                    RequestId = $Response.id
                                    RequestStatus = "FINISHED"
                                }
                            }
                            break # leave loop as we are done here
                        }
                        $ElapsedTime += 5
                        Start-Sleep -Seconds 5
                    } while ($ElapsedTime -lt $CompletionTimeout)

                    if ($ElapsedTime -gt $CompletionTimeout -or $ElapsedTime -eq $CompletionTimeout) {
                        # we have errored out
                        [PSCustomObject]@{
                            Name = $RestResponse.name
                            Progress = $RestResponse.progress
                            Resources = $RestResponse.resources
                            RequestId = $RestResponse.id
                            Message = "We waited for completion, but we hit a timeout at $CompletionTimeout seconds. You may use Get-vAARequest -RequestId $($RestResponse.id) to continue checking status. Here was the original response: $($RestResponse.message)"
                            RequestStatus = $RestResponse.status
                        }
                    }
                } else {
                    [PSCustomObject]@{
                        Name = $RestResponse.name
                        Progress = $RestResponse.progress
                        Resources = $RestResponse.resources
                        RequestId = $RestResponse.id
                        Message = $RestResponse.message
                        RequestStatus = $RestResponse.status
                    }
                }
            }
        }
        Process {

            try {

                    switch ($PsCmdlet.ParameterSetName) {

                        # --- Start the given machine by its id
                        'PowerOnById' {

                            foreach ($MachineId in $Id) {
                                if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($MachineId)){
                                    $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId/operations/power-on" -Method POST
                                    CalculateOutput $CompletionTimeout $WaitForCompletion $RestResponse
                                }
                            }
                            break
                        }

                        # --- Start the given machine by its name
                        'PowerOnByName' {

                            foreach ($Machine in $Name) {
                                if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($Machine)){
                                    $MachineResponse = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$Machine'`&`$select=id" -Method GET
                                    $MachineId = $MachineResponse.content[0].Id

                                    $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId/operations/power-on" -Method POST
                                    CalculateOutput $CompletionTimeout $WaitForCompletion $RestResponse
                                }
                            }
                            break
                        }

                    }

            }
            catch [Exception]{

                throw
            }
        }
        End {

        }
    }


<#
    - Function: Stop-vAAMachine
#>


function Stop-vAAMachine {
<#
    .SYNOPSIS
    Power-Off a vRA Machine
 
    .DESCRIPTION
    Power-Off a vRA Machine
 
    .PARAMETER Id
    The ID of the vRA Machine
 
    .PARAMETER Name
    The Name of the vRA Machine
 
    .PARAMETER WaitForCompletion
    If this flag is added, this function will wait for the power state of the machine to = OFF
 
    .PARAMETER CompletionTimeout
    The default of this paramter is 2 minutes (120 seconds), but this parameter can be overriden here
 
    .PARAMETER Force
    Force this change
 
    .OUTPUTS
    System.Management.Automation.PSObject.
 
    .EXAMPLE
    Stop-vAAMachine -Id 'b1dd48e71d74267559bb930934470'
 
    .EXAMPLE
    Stop-vAAMachine -Name 'iaas01'
 
    .EXAMPLE
    Stop-vAAMachine -Name 'iaas01' -WaitForCompletion
 
    .EXAMPLE
    Stop-vAAMachine -Name 'iaas01' -WaitForCompletion -CompletionTimeout 300
 
#>

[CmdletBinding(DefaultParameterSetName="PowerOffByName", SupportsShouldProcess, ConfirmImpact='High')][OutputType('System.Management.Automation.PSObject')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'WaitForCompletion',Justification = 'False positive as rule does not scan child scopes')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'CompletionTimeout',Justification = 'False positive as rule does not scan child scopes')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="PowerOffById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="PowerOffByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Name,

        [Parameter()]
        [switch]$WaitForCompletion,

        [Parameter()]
        [int]$CompletionTimeout = 120,

        [Parameter()]
        [switch]$Force

    )
    Begin {

        $APIUrl = "/iaas/api/machines"

        function CalculateOutput([int]$CompletionTimeout,[switch]$WaitForCompletion,[PSCustomObject]$RestResponse) {
            if ($WaitForCompletion.IsPresent) {
                # if the wait for completion flag is given, the output will be different, we will wait here
                # we will use the built-in function to check status
                $ElapsedTime = 0
                do {
                    $RequestResponse = Get-vAARequest -RequestId $RestResponse.id
                    if ($RequestResponse.Status -eq "FINISHED") {
                        foreach ($Resource in $RequestResponse.Resources) {
                            $Record = Invoke-vAARestMethod -URI "$Resource" -Method GET
                            [PSCustomObject]@{
                                Name = $Record.name
                                PowerState = $Record.powerState
                                IPAddress = $Record.address
                                ExternalRegionId = $Record.externalRegionId
                                CloudAccountIDs = $Record.cloudAccountIds
                                ExternalId = $Record.externalId
                                Id = $Record.id
                                DateCreated = $Record.createdAt
                                LastUpdated = $Record.updatedAt
                                OrganizationId = $Record.organizationId
                                Properties = $Record.customProperties
                                RequestId = $Response.id
                                RequestStatus = "FINISHED"
                            }
                        }
                        break # leave loop as we are done here
                    }
                    $ElapsedTime += 5
                    Start-Sleep -Seconds 5
                } while ($ElapsedTime -lt $CompletionTimeout)

                if ($ElapsedTime -gt $CompletionTimeout -or $ElapsedTime -eq $CompletionTimeout) {
                    # we have errored out
                    [PSCustomObject]@{
                        Name = $RestResponse.name
                        Progress = $RestResponse.progress
                        Resources = $RestResponse.resources
                        RequestId = $RestResponse.id
                        Message = "We waited for completion, but we hit a timeout at $CompletionTimeout seconds. You may use Get-vAARequest -RequestId $($RestResponse.id) to continue checking status. Here was the original response: $($RestResponse.message)"
                        RequestStatus = $RestResponse.status
                    }
                }
            } else {
                [PSCustomObject]@{
                    Name = $RestResponse.name
                    Progress = $RestResponse.progress
                    Resources = $RestResponse.resources
                    RequestId = $RestResponse.id
                    Message = $RestResponse.message
                    RequestStatus = $RestResponse.status
                }
            }
        }
    }
    Process {

        try {

                switch ($PsCmdlet.ParameterSetName) {

                    # --- Stop the given machine by its id
                    'PowerOffById' {

                        foreach ($MachineId in $Id) {
                            if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($MachineId)){
                                $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId/operations/power-off" -Method POST
                                CalculateOutput $CompletionTimeout $WaitForCompletion $RestResponse
                            }
                        }
                        break
                    }

                    # --- Stop the given machine by its name
                    'PowerOffByName' {

                        foreach ($Machine in $Name) {
                            if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($Machine)){
                                $MachineResponse = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$Machine'`&`$select=id" -Method GET
                                $MachineId = $MachineResponse.content[0].Id

                                $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId/operations/power-off" -Method POST
                                CalculateOutput $CompletionTimeout $WaitForCompletion $RestResponse
                            }
                        }
                        break
                    }

                }
        }
        catch [Exception]{

            throw
        }
    }
    End {

    }
}


<#
    - Function: Stop-vAAMachineGuestOS
#>


function Stop-vAAMachineGuestOS {
<#
    .SYNOPSIS
    Shutdown a vRA Machine
 
    .DESCRIPTION
    Shutdown a vRA Machine
 
    .PARAMETER Id
    The ID of the vRA Machine
 
    .PARAMETER Name
    The Name of the vRA Machine
 
    .PARAMETER WaitForCompletion
    If this flag is added, this function will wait for the power state of the machine to = OFF
 
    .PARAMETER CompletionTimeout
    The default of this paramter is 2 minutes (120 seconds), but this parameter can be overriden here
 
    .PARAMETER Force
    Force this change
 
    .OUTPUTS
    System.Management.Automation.PSObject.
 
    .EXAMPLE
    Stop-vAAMachineGuestOS -Id 'b1dd48e71d74267559bb930934470'
 
    .EXAMPLE
    Stop-vAAMachineGuestOS -Name 'iaas01'
 
    .EXAMPLE
    Stop-vAAMachineGuestOS -Name 'iaas01' -WaitForCompletion
 
    .EXAMPLE
    Stop-vAAMachineGuestOS -Name 'iaas01' -WaitForCompletion -CompletionTimeout 300
 
#>

[CmdletBinding(DefaultParameterSetName="ShutdownByName", SupportsShouldProcess, ConfirmImpact='High')][OutputType('System.Management.Automation.PSObject')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'WaitForCompletion',Justification = 'False positive as rule does not scan child scopes')]
[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'CompletionTimeout',Justification = 'False positive as rule does not scan child scopes')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ShutdownById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ShutdownByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Name,

        [Parameter()]
        [switch]$WaitForCompletion,

        [Parameter()]
        [int]$CompletionTimeout = 120,

        [Parameter()]
        [switch]$Force

    )
    Begin {

        $APIUrl = "/iaas/api/machines"

        function CalculateOutput([int]$CompletionTimeout,[switch]$WaitForCompletion,[PSCustomObject]$RestResponse) {

            if ($WaitForCompletion.IsPresent) {
                # if the wait for completion flag is given, the output will be different, we will wait here
                # we will use the built-in function to check status
                $ElapsedTime = 0
                do {
                    $RequestResponse = Get-vAARequest -RequestId $RestResponse.id
                    if ($RequestResponse.Status -eq "FINISHED") {
                        foreach ($Resource in $RequestResponse.Resources) {
                            $Record = Invoke-vAARestMethod -URI "$Resource" -Method GET
                            [PSCustomObject]@{
                                Name = $Record.name
                                PowerState = $Record.powerState
                                IPAddress = $Record.address
                                ExternalRegionId = $Record.externalRegionId
                                CloudAccountIDs = $Record.cloudAccountIds
                                ExternalId = $Record.externalId
                                Id = $Record.id
                                DateCreated = $Record.createdAt
                                LastUpdated = $Record.updatedAt
                                OrganizationId = $Record.organizationId
                                Properties = $Record.customProperties
                                RequestId = $Response.id
                                RequestStatus = "FINISHED"
                            }
                        }
                        break # leave loop as we are done here
                    }
                    $ElapsedTime += 5
                    Start-Sleep -Seconds 5
                } while ($ElapsedTime -lt $CompletionTimeout)

                if ($ElapsedTime -gt $CompletionTimeout -or $ElapsedTime -eq $CompletionTimeout) {
                    # we have errored out
                    [PSCustomObject]@{
                        Name = $RestResponse.name
                        Progress = $RestResponse.progress
                        Resources = $RestResponse.resources
                        RequestId = $RestResponse.id
                        Message = "We waited for completion, but we hit a timeout at $CompletionTimeout seconds. You may use Get-vAARequest -RequestId $($RestResponse.id) to continue checking status. Here was the original response: $($RestResponse.message)"
                        RequestStatus = $RestResponse.status
                    }
                }
            } else {
                [PSCustomObject]@{
                    Name = $RestResponse.name
                    Progress = $RestResponse.progress
                    Resources = $RestResponse.resources
                    RequestId = $RestResponse.id
                    Message = $RestResponse.message
                    RequestStatus = $RestResponse.status
                }
            }
        }
    }
    Process {

        try {

                switch ($PsCmdlet.ParameterSetName) {

                    # --- Shutdown the given machine by its id
                    'ShutdownById' {

                        foreach ($MachineId in $Id) {
                            if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($MachineId)) {
                                $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId/operations/shutdown" -Method POST
                                CalculateOutput $CompletionTimeout $WaitForCompletion $RestResponse
                            }
                        }
                        break
                    }

                    # --- Shutdown the given machine by its name
                    'ShutdownByName' {

                        foreach ($Machine in $Name) {
                            if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($Machine)) {
                                $MachineResponse = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$Machine'`&`$select=id" -Method GET
                                $MachineId = $MachineResponse.content[0].Id

                                $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId/operations/shutdown" -Method POST
                                CalculateOutput $CompletionTimeout $WaitForCompletion $RestResponse
                            }
                        }
                        break
                    }

                }
        }
        catch [Exception]{

            throw
        }
    }
    End {

    }
}


<#
    - Function: Suspend-vAAMachine
#>


function Suspend-vAAMachine {
    <#
        .SYNOPSIS
        Suspend a vRA Machine
 
        .DESCRIPTION
        Suspend a vRA Machine
 
        .PARAMETER Id
        The ID of the vRA Machine
 
        .PARAMETER Name
        The Name of the vRA Machine
 
        .PARAMETER WaitForCompletion
        If this flag is added, this function will wait for the suspend operation to complete
 
        .PARAMETER CompletionTimeout
        The default of this paramter is 2 minutes (120 seconds), but this parameter can be overriden here
 
        .PARAMETER Force
        Force this change
 
        .OUTPUTS
        System.Management.Automation.PSObject.
 
        .EXAMPLE
        Suspend-vAAMachine -Id 'b1dd48e71d74267559bb930934470'
 
        .EXAMPLE
        Suspend-vAAMachine -Name 'iaas01'
 
        .EXAMPLE
        Suspend-vAAMachine -Name 'iaas01' -WaitForCompletion
 
        .EXAMPLE
        Suspend-vAAMachine -Name 'iaas01' -WaitForCompletion -CompletionTimeout 300
 
    #>

    [CmdletBinding(SupportsShouldProcess, ConfirmImpact='High', DefaultParameterSetName="SuspendByName")][OutputType('System.Management.Automation.PSObject')]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'WaitForCompletion',Justification = 'False positive as rule does not scan child scopes')]
    [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'CompletionTimeout',Justification = 'False positive as rule does not scan child scopes')]

        Param (

            [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="SuspendById")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Id,

            [Parameter(Mandatory=$true,ParameterSetName="SuspendByName")]
            [ValidateNotNullOrEmpty()]
            [String[]]$Name,

            [Parameter()]
            [switch]$WaitForCompletion,

            [Parameter()]
            [int]$CompletionTimeout = 120,

            [Parameter()]
            [switch]$Force

        )
        Begin {

            $APIUrl = "/iaas/api/machines"

            function CalculateOutput([int]$CompletionTimeout,[switch]$WaitForCompletion,[PSCustomObject]$RestResponse) {

                if ($WaitForCompletion.IsPresent) {
                    # if the wait for completion flag is given, the output will be different, we will wait here
                    # we will use the built-in function to check status
                    $ElapsedTime = 0
                    do {
                        $RequestResponse = Get-vAARequest -RequestId $RestResponse.id
                        if ($RequestResponse.Status -eq "FINISHED") {
                            foreach ($Resource in $RequestResponse.Resources) {
                                $Record = Invoke-vAARestMethod -URI "$Resource" -Method GET
                                [PSCustomObject]@{
                                    Name = $Record.name
                                    PowerState = $Record.powerState
                                    IPAddress = $Record.address
                                    ExternalRegionId = $Record.externalRegionId
                                    CloudAccountIDs = $Record.cloudAccountIds
                                    ExternalId = $Record.externalId
                                    Id = $Record.id
                                    DateCreated = $Record.createdAt
                                    LastUpdated = $Record.updatedAt
                                    OrganizationId = $Record.organizationId
                                    Properties = $Record.customProperties
                                    RequestId = $Response.id
                                    RequestStatus = "FINISHED"
                                }
                            }
                            break # leave loop as we are done here
                        }
                        $ElapsedTime += 5
                        Start-Sleep -Seconds 5
                    } while ($ElapsedTime -lt $CompletionTimeout)

                    if ($ElapsedTime -gt $CompletionTimeout -or $ElapsedTime -eq $CompletionTimeout) {
                        # we have errored out
                        [PSCustomObject]@{
                            Name = $RestResponse.name
                            Progress = $RestResponse.progress
                            Resources = $RestResponse.resources
                            RequestId = $RestResponse.id
                            Message = "We waited for completion, but we hit a timeout at $CompletionTimeout seconds. You may use Get-vAARequest -RequestId $($RestResponse.id) to continue checking status. Here was the original response: $($RestResponse.message)"
                            RequestStatus = $RestResponse.status
                        }
                    }
                } else {
                    [PSCustomObject]@{
                        Name = $RestResponse.name
                        Progress = $RestResponse.progress
                        Resources = $RestResponse.resources
                        RequestId = $RestResponse.id
                        Message = $RestResponse.message
                        RequestStatus = $RestResponse.status
                    }
                }
            }
        }
        Process {

            try {


                    switch ($PsCmdlet.ParameterSetName) {

                        # --- Suspend the given machine by its id
                        'SuspendById' {

                            foreach ($MachineId in $Id) {
                                if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($Machineid)) {
                                    $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId/operations/suspend" -Method POST
                                    CalculateOutput $CompletionTimeout $WaitForCompletion $RestResponse
                                }
                            }
                            break
                        }

                        # --- Suspend the given machine by its name
                        'SuspendByName' {

                            foreach ($Machine in $Name) {
                                if ($Force.IsPresent -or $PsCmdlet.ShouldProcess($Machine)) {
                                    $MachineResponse = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$Machine'`&`$select=id" -Method GET
                                    $MachineId = $MachineResponse.content[0].Id

                                    $RestResponse = Invoke-vAARestMethod -URI "$APIUrl`/$MachineId/operations/suspend" -Method POST
                                    CalculateOutput $CompletionTimeout $WaitForCompletion $RestResponse
                                }
                            }
                            break
                        }

                    }
            }
            catch [Exception]{

                throw
            }
        }
        End {

        }
    }


<#
    - Function: Update-vAAExternalNetworkIPRange
#>


function Update-vAAExternalNetworkIPRange {
<#
    .SYNOPSIS
    Update the vRA External Network IP Range depending on input
 
    .DESCRIPTION
    Update the vRA External Network IP Range depending on input, only thing that can be updated is associated fabric at this time.
 
    .PARAMETER Id
    The ID of the vRA External Network IP Range
 
    .PARAMETER Name
    The Name of the vRA External Network IP Range
 
    .PARAMETER FabricId
    The id of the fabric network that this IP range should be associated with.
 
    .OUTPUTS
    System.Management.Automation.PSObject.
 
    .EXAMPLE
    Update-vAAExternalNetworkIPRange
 
    .EXAMPLE
    Update-vAAExternalNetworkIPRange -Id 'b1dd48e71d74267559bb930934470' -FabricId 'MyFabricNetworkId'
 
    .EXAMPLE
    Update-vAAExternalNetworkIPRange -Name 'my-external-network-name' -FabricId 'MyFabricNetworkId'
 
#>

[CmdletBinding(SupportsShouldProcess,ConfirmImpact="Low",DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Name,

        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [String]$FabricId

    )
    Begin {

        $APIUrl = "/iaas/api/external-network-ip-ranges"

        function CalculateOutput([PSCustomObject] $ExternalNetworkIPRange) {

            [PSCustomObject] @{
                Owner = $ExternalNetworkIPRange.owner
                Description = $ExternalNetworkIPRange.description
                Tags = $ExternalNetworkIPRange.tags
                ExternalId = $ExternalNetworkIPRange.externalId
                SubnetPrefixLength = $ExternalNetworkIPRange.subnetPrefixLength
                Name = $ExternalNetworkIPRange.name
                Id = $ExternalNetworkIPRange.id
                CreatedAt = $ExternalNetworkIPRange.createdAt
                UpdatedAt = $ExternalNetworkIPRange.updatedAt
                OrganizationId = $ExternalNetworkIPRange.orgId
                StartIPAddress = $ExternalNetworkIPRange.startIPAddress
                EndIPAddress = $ExternalNetworkIPRange.endIPAddress
                IPVersion = $ExternalNetworkIPRange.ipVersion
                AddressSpaceId = $ExternalNetworkIPRange.addressSpaceId
                DNSServerAddresses = $ExternalNetworkIPRange.dnsServerAddresses
                DNSSearchDomains = $ExternalNetworkIPRange.dnsSearchDomains
                Domain = $ExternalNetworkIPRange.domain
                GatewayAddress = $ExternalNetworkIPRange.gatewayAddress
                Links = $ExternalNetworkIPRange._links
            }
        }
    }
    Process {

        try {

            $Body = @"
                    {
                        "fabricNetworkId": "$($FabricId)"
                    }
"@


            switch ($PsCmdlet.ParameterSetName) {

                # --- Process by its id
                'ById' {
                    if ($PSCmdlet.ShouldProcess($Id)){
                    foreach ($networkId in $Id) {
                        $Response = Invoke-vAARestMethod -URI "$APIUrl/$networkId" -Body $Body -Method PATCH
                        CalculateOutput $Response
                    }
                }
                    break
                }

                # --- Process by its name
                'ByName' {
                    if ($PSCmdlet.ShouldProcess($Name)){
                    foreach ($networkName in $Name) {
                       $network = Get-vAAExternalNetworkIPRange -name $networkName
                       $Response = Invoke-vAARestMethod -URI "$APIUrl/$($network.Id)" -Body $Body -Method PATCH
                       CalculateOutput $Response
                    }
                }
                    break
                }

            }


        }
        catch [Exception]{

            throw
        }
    }
    End {

    }
}


<#
    - Function: Update-vAAvSphereFabricNetwork
#>


function Update-vAAvSphereFabricNetwork {
<#
    .SYNOPSIS
    Update the vRA External Network IP Range depending on input
 
    .DESCRIPTION
    Update the vRA External Network IP Range depending on input, only thing that can be updated is associated fabric at this time.
 
    .PARAMETER Id
    The ID of the vRA External Network IP Range
 
    .PARAMETER Name
    The Name of the vRA External Network IP Range
 
    .PARAMETER Ipv6Cidr
    Network IPv6 CIDR to be used
 
    .PARAMETER IsDefault
    Indicates whether this is the default subnet for the zone.
 
    .PARAMETER Domain
    Domain value.
     
    .PARAMETER DefaultIpv6Gateway
    IPv6 default gateway to be used.
 
    .PARAMETER DnsServerAddresses
    A list of DNS server addresses that were set on this resource instance.
 
    .PARAMETER IsPublic
    Indicates whether the sub-network supports public IP assignment.
 
    .PARAMETER Cidr
    Network CIDR to be used.
 
    .PARAMETER DefaultGateway
    IPv4 default gateway to be used.
 
    .PARAMETER Tags
    A set of tag keys and optional values that were set on this resource instance.
 
    .PARAMETER DnsSearchDomains
    A list of DNS search domains that were set on this resource instance.
 
    .PARAMETER CloudAccountName
    The name of the vRA Cloud account to search for (optional)
 
    .PARAMETER CloudAccountId
    The ID of the vRA Cloud Account to search for (optional)
     
    .OUTPUTS
    System.Management.Automation.PSObject.
 
    .EXAMPLE
    Update-vAAvSphereFabricNetwork
 
    .EXAMPLE
    Update-vAAvSphereFabricNetwork -Id 'b1dd48e71d74267559bb930934470' -DefaultGateway '1.1.1.1'
 
    .EXAMPLE
    Update-vAAvSphereFabricNetwork -Name 'my-fabric-network' -DefaultGateway '1.1.1.1'
 
#>

[CmdletBinding(SupportsShouldProcess,ConfirmImpact="Low",DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]
 [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'Ipv6Cidr',Justification = 'False positive as rule does not scan child scopes')]
 [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'Domain',Justification = 'False positive as rule does not scan child scopes')]
 [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSReviewUnusedParameter', 'Tags',Justification = 'False positive as rule does not scan child scopes')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Name,

        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [String]$Ipv6Cidr,

        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [bool]$IsDefault,

        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [String]$Domain,

        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [String]$DefaultIpv6Gateway,

        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [String[]]$DnsServerAddresses,

        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [bool]$IsPublic,

        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [String]$Cidr,

        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [String]$DefaultGateway,

        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [String[]]$Tags,

        [Parameter(Mandatory=$false,ParameterSetName="ByName")]
        [Parameter(Mandatory=$false,ParameterSetName="ById")]
        [String[]]$DnsSearchDomains,

        [Parameter(Mandatory=$false)]
        [ValidateNotNullOrEmpty()]
        [String[]]$CloudAccountName,

        [Parameter(Mandatory=$false)]
        [ValidateNotNullOrEmpty()]
        [String[]]$CloudAccountId



    )
    Begin {

        $APIUrl = "/iaas/api/fabric-networks-vsphere"

        function CalculateOutput ([PSCustomObject]$FabricNetworks) {
            
                [PSCustomObject]@{
                    DefaultGateway = $FabricNetworks.defaultGateway
                    IsPublic = $FabricNetworks.isPublic
                    IsDefault = $FabricNetworks.isDefault
                    ExternalRegionId = $FabricNetworks.externalRegionId
                    CloudAccountIds = $FabricNetworks.cloudAccountIds
                    ExternalId = $FabricNetworks.externalId
                    Name = $FabricNetworks.name
                    Id = $FabricNetworks.id
                    CreatedAt = $FabricNetworks.createdAt
                    UpdatedAt = $FabricNetworks.updatedAt
                    OrganizationId = $FabricNetworks.organizationId
                    OrgId = $FabricNetworks.orgId
                    Links = $FabricNetworks._links
                }
            
        }

        function buildUpdateBody([PSCustomObject]$CurrentRecord,
                                    [bool]$IsDefault,
                                    [String]$DefaultIpv6Gateway,
                                    [String[]]$DnsServerAddresses,
                                    [bool]$IsPublic,
                                    [String]$Cidr,
                                    [String]$DefaultGateway,
                                    [String[]]$DnsSearchDomains) {
            $DnsServerAddressesJson = ($DnsServerAddresses | ForEach-Object {"`"$_`""}) -join ","
            $DnsSearchDomainsJson = ($DnsSearchDomains | ForEach-Object {"`"$_`""}) -join ","
            if($DnsServerAddressesJson -eq "`"`"") {
                $DnsServerAddressesJson = $null
            }
            if($DnsSearchDomainsJson -eq "`"`"") {
                $DnsSearchDomainsJson = $null
            }

            # handle Tags
            $TagsJson = "null"
            if ($null -ne $Tags) {
                $TagsJson = ($Tags | ForEach-Object { 
                    $TagSplit = $_.Split(":")
                    [PSCustomObject]@{
                        key = $TagSplit[0]
                        value = $TagSplit[1]
                    }   
                }) | ConvertTo-Json -Depth 5 -Compress
            }

            # handle items that may not have been supplied but exist already on object
            # we keep that value just in case so that is not inadvertantly wiped out
            if ($CurrentRecord.PSObject.Properties.name -match "content") {
                $CurrentRecord = $CurrentRecord[0]
            }

            if ($null -eq $Ipv6Cidr) {
                $Ipv6Cidr = $CurrentRecord.ipv6Cidr
            }
            if ($null -eq $IsDefault) {
                $IsDefault = $CurrentRecord.isDefault
            }
            if ($null -eq $IsPublic) {
                $IsPublic = $CurrentRecord.isPublic
            }
            if ($null -eq $Cidr) {
                $Cidr = $CurrentRecord.cidr
            }

            $RawJson = @"
                {
                    "ipv6Cidr": "$($Ipv6Cidr)",
                    "isDefault": $($isDefault | ConvertTo-Json),
                    "domain": "$($Domain)",
                    "defaultIpv6Gateway": "$($DefaultIpv6Gateway)",
                    "dnsServerAddresses": [ $($DnsServerAddressesJson) ],
                    "isPublic": $($IsPublic | ConvertTo-Json),
                    "cidr": "$($Cidr)",
                    "defaultGateway": "$($DefaultGateway)",
                    "tags": $($TagsJson),
                    "dnsSearchDomains": [ $($DnsSearchDomainsJson) ]
                }
"@

            $Body = ($RawJson | ConvertFrom-Json) | ConvertTo-Json -Depth 5

            return $Body
        }

        function buildAccountQuery([String[]]$CloudAccountName,
                                    [String[]]$CloudAccountId) {
            $accountIdString = ''
            $cloudAccountIds = @()

            if ($null -ne $CloudAccountName -and "" -ne $CloudAccountName) {
                # pull the ID's from each cloud account
                $cloudAccountIds = Get-vAACloudAccount -Name $CloudAccountName | Select-Object Id | ForEach-Object { $_.Id }
            }
            if ($null -ne $CloudAccountId) {
                $cloudAccountIds = $cloudAccountIds + @($CloudAccountId)
            }
            foreach ($id in $cloudAccountIds) {
                $accountIdString = $accountIdString + ",'$id'"
            }
            if ($accountIdString -ne '') {
                return "cloudAccountIds.item any $($accountIdString.substring(1))"
            } else {
                return ""
            }
        }
    }
    Process {

        try {

            $Body = @"
                    {
                        "fabricNetworkId": "$($FabricId)"
                    }
"@


            switch ($PsCmdlet.ParameterSetName) {

                # --- Process by its id
                'ById' {
                    if ($PSCmdlet.ShouldProcess($Id)){
                    foreach ($networkId in $Id) {
                        $CurrentRecord = Invoke-vAARestMethod -URI "$APIUrl/$networkId" -Method GET

                        # build the body of the update request
                        $Body = buildUpdateBody -CurrentRecord $CurrentProtocols -IsDefault $IsDefault `
                                                -DefaultIpv6Gateway $DefaultIpv6Gateway -DnsServerAddresses $DnsServerAddresses `
                                                -IsPublic $IsPublic -Cidr $Cidr -DefaultGateway $DefaultGateway -DnsSearchDomains $DnsSearchDomains

                        # send the udpate request
                        $Response = Invoke-vAARestMethod -URI "$APIUrl/$($CurrentRecord.Id)" -Body $Body -Method PATCH

                        CalculateOutput $Response
                    }
                }
                    break
                }

                # --- Process by its name
                'ByName' {
                    if ($PSCmdlet.ShouldProcess($Name)){
                    $acctQuery = buildAccountQuery -CloudAccountName $CloudAccountName -CloudAccountId $CloudAccountId
                    foreach ($networkName in $Name) {
                        if ($null -ne $acctQuery -and '' -ne $acctQuery) {
                            $CurrentRecord = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$networkName' and $acctQuery" -Method GET
                        } else {
                            $CurrentRecord = Invoke-vAARestMethod -URI "$APIUrl`?`$filter=name eq '$networkName'" -Method GET
                        }
                        
                        # build the body of the update request
                        $Body = buildUpdateBody -CurrentRecord $CurrentProtocols -IsDefault $IsDefault `
                                                -DefaultIpv6Gateway $DefaultIpv6Gateway -DnsServerAddresses $DnsServerAddresses `
                                                -IsPublic $IsPublic -Cidr $Cidr -DefaultGateway $DefaultGateway -DnsSearchDomains $DnsSearchDomains

                        # send the udpate request
                        $Response = Invoke-vAARestMethod -URI "$APIUrl/$($CurrentRecord.Id)" -Body $Body -Method PATCH
                        CalculateOutput $Response
                    }
                }
                    break
                }

            }


        }
        catch [Exception]{

            throw
        }
    }
    End {

    }
}


<#
    - Function: Get-vAAOnboardingDeployment
#>


function Get-vAAOnboardingDeployment {
<#
    .SYNOPSIS
    Get a vRA OnboardingDeployment.
 
    .DESCRIPTION
    Get a vRA OnboardingDeployment.
 
    .PARAMETER Id
    The ID of the OnboardingDeployment
 
    .PARAMETER Name
    The Name of the OnboardingDeployment
 
    .INPUTS
    System.String
 
    .OUTPUTS
    System.Management.Automation.PSObject
 
    .EXAMPLE
    Get-vAAOnboardingDeployment
 
    .EXAMPLE
    Get-vAAOnboardingDeployment -Id '247d9305a4231275581a098553c26'
 
    .EXAMPLE
    Get-vAAOnboardingDeployment -Name 'Test OnboardingDeployment'
 
#>

[CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Name
    )

    Begin {
        $APIUrl = '/relocation/onboarding/deployment'

        function CalculateOutput($ResponseObject) {

            $DocumentSelfLink = $ResponseObject.documentSelfLink
            $OnboardingDeploymentId = ($DocumentSelfLink -split "/")[-1]

            [PSCustomObject] @{

                Name = $ResponseObject.name
                Id = $OnboardingDeploymentId
                PlanLink = $ResponseObject.planLink
                ConsumerDeploymentLink = $ResponseObject.consumerDeploymentLink
                DocumentSelfLink = $DocumentSelfLink
            }
        }
    }

    Process {

        try {

            switch ($PsCmdlet.ParameterSetName) {

                # --- Get Onboarding Deployment by id
                'ById' {

                    foreach ($OnboardingDeploymentId in $Id){

                        $URI = "$($APIUrl)/$($OnboardingDeploymentId)"

                        $OnboardingDeployment= Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        CalculateOutput $OnboardingDeployment
                    }

                    break
                }
                # --- Get Onboarding Deployment by name
                'ByName' {

                    $URI = "$($APIUrl)?`$expand=true"

                    $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                    foreach ($OnboardingDeploymentName in $Name){

                        $MatchedOnboardingDeployment = $false

                        foreach ($Document in $Response.documentLinks){

                            $OnboardingDeployment = $Response.documents.$document

                            if ($OnboardingDeployment.name -eq $OnboardingDeploymentName){

                                $MatchedOnboardingDeployment = $true
                                CalculateOutput $OnboardingDeployment
                            }
                        }

                        if (!$MatchedOnboardingDeployment) {

                            throw "Could not find Onboarding Deployment with name: $($OnboardingDeploymentName)"
                        }
                    }

                    break
                }
                # --- No parameters passed so return all Onboarding Deployments
                'Standard' {

                    $URI = "$($APIUrl)?`$expand=true"

                    $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                    foreach ($Document in $Response.documentLinks){

                        $OnboardingDeployment = $Response.documents.$document

                        CalculateOutput $OnboardingDeployment
                    }
                }
            }
        }
        catch [Exception]{

            throw
        }
    }

    End {

    }
}

<#
    - Function: Get-vAAOnboardingPlan
#>


function Get-vAAOnboardingPlan {
<#
    .SYNOPSIS
    Get a vRA OnboardingPlan.
 
    .DESCRIPTION
    Get a vRA OnboardingPlan.
 
    .PARAMETER Id
    The ID of the OnboardingPlan
 
    .PARAMETER Name
    The Name of the OnboardingPlan
 
    .INPUTS
    System.String
 
    .OUTPUTS
    System.Management.Automation.PSObject
 
    .EXAMPLE
    Get-vAAOnboardingPlan
 
    .EXAMPLE
    Get-vAAOnboardingPlan -Id '247d9305a4231275581a098553c26'
 
    .EXAMPLE
    Get-vAAOnboardingPlan -Name 'Test OnboardingPlan'
 
#>

[CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Name
    )

    Begin {
        $APIUrl = '/relocation/onboarding/plan'

        function CalculateOutput($ResponseObject) {

            $DocumentSelfLink = $ResponseObject.documentSelfLink
            $OnboardingPlanId = ($DocumentSelfLink -split "/")[-1]

            [PSCustomObject] @{

                Name = $ResponseObject.name
                Id = $OnboardingPlanId
                Status = $ResponseObject.status
                EndpointName = $ResponseObject.endpointName
                EndpointId = $ResponseObject.endpointId
                EndpointIds = $ResponseObject.endpointIds
                ProjectName = $ResponseObject.projectName
                ProjectId = $ResponseObject.projectId
                CreatedBy = $ResponseObject.createdBy
                EnableExtensibilityEvents = $ResponseObject.enableExtensibilityEvents
                OrganizationId = $ResponseObject.organizationId
                LastRunTimeMicros = $ResponseObject.lastRunTimeMicros
                NextRefreshTimeMicros = $ResponseObject.nextRefreshTimeMicros
                RefreshIntervalMicros = $ResponseObject.refreshIntervalMicros
                DocumentSelfLink = $DocumentSelfLink
            }
        }
    }

    Process {

        try {

            switch ($PsCmdlet.ParameterSetName) {

                # --- Get Onboarding Plan by id
                'ById' {

                    foreach ($OnboardingPlanId in $Id){

                        $URI = "$($APIUrl)/$($OnboardingPlanId)"

                        $OnboardingPlan= Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        CalculateOutput $OnboardingPlan
                    }

                    break
                }
                # --- Get Onboarding Plan by name
                'ByName' {

                    $URI = "$($APIUrl)?`$expand=true"

                    $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                    foreach ($OnboardingPlanName in $Name){

                        $MatchedOnboardingPlan = $false

                        foreach ($Document in $Response.documentLinks){

                            $OnboardingPlan = $Response.documents.$document

                            if ($OnboardingPlan.name -eq $OnboardingPlanName){

                                $MatchedOnboardingPlan = $true
                                CalculateOutput $OnboardingPlan
                            }
                        }

                        if (!$MatchedOnboardingPlan) {

                            throw "Could not find Onboarding Plan with name: $($OnboardingPlanName)"
                        }
                    }

                    break
                }
                # --- No parameters passed so return all Onboarding Plans
                'Standard' {

                    $URI = "$($APIUrl)?`$expand=true"

                    $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                    foreach ($Document in $Response.documentLinks){

                        $OnboardingPlan = $Response.documents.$document

                        CalculateOutput $OnboardingPlan
                    }
                }
            }
        }
        catch [Exception]{

            throw
        }
    }

    End {

    }
}

<#
    - Function: Get-vAAOnboardingPlanExecution
#>


function Get-vAAOnboardingPlanExecution {
<#
    .SYNOPSIS
    Get a vRA OnboardingPlanExecution
 
    .DESCRIPTION
    Get a vRA OnboardingPlanExecution
 
    .PARAMETER Id
    The ID of the OnboardingPlanExecution
 
    .PARAMETER ExecutionPlanLink
    The Execution Plan Link
 
    .INPUTS
    System.String
 
    .OUTPUTS
    System.Management.Automation.PSObject
 
    .EXAMPLE
    Get-vAAOnboardingPlanExecution -Id 'ig885f86-0e2d-4157-r5d4-8cb42ce6dd84'
 
    .EXAMPLE
    Get-vAAOnboardingPlanExecution -ExecutionPlanLink '/relocation/api/wo/execute-plan/ig885f86-0e2d-4157-r5d4-8cb42ce6dd8'
 
#>

[CmdletBinding(DefaultParameterSetName="ById")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ByExecutionPlanLink")]
        [ValidateNotNullOrEmpty()]
        [String[]]$ExecutionPlanLink
    )

    begin {

        function CalculateOutput($ResponseObject) {

            [PSCustomObject] @{

                ExecutionId = $ResponseObject.executionId
                DocumentSelfLink = $ResponseObject.documentSelfLink
                PlanLink = $ResponseObject.planLink
                TaskInfo = $ResponseObject.taskInfo
                SubStage = $ResponseObject.subStage
                PlanValidated = $ResponseObject.planValidated
                BlueprintsValidated = $ResponseObject.blueprintsValidated
                DeploymentsValidated = $ResponseObject.deploymentsValidated
                MachinesValidated = $ResponseObject.machinesValidated
                DeploymentCount = $ResponseObject.deploymentCount
                RetryCount = $ResponseObject.retryCount
                FailedDeploymentCount = $ResponseObject.failedDeploymentCount
            }
        }
    }

    process {

        try {

            switch ($PsCmdlet.ParameterSetName) {

                # --- Get Onboarding Plan Execution by Id
                'ById' {

                    foreach ($OnboardingPlanExecutionId in $Id){

                        $URI = "/relocation/api/wo/execute-plan/$($OnboardingPlanExecutionId)"

                        $ExecuteOnboardingPlan = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        CalculateOutput $ExecuteOnboardingPlan
                    }

                    break
                }
                # --- Get Onboarding Plan Execution by Name
                'ByExecutionPlanLink' {

                    foreach ($OnboardingPlanExecutionLink in $ExecutionPlanLink){

                        $ExecuteOnboardingPlan = Invoke-vAARestMethod -Method GET -URI $OnboardingPlanExecutionLink -Verbose:$VerbosePreference

                        CalculateOutput $ExecuteOnboardingPlan
                    }

                    break
                }
            }
        }
        catch [Exception]{

            throw
        }
    }
    end {

    }
}

<#
    - Function: Get-vAAOnboardingResource
#>


function Get-vAAOnboardingResource {
<#
    .SYNOPSIS
    Get a vRA Onboarding Resource
 
    .DESCRIPTION
    Get a vRA Onboarding Resource
 
    .PARAMETER Id
    The ID of the Onboarding Resource
 
    .PARAMETER Name
    The Name of the Onboarding Resource
 
    .INPUTS
    System.String
 
    .OUTPUTS
    System.Management.Automation.PSObject
 
    .EXAMPLE
    Get-vAAOnboardingResource
 
    .EXAMPLE
    Get-vAAOnboardingResource -Id '0b8c2def-b2bc-3fb1-a88f-0621dacdab71'
 
    .EXAMPLE
    Get-vAAOnboardingResource -Name 'Test OnboardingResource'
 
#>

[CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Name
    )

    begin {
        $APIUrl = '/relocation/onboarding/resource'

        function CalculateOutput($ResponseObject) {

            $DocumentSelfLink = $ResponseObject.documentSelfLink
            $OnboardingResourceId = ($DocumentSelfLink -split "/")[-1]

            [PSCustomObject] @{

                Name = $ResponseObject.resourceName
                Id = $OnboardingResourceId
                PlanLink = $ResponseObject.planLink
                ResourceLink = $ResponseObject.resourceLink
                DeploymentLink = $ResponseObject.deploymentLink
                TagLinks = $ResponseObject.tagLinks
                RuleLinks = $ResponseObject.ruleLinks
                CreatedTimeMicros = $ResponseObject.createdTimeMicros
                DocumentSelfLink = $DocumentSelfLink
            }
        }
    }

    process {

        try {

            switch ($PsCmdlet.ParameterSetName) {

                # --- Get Onboarding Resource by Id
                'ById' {

                    foreach ($OnboardingResourceId in $Id){

                        $URI = "$($APIUrl)/$($OnboardingResourceId)"
                        $OnboardingResource= Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                        CalculateOutput $OnboardingResource
                    }

                    break
                }
                # --- Get Onboarding Resource by Name
                'ByName' {

                    $URI = "$($APIUrl)?`$expand=true"
                    $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                    foreach ($OnboardingResourceName in $Name){

                        $MatchedOnboardingResource = $false

                        foreach ($Document in $Response.documentLinks){

                            $OnboardingResource = $Response.documents.$document

                            if ($OnboardingResource.resourceName -eq $OnboardingResourceName){

                                $MatchedOnboardingResource = $true
                                CalculateOutput $OnboardingResource
                            }
                        }

                        if (!$MatchedOnboardingResource) {

                            throw "Could not find Onboarding Resource with name: $($OnboardingResourceName)"
                        }
                    }

                    break
                }
                # --- No parameters passed so return all Onboarding Resources
                'Standard' {

                    $URI = "$($APIUrl)?`$expand=true"
                    $Response = Invoke-vAARestMethod -Method GET -URI $URI -Verbose:$VerbosePreference

                    foreach ($Document in $Response.documentLinks){

                        $OnboardingResource = $Response.documents.$document

                        CalculateOutput $OnboardingResource
                    }
                }
            }
        }
        catch [Exception]{

            throw
        }
    }
    end {

    }
}

<#
    - Function: Invoke-vAAOnboardingPlan
#>


function Invoke-vAAOnboardingPlan {
<#
    .SYNOPSIS
    Execute a vRA Onboarding Plan
 
    .DESCRIPTION
    Execute a vRA Onboarding Plan
 
    .PARAMETER Name
    The Name of the Onboarding Plan
 
    .PARAMETER Id
    The Id of the Onboarding Plan
 
    .PARAMETER PlanLink
    The Link of the Onboarding Plan
 
    .PARAMETER JSON
    A JSON string with the body payload
 
    .INPUTS
    System.String
 
    .OUTPUTS
    System.Management.Automation.PSObject
 
    .EXAMPLE
    Invoke-vAAOnboardingPlan -Name "TestOnboardingPlan"
 
    .EXAMPLE
    Invoke-vAAOnboardingPlan -Id "ecaa2cf0-2f8c-4a79-r4d7-27f13c7d3ee6"
 
    .EXAMPLE
    Invoke-vAAOnboardingPlan -PlanLink "/relocation/onboarding/plan/ecaa2cf0-2f8c-4a79-r4d7-27f13c7d3ee6"
 
    .EXAMPLE
    $JSON = @"
 
        {
            "planLink": "/relocation/onboarding/plan/ecaa2cf0-2f8c-4a79-r4d7-27f13c7d3ee6"
        }
"@
 
    $JSON | Invoke-vAAOnboardingPlan
#>

[CmdletBinding(SupportsShouldProcess,ConfirmImpact="Low",DefaultParameterSetName="ById")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,ParameterSetName="ById")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Id,

        [Parameter(Mandatory=$true,ParameterSetName="ByName")]
        [ValidateNotNullOrEmpty()]
        [String[]]$Name,

        [Parameter(Mandatory=$true,ParameterSetName="ByPlanLink")]
        [ValidateNotNullOrEmpty()]
        [String[]]$PlanLink,

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ParameterSetName="JSON")]
        [ValidateNotNullOrEmpty()]
        [String]$JSON

    )

    begin {

        $URI = "/relocation/api/wo/execute-plan"
        function CalculateOutput($ResponseObject) {

            [PSCustomObject] @{

                ExecutionId = $ResponseObject.executionId
                DocumentSelfLink = $ResponseObject.documentSelfLink
                PlanLink = $ResponseObject.planLink
                TaskInfo = $ResponseObject.taskInfo
                SubStage = $ResponseObject.subStage
                PlanValidated = $ResponseObject.planValidated
                BlueprintsValidated = $ResponseObject.blueprintsValidated
                DeploymentsValidated = $ResponseObject.deploymentsValidated
                MachinesValidated = $ResponseObject.machinesValidated
                DeploymentCount = $ResponseObject.deploymentCount
                RetryCount = $ResponseObject.retryCount
                FailedDeploymentCount = $ResponseObject.failedDeploymentCount
            }
        }
    }

    process {
        try {

            switch ($PsCmdlet.ParameterSetName) {

                # --- Execute Onboarding Plan by Id
                'ById' {

                    foreach ($OnboardingPlanId in $Id){

                        if ($PSCmdlet.ShouldProcess($OnboardingPlanId)){

                            $Body = @"
                            {
                                "planLink": "/relocation/onboarding/plan/$($OnboardingPlanId)"
                            }
"@

                            $ExecuteOnboardingPlan= Invoke-vAARestMethod -Method POST -URI $URI -Body $Body -Verbose:$VerbosePreference

                            CalculateOutput $ExecuteOnboardingPlan
                        }
                    }

                    break
                }
                # --- Execute Onboarding Plan by Name
                'ByName' {

                    foreach ($OnboardingPlanName in $Name){

                        if ($PSCmdlet.ShouldProcess($OnboardingPlanName)){

                            $OnboardingPlanLink = (Get-vAAOnboardingPlan -Name $OnboardingPlanName).DocumentSelfLink
                            $Body = @"
                            {
                                "planLink": "$($OnboardingPlanLink)"
                            }
"@

                            $ExecuteOnboardingPlan= Invoke-vAARestMethod -Method POST -URI $URI -Body $Body -Verbose:$VerbosePreference

                            CalculateOutput $ExecuteOnboardingPlan
                        }
                    }
                }
                # --- Execute Onboarding Plan by PlanLink
                'ByPlanLink' {

                    foreach ($OnboardingPlanLink in $PlanLink){

                        if ($PSCmdlet.ShouldProcess($OnboardingPlanLink)){

                            $Body = @"
                            {
                                "planLink": "$($OnboardingPlanLink)"
                            }
"@

                            $ExecuteOnboardingPlan= Invoke-vAARestMethod -Method POST -URI $URI -Body $Body -Verbose:$VerbosePreference

                            CalculateOutput $ExecuteOnboardingPlan
                        }
                    }
                }
                # --- Execute Onboarding Plan by JSON
                'JSON' {

                    $Data = ($JSON | ConvertFrom-Json)
                    $Body = $JSON
                    $OnboardingPlanLink = $Data.planLink

                    if ($PSCmdlet.ShouldProcess($OnboardingPlanLink)){

                        $ExecuteOnboardingPlan= Invoke-vAARestMethod -Method POST -URI $URI -Body $Body -Verbose:$VerbosePreference

                        CalculateOutput $ExecuteOnboardingPlan
                    }
                }
            }
        }
        catch [Exception] {

            throw
        }
    }
    end {

    }
}

<#
    - Function: New-vAAOnboardingDeployment
#>


function New-vAAOnboardingDeployment {
<#
    .SYNOPSIS
    Create a vRA Onboarding Deployment
 
    .DESCRIPTION
    Create a vRA Onboarding Deployment
 
    .PARAMETER Name
    The name of the Onboarding Deployment
 
    .PARAMETER OnboardingPlanLink
    Link for the Onboarding Plan to associate with
 
    .PARAMETER JSON
    A JSON string with the body payload
 
    .INPUTS
    System.String
 
    .OUTPUTS
    System.Management.Automation.PSObject
 
    .EXAMPLE
    New-vAAOnboardingDeployment -Name "TestOnboardingDeployment" -OnboardingPlanLink "/relocation/onboarding/plan/282dd58e8dcfc7559a0d225680a7"
 
    .EXAMPLE
    $JSON = @"
 
        {
            "name": "TestOnboardingDeployment",
            "planLink": "/relocation/onboarding/plan/282dd58e8dcfc7559a0d225680a7"
        }
"@
 
    $JSON | New-vAAOnboardingDeployment
 
 
#>

[CmdletBinding(SupportsShouldProcess,ConfirmImpact="Low",DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter(Mandatory=$false,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$OnboardingPlanLink,

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ParameterSetName="JSON")]
        [ValidateNotNullOrEmpty()]
        [String]$JSON

    )

    begin {
        function CalculateOutput($ResponseObject) {

            $DocumentSelfLink = $ResponseObject.documentSelfLink
            $OnboardingDeploymentId = ($DocumentSelfLink -split "/")[-1]

            [PSCustomObject] @{

                Name = $ResponseObject.name
                Id = $OnboardingDeploymentId
                PlanLink = $ResponseObject.planLink
                DocumentSelfLink = $DocumentSelfLink
            }
        }
    }

    process {

        if ($PSBoundParameters.ContainsKey("JSON")) {

            $Data = ($JSON | ConvertFrom-Json)

            $Body = $JSON
            $Name = $Data.name
        }
        else {

            $Body = @"
                {
                    "name": "$($Name)",
                    "planLink": "$($OnboardingPlanLink)"
                }
"@

        }

        # --- Create new Onboarding Deployment
        try {
            if ($PSCmdlet.ShouldProcess($Name)){

                $URI = "/relocation/onboarding/deployment"
                $OnboardingDeployment = Invoke-vAARestMethod -Method POST -URI $URI -Body $Body -Verbose:$VerbosePreference

                CalculateOutput $OnboardingDeployment
            }
        }
        catch [Exception] {

            throw
        }
    }

    end {

    }
}

<#
    - Function: New-vAAOnboardingPlan
#>


function New-vAAOnboardingPlan {
<#
    .SYNOPSIS
    Create a vRA Onboarding Plan
 
    .DESCRIPTION
    Create a vRA Onboarding Plan
 
    .PARAMETER Name
    The name of the Onboarding Plan
 
    .PARAMETER CloudAccountId
    Cloud Account Id for the Onboarding Plan (Note: vRA Cloud API refers to it as endpointId)
 
    .PARAMETER ProjectId
    Project Id for the Onboarding Plan
 
    .PARAMETER JSON
    A JSON string with the body payload
 
    .INPUTS
    System.String
 
    .OUTPUTS
    System.Management.Automation.PSObject
 
    .EXAMPLE
    New-vAAOnboardingPlan -Name "TestOnboardingPlan" -CloudAccountId "42fe38765a63bd755921a88814a14" -ProjectId "9f732951-2279-422a-8045-9b254d427100"
 
    .EXAMPLE
    $JSON = @"
 
        {
            "name": "TestOnboardingPlan",
            "endpointId": "42fe38765a63bd755921a88814a14",
            "projectId": "9f732951-2279-422a-8045-9b254d427100"
        }
"@
 
    $JSON | New-vAAOnboardingPlan
 
 
#>

[CmdletBinding(SupportsShouldProcess,ConfirmImpact="Low",DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$CloudAccountId,

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$ProjectId,

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ParameterSetName="JSON")]
        [ValidateNotNullOrEmpty()]
        [String]$JSON

    )

    Begin {
        function CalculateOutput($ResponseObject) {

            $DocumentSelfLink = $ResponseObject.documentSelfLink
            $OnboardingPlanId = ($DocumentSelfLink -split "/")[-1]

            [PSCustomObject] @{

                Name = $ResponseObject.name
                Id = $OnboardingPlanId
                Status = $ResponseObject.status
                EndpointId = $ResponseObject.endpointId
                EndpointIds = $ResponseObject.endpointIds
                ProjectId = $ResponseObject.projectId
                CreatedBy = $ResponseObject.createdBy
                EnableExtensibilityEvents = $ResponseObject.enableExtensibilityEvents
                OrganizationId = $ResponseObject.organizationId
                DocumentSelfLink = $DocumentSelfLink
            }
        }
    }

    Process {

        if ($PSBoundParameters.ContainsKey("JSON")) {

            $Data = ($JSON | ConvertFrom-Json)

            $Body = $JSON
            $Name = $Data.name
        }
        else {

            $Body = @"
                {
                    "name": "$($Name)",
                    "endpointId": "$($CloudAccountId)",
                    "projectId": "$($ProjectId)"
                }
"@

        }

        # --- Create new Onboarding Plan
        try {
            if ($PSCmdlet.ShouldProcess($Name)){

                $URI = "/relocation/onboarding/plan"
                $OnboardingPlan = Invoke-vAARestMethod -Method POST -URI $URI -Body $Body -Verbose:$VerbosePreference

                CalculateOutput $OnboardingPlan
            }
        }
        catch [Exception] {

            throw
        }
    }

    End {

    }
}

<#
    - Function: New-vAAOnboardingResource
#>


function New-vAAOnboardingResource {
<#
    .SYNOPSIS
    Create a vRA Onboarding Resource
 
    .DESCRIPTION
    Create a vRA Onboarding Resource
 
    .PARAMETER Name
    The name of the Onboarding Resource
 
    .PARAMETER VMId
    The Id of the IaaS VM to associate the Onboarding Resource with
 
    .PARAMETER DeploymentLink
    Link to the Onboarding Deployment to associate the Onboarding Resource with
 
    .PARAMETER PlanLink
    Link to the Onboarding Plan to associate the Onboarding Resource with
 
    .PARAMETER RuleLinks
    Link(s) to the Onboarding Rule(s) to associate the Onboarding Resource with
 
    .PARAMETER JSON
    A JSON string with the body payload
 
    .INPUTS
    System.String
 
    .OUTPUTS
    System.Management.Automation.PSObject
 
    .EXAMPLE
    $OnboardingResourceArguments = @{
 
        Name = 'TestOnboardingResource'
        VMId = 'ee7eeed1-b4e4-4143-a437-d3c0622bf9df'
        DeploymentLink = '/relocation/onboarding/deployment/5bc7eb75-r2d2-4c24-93ac-8c3p0d02f7f1'
        PlanLink = '/relocation/onboarding/plan/ecaak2s0-r5d4-4a79-b17b-27f13c7d3ff7'
        RuleLinks = '/relocation/onboarding/rule/include'
    }
 
    New-vAAOnboardingResource @OnboardingResourceArguments
 
    .EXAMPLE
    $JSON = @"
 
        {
            "deploymentLink": "/relocation/onboarding/deployment/5bc7eb75-r2d2-4c24-93ac-8c3p0d02f7f1",
            "planLink": "/relocation/onboarding/plan/ecaak2s0-r5d4-4a79-b17b-27f13c7d3ff7",
            "resourceLink": "/resources/compute/ee7eeed1-b4e4-4143-a437-d3c0622bf9df",
            "resourceName": "TestOnboardingResource",
            "ruleLinks": [
                "/relocation/onboarding/rule/include"
            ]
        }
"@
 
    $JSON | New-vAAOnboardingResource
#>

[CmdletBinding(SupportsShouldProcess,ConfirmImpact="Low",DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject')]

    Param (

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$Name,

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$VMId,

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$DeploymentLink,

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String]$PlanLink,

        [Parameter(Mandatory=$true,ParameterSetName="Standard")]
        [ValidateNotNullOrEmpty()]
        [String[]]$RuleLinks,

        [Parameter(Mandatory=$true,ValueFromPipeline=$true,ParameterSetName="JSON")]
        [ValidateNotNullOrEmpty()]
        [String]$JSON

    )

    begin {
        function CalculateOutput($ResponseObject) {

            $DocumentSelfLink = $ResponseObject.documentSelfLink
            $OnboardingResourceId = ($DocumentSelfLink -split "/")[-1]

            [PSCustomObject] @{

                Name = $ResponseObject.resourceName
                Id = $OnboardingResourceId
                PlanLink = $ResponseObject.planLink
                ResourceLink = $ResponseObject.resourceLink
                DeploymentLink = $ResponseObject.deploymentLink
                RuleLinks = $ResponseObject.ruleLinks
                CreatedTimeMicros = $ResponseObject.createdTimeMicros
                DocumentSelfLink = $DocumentSelfLink
            }
        }
    }

    process {

        if ($PSBoundParameters.ContainsKey("JSON")) {

            $Data = ($JSON | ConvertFrom-Json)

            $Body = $JSON
            $Name = $Data.resourceName
        }
        else {

            # Format RuleLinks with surrounding quotes and join into single string
            $RuleLinksAddQuotes = $RuleLinks | ForEach-Object {"`"$_`""}
            $RuleLinksFormatForBodyText = $RuleLinksAddQuotes -join ","

            $Body = @"
                {
                    "deploymentLink": "$($DeploymentLink)",
                    "planLink": "$($PlanLink)",
                    "resourceLink": "/resources/compute/$($VMId)",
                    "resourceName": "$($Name)",
                    "ruleLinks": [ $($RuleLinksFormatForBodyText) ]
                }
"@

        }

        # --- Create new Onboarding Resource
        try {
            if ($PSCmdlet.ShouldProcess($Name)){

                $URI = "/relocation/onboarding/resource"
                $OnboardingResource = Invoke-vAARestMethod -Method POST -URI $URI -Body $Body -Verbose:$VerbosePreference

                CalculateOutput $OnboardingResource
            }
        }
        catch [Exception] {

            throw
        }
    }
    end {

    }
}

<#
    - Function: Remove-vAAOnboardingDeployment
#>


function Remove-vAAOnboardingDeployment {
    <#
        .SYNOPSIS
        Remove an Onboarding Deployment
 
        .DESCRIPTION
        Remove an Onboarding Deployment
 
        .PARAMETER Id
        The Id of the Onboarding Deployment
 
        .PARAMETER Name
        The name of the Onboarding Deployment
 
        .INPUTS
        System.String
 
        .EXAMPLE
        Remove-vAAOnboardingDeployment -Name OnboardingDeployment1
 
        .EXAMPLE
        Remove-vAAOnboardingDeployment -Id 'b210b3044578447559e3b3bad52de'
 
        .EXAMPLE
        Get-vAAOnboardingDeployment -Name OnboardingDeployment1 | Remove-vAAOnboardingDeployment
 
    #>

    [CmdletBinding(SupportsShouldProcess,ConfirmImpact="High",DefaultParameterSetName="ById")]

    Param (

    [parameter(Mandatory=$true, ValueFromPipelineByPropertyName, ParameterSetName="ById")]
    [ValidateNotNullOrEmpty()]
    [String[]]$Id,

    [parameter(Mandatory=$true, ParameterSetName="ByName")]
    [ValidateNotNullOrEmpty()]
    [String[]]$Name

    )

    begin {}

    process {

        try {

            switch ($PSCmdlet.ParameterSetName) {

                'ById' {

                    foreach ($OnboardingDeploymentId in $Id) {

                        if ($PSCmdlet.ShouldProcess($OnboardingDeploymentId)){

                            $URI = "/relocation/onboarding/deployment/$($OnboardingDeploymentId)"

                            Invoke-vAARestMethod -Method DELETE -URI "$($URI)" -Verbose:$VerbosePreference | Out-Null
                        }
                    }

                    break
                }

                'ByName' {

                    foreach ($OnboardingDeploymentName in $Name) {

                        if ($PSCmdlet.ShouldProcess($OnboardingDeploymentName)){

                            $OnboardingDeploymentId = (Get-vAAOnboardingDeployment -Name $OnboardingDeploymentName).id
                            $URI = "/relocation/onboarding/deployment/$($OnboardingDeploymentId)"

                            Invoke-vAARestMethod -Method DELETE -URI "$($URI)" -Verbose:$VerbosePreference | Out-Null
                        }
                    }

                    break
                }
            }
        }
        catch [Exception]{

            throw
        }
    }
}

<#
    - Function: Remove-vAAOnboardingPlan
#>


function Remove-vAAOnboardingPlan {
    <#
        .SYNOPSIS
        Remove an Onboarding Plan
 
        .DESCRIPTION
        Remove an Onboarding Plan
 
        .PARAMETER Id
        The id of the Onboarding Plan
 
        .PARAMETER Name
        The name of the Onboarding Plan
 
        .INPUTS
        System.String
 
        .EXAMPLE
        Remove-vAAOnboardingPlan -Name OnboardingPlan1
 
        .EXAMPLE
        Remove-vAAOnboardingPlan -Id 'b210b3044578447559e3b3bad52de'
 
        .EXAMPLE
        Get-vAAOnboardingPlan -Name OnboardingPlan1 | Remove-vAAOnboardingPlan
 
    #>

    [CmdletBinding(SupportsShouldProcess,ConfirmImpact="High",DefaultParameterSetName="ById")]

    Param (

    [parameter(Mandatory=$true, ValueFromPipelineByPropertyName, ParameterSetName="ById")]
    [ValidateNotNullOrEmpty()]
    [String[]]$Id,

    [parameter(Mandatory=$true, ParameterSetName="ByName")]
    [ValidateNotNullOrEmpty()]
    [String[]]$Name

    )

    begin {}

    process {

        try {

            switch ($PSCmdlet.ParameterSetName) {

                'ById' {

                    foreach ($OnboardingPlanId in $Id) {

                        if ($PSCmdlet.ShouldProcess($OnboardingPlanId)){

                            $URI = "/relocation/onboarding/plan/$($OnboardingPlanId)"

                            Invoke-vAARestMethod -Method DELETE -URI "$($URI)" -Verbose:$VerbosePreference | Out-Null
                        }
                    }

                    break
                }

                'ByName' {

                    foreach ($OnboardingPlanName in $Name) {

                        if ($PSCmdlet.ShouldProcess($OnboardingPlanName)){

                            $OnboardingPlanId = (Get-vAAOnboardingPlan -Name $OnboardingPlanName).id
                            $URI = "/relocation/onboarding/plan/$($OnboardingPlanId)"

                            Invoke-vAARestMethod -Method DELETE -URI "$($URI)" -Verbose:$VerbosePreference | Out-Null
                        }
                    }

                    break
                }
            }
        }
        catch [Exception]{

            throw
        }
    }
}

<#
    - Function: Remove-vAAOnboardingResource
#>


function Remove-vAAOnboardingResource {
    <#
        .SYNOPSIS
        Remove a Onboarding Resource
 
        .DESCRIPTION
        Remove a Onboarding Resource
 
        .PARAMETER Id
        The Id of the Onboarding Resource
 
        .PARAMETER Name
        The Name of the Onboarding Resource
 
        .INPUTS
        System.String
 
        .EXAMPLE
        Remove-vAAOnboardingResource -Name OnboardingResource1
 
        .EXAMPLE
        Remove-vAAOnboardingResource -Id '81289f15-89e4-3580-k2s0-86cd3af25257'
 
        .EXAMPLE
        Get-vAAOnboardingResource -Name OnboardingResource1 | Remove-vAAOnboardingResource
 
    #>

    [CmdletBinding(SupportsShouldProcess,ConfirmImpact="High",DefaultParameterSetName="ById")]

    Param (

    [parameter(Mandatory=$true, ValueFromPipelineByPropertyName, ParameterSetName="ById")]
    [ValidateNotNullOrEmpty()]
    [String[]]$Id,

    [parameter(Mandatory=$true, ParameterSetName="ByName")]
    [ValidateNotNullOrEmpty()]
    [String[]]$Name

    )

    begin {}

    process {

        try {

            switch ($PSCmdlet.ParameterSetName) {

                'ById' {

                    foreach ($OnboardingResourceId in $Id) {

                        if ($PSCmdlet.ShouldProcess($OnboardingResourceId)){

                            $URI = "/relocation/onboarding/resource/$($OnboardingResourceId)"

                            Invoke-vAARestMethod -Method DELETE -URI "$($URI)" -Verbose:$VerbosePreference | Out-Null
                        }
                    }

                    break
                }

                'ByName' {

                    foreach ($OnboardingResourceName in $Name) {

                        if ($PSCmdlet.ShouldProcess($OnboardingResourceName)){

                            $OnboardingResourceId = (Get-vAAOnboardingResource -Name $OnboardingResourceName).id
                            $URI = "/relocation/onboarding/resource/$($OnboardingResourceId)"

                            Invoke-vAARestMethod -Method DELETE -URI "$($URI)" -Verbose:$VerbosePreference | Out-Null
                        }
                    }

                    break
                }
            }
        }
        catch [Exception]{

            throw
        }
    }
}


Export-ModuleMember -Alias New-vAABlockDevice,Update-vAAProject