PowervLCM.psm1
<# ____ _ ____ __ __ | _ \ _____ _____ _ ____ _| | / ___| \/ | | |_) / _ \ \ /\ / / _ \ '__\ \ / / | | | | |\/| | | __/ (_) \ V V / __/ | \ V /| |__| |___| | | | |_| \___/ \_/\_/ \___|_| \_/ |_____\____|_| |_| #> # --- Clean up vRAConnection variable on module remove $ExecutionContext.SessionState.Module.OnRemove = { Remove-Variable -Name vLCMConnection -Force -ErrorAction SilentlyContinue } <# - Function: Connect-vLCMServer #> function Connect-vLCMServer { <# .SYNOPSIS Connect to a vLCM Server .DESCRIPTION Connect to a vLCM Server and generate a connection object with Servername, Token etc .PARAMETER Server vLCM Server to connect to .PARAMETER Username Username to connect with .PARAMETER Password Password to connect with .PARAMETER Credential Credential object to connect with .PARAMETER IgnoreCertRequirements Ignore requirements to use fully signed certificates .PARAMETER SslProtocol Alternative Ssl protocol to use from the default Windows PowerShell: Ssl3, Tls, Tls11, Tls12 PowerShell Core: Tls, Tls11, Tls12 .INPUTS System.String System.SecureString Management.Automation.PSCredential Switch .OUTPUTS System.Management.Automation.PSObject .EXAMPLE Connect-vLCMServer -Server vlcmappliance01.domain.local -Credential (Get-Credential) #> [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 = $false)] [Switch]$IgnoreCertRequirements, [parameter(Mandatory = $false)] [ValidateSet('Ssl3', 'Tls', 'Tls11', 'Tls12')] [String]$SslProtocol ) # --- Handle untrusted certificates if necessary $SignedCertificates = $true if ($PSBoundParameters.ContainsKey("IgnoreCertRequirements") ) { 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 } # --- 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 } try { # --- Create Invoke-RestMethod Parameters $JSON = @{ username = $Username password = $JSONPassword } | ConvertTo-Json $Params = @{ Method = "POST" URI = "https://$($Server)/lcm/api/v1/login" Headers = @{ "Accept" = "application/json"; "Content-Type" = "application/json"; } Body = $JSON } if ((!$SignedCertificate) -and ($IsCoreCLR)) { $Params.Add("SkipCertificateCheck", $true) } if (($SslProtocolResult -ne 'Default') -and ($IsCoreCLR)) { $Params.Add("SslProtocol", $SslProtocol) } $Response = Invoke-RestMethod @Params # --- Create Output Object $Global:vLCMConnection = [PSCustomObject] @{ Server = "https://$($Server)" Token = $Response.token Username = $Username SignedCertificates = $SignedCertificates SslProtocol = $SslProtocolResult } } catch [Exception] { throw } Write-Output $vLCMConnection } <# - Function: Disconnect-vLCMServer #> function Disconnect-vLCMServer { <# .SYNOPSIS Disconnect from a vLCM server .DESCRIPTION Disconnect from a vLCM server by removing the authorization token and the global vLCMConnection variable from PowerShell .EXAMPLE Disconnect-vLCMServer .EXAMPLE Disconnect-vLCMServer -Confirm:$false #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = "Low")] Param () # --- Test for existing connection to vLCM if (-not $Global:vLCMConnection) { throw "vLCM Connection variable does not exist. Please run Connect-vLCMServer first to create it" } if ($PSCmdlet.ShouldProcess($Global:vLCMConnection.Server)) { try { # --- Remove the token from vLCM and remove the global PowerShell variable $URI = "/lcm/api/v1/logout" Invoke-vLCMRestMethod -Method POST -URI $URI -Verbose:$VerbosePreference # --- Remove custom Security Protocol if it has been specified if ($Global:vLCMConnection.SslProtocol -ne 'Default') { if (!$IsCoreCLR) { [System.Net.ServicePointManager]::SecurityProtocol -= [System.Net.SecurityProtocolType]::$($Global:vLCMConnection.SslProtocol) } } } catch [Exception] { throw } finally { Write-Verbose -Message "Removing vLCMConnection global variable" Remove-Variable -Name vLCMConnection -Scope Global -Force -ErrorAction SilentlyContinue } } } <# - Function: Invoke-vLCMRestMethod #> function Invoke-vLCMRestMethod { <# .SYNOPSIS Wrapper for Invoke-RestMethod/Invoke-WebRequest with vLCM specifics .DESCRIPTION Wrapper for Invoke-RestMethod/Invoke-WebRequest with vLCM specifics .PARAMETER Method REST Method: Supported Methods: GET, POST, PUT,DELETE .PARAMETER URI API URI, e.g. /lcm/api/v1/view/datacenter .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-vLCMRestMethod -Method GET -URI '/lcm/api/v1/view/datacenter' - .EXAMPLE $JSON = @" { "datacenterName": "CHICAGO_DATA_CENTER", "city": "Chicago", "country": "US", "latitude": "41.8781", "longitude": "87.6298", "state": "Illinois" } "@ Invoke-vLCMRestMethod -Method PUT -URI '/lcm/api/v1/view/datacenter' -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", "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 vLCM if (-not $Global:vLCMConnection) { throw "vLCM Connection variable does not exist. Please run Connect-vLCMServer first to create it" } # --- Create Invoke-RestMethod Parameters $FullURI = "$($Global:vLCMConnection.Server)$($URI)" # --- Add default headers if not passed if (!$PSBoundParameters.ContainsKey("Headers")) { $Headers = @{ "Accept" = "application/json"; "Content-Type" = "application/json"; "x-xenon-auth-token" = "$($Global:vLCMConnection.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 (!($Global:vLCMConnection.SignedCertificates) -and ($IsCoreCLR)) { $Params.Add("SkipCertificateCheck", $true); } # --- Support for PowerShell Core SSL protocol checking if (($Global:vLCMConnection.SslProtocol -ne 'Default') -and ($IsCoreCLR)) { $Params.Add("SslProtocol", $Global:vLCMConnection.SslProtocol); } try { # --- Use either Invoke-WebRequest or Invoke-RestMethod if ($PSBoundParameters.ContainsKey("WebRequest")) { Invoke-WebRequest @Params } else { Invoke-RestMethod @Params } } 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-vLCMDatacenter #> function Get-vLCMDatacenter { <# .SYNOPSIS Get dacenter(s) from vRealize Lifecycle Manager .DESCRIPTION Get all datacenters or a single datacenter by ID. .PARAMETER Id The id of the Datacenter .INPUTS System.String .OUTPUTS System.Management.Automation.PSObject .EXAMPLE Get-vLCMDatacenter -Id 6da4b2a20c6b127557662cd1c8ff8 .EXAMPLE Get-vLCMDatacenter #> [CmdletBinding(DefaultParameterSetName = "Standard")][OutputType('System.Management.Automation.PSObject', 'System.Object[]')] Param ( [parameter(Mandatory = $true, ParameterSetName = "ById")] [ValidateNotNullOrEmpty()] [String[]]$Id ) try { switch ($PsCmdlet.ParameterSetName) { 'ById' { foreach ($DatacenterId in $Id) { $URI = "/lcm/api/v1/view/datacenter?datacenterId=$($DatacenterId)" Write-Verbose -Message "Preparing GET to $($URI)" $Response = Invoke-vLCMRestMethod -Method GET -URI "$($URI)" Write-Verbose -Message "SUCCESS" if ($Response.Count -eq 0) { throw "Could not find Datacenter $($DatacenterId)" } [pscustomobject] @{ DatacenterName = $Response.DatacenterName ID = $DatacenterId City = $Response.city Latitude = $Response.latitude Longitude = $Response.longitude } } break } 'Standard' { #URL for getting all datacenter list $allURI = "/lcm/api/v1/view/datacenter" # --- Make the first request to get all datacenter IDs $Response = Invoke-vLCMRestMethod -Method GET -URI $allURI Write-Verbose -Message "Response contains $($Response.Count) datacenter records" # --- Initialise an empty array $ResponseObject = @() #Loop over each datacenter in the list and get detailed view to create new object foreach ($Datacenter in $Response) { #Get the detailed view of each datacenter $detailURI = "/lcm/api/v1/view/datacenter?datacenterId=$($Datacenter.id)" Write-Verbose -Message "Getting datacenter details for $Datacenter.name via $($detailURI)" $DetailResponse = Invoke-vLCMRestMethod -Method GET -URI $detailURI $Object = [pscustomobject] @{ DatacenterName = $DetailResponse.DatacenterName ID = $Datacenter.id #ID only exists on list view, so it must be retrieved from $datacenter instead of $detailresponse City = $DetailResponse.city Latitude = $DetailResponse.latitude Longitude = $DetailResponse.longitude } $ResponseObject += $Object } # --- Return Datacenters $ResponseObject break } } } catch [Exception] { throw } } <# - Function: Add-vLCMContentCapture #> function Add-vLCMContentCapture { <# .SYNOPSIS Get content item from vRealize Lifecycle Manager content management service .DESCRIPTION Get all content or a single content by ID. .PARAMETER ContentName The content item name .PARAMETER ContentType The type of content that is being captured .PARAMETER CaptureEndpoint Content endpoint to capture the updated content item from .PARAMETER Tags Comma seperated list of tags to add to the content .PARAMETER IncludeDependencies Include dependencies of of content - Boolean .PARAMETER Releaseable Whether to mark the content as production ready or not - Boolean .PARAMETER Comments Comments for content capture .INPUTS System.String System.Management.Automation.PSObject .OUTPUTS System.String .EXAMPLE Get-vLCMContentItem -Id fb9c1c95-04ac-47db-a3fe-e55ad2833f74 | Add-vLCMContentCapture -CaptureEndpoint vra01.domain.local-Tenant -Tags "IaaS, CentOS" -IncludeDependencies: $false -Releaseable: $true -Comments "Comments here" .EXAMPLE Add-vLCMContentCapture -ContentItem $contentItem -CaptureEndpoint vra01.domain.local-Tenant -Tags "IaaS","CentOS" -IncludeDependencies: $false -Releaseable: $true -Comments "Comments here" #> [CmdletBinding(SupportsShouldProcess,ConfirmImpact="Low")][OutputType('System.Management.Automation.PSObject')] Param ( [Parameter(Mandatory=$true,ValueFromPipeline=$true)] [Alias("Name")] [ValidateNotNullOrEmpty()] [String]$ContentName, [Parameter(Mandatory=$true,ValueFromPipeline=$true)] [Alias("PackageType")] [ValidateNotNullOrEmpty()] [String]$ContentType, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [String]$CaptureEndpoint, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [String]$Tags, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [Boolean]$IncludeDependencies, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [Boolean]$Releaseable, [Parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()] [String]$Comments ) begin{ #Initialize Write-Verbose -Message "Initializing..." } process{ try { $TagsAsJson = $($Tags) | ConvertTo-Json $Template = @" { "comments": "$($Comments)", "uniqueId": null, "releasable": "$($Releaseable)", "capture": true, "test": null, "release": null, "enableUnitTests": null, "includeDependencies": "$($IncludeDependencies)", "stopTestDeploymentOnFirstFailure": null, "stopReleaseDeploymentOnFirstFailure": null, "stopDeploymentOnFirstFailure": null, "stopUnitTestsOnFirstFailure": null, "deployTestContent": null, "unitTestConfig": null, "contentName": "$($ContentName)", "contentEndpointName": "$($ContentEndpointName)", "testContentEndpoints": [], "packageType": [], "releaseContentEndpoints": [], "contentType": "$($ContentType)", "unitTestContentEndpointLink": null, "deployContent": null, "packageVersionLink": null, "releaseComments": null, "formValid": true, "deployIncludeDependencies": null, "testIncludeDependencies": null, "releaseLatest": null, "latestContent": null, "vROPackageName": null, "vROSharedPackageVersionLink": null, "tags": $($TagsAsJson), "captureByFolder": false, "packageVersionLinks": [], "deployFiles": [], "deployAllFiles": true } "@ if ($PSCmdlet.ShouldProcess($endpoint)) { #URL for getting all Content Pipeline Service Commands $contentUrl = "/cms/api/v1/pipelines/capture" # change expands to parameter after testing # --- Make the first request to get all Content IDs $Response = Invoke-vLCMRestMethod -Method POST -URI $contentUrl -Body $Template Write-Verbose -Message "Response contains $($Response.Count) content records" # --- Return Contents return $Reponse break } } catch [Exception]{ throw } } end{ } } <# - Function: Get-vLCMContentEndpoint #> function Get-vLCMContentEndpoint { <# .SYNOPSIS Get content endpoints from vRealize Lifecycle Manager content management service .DESCRIPTION Get all content endpoints or a single content by ID. .PARAMETER Category The content endpoint category type to filter .PARAMETER Limit Limit the number of objects returned. Default = 100 .INPUTS System.String .OUTPUTS System.Management.Automation.PSObject .EXAMPLE Get-vLCMContentEndpoint -Category SourceControl .EXAMPLE Get-vLCMContentEndpoint | ft #> [OutputType('System.Management.Automation.PSObject')] Param ( [Parameter(Mandatory = $false, ValueFromPipeline = $false)] [ValidateSet("Orchestration", "Automation", "SourceControl", "Operations")] [String]$Category, [parameter(Mandatory = $false, ValueFromPipeline = $false)] [ValidateNotNullOrEmpty()] [String]$Limit = "100" ) begin { #Initialize Write-Verbose -Message "Initializing..." #Create PSObject for Output function StandardOutput ($contentItem) { [pscustomobject]@{ Name = $contentItem.name Category = $contentItem.category Capture = $contentItem.supportCapture Test = $contentItem.supportTest Release = $contentItem.supportRelease Id = ($contentItem.id).split('/')[5] URL = $contentItem.id Tags = $contentItem.tags Messages = $contentItem.messages } } } process { try { if ($PSBoundParameters.ContainsKey('Category')) { #URL for getting all Content Endpoints list by category $contentUrl = "/cms/api/v1/endpoints?expands&limit=$($Limit)&category=$($Category)" } else { #URL for getting all Content Endpoints list $contentUrl = "/cms/api/v1/endpoints?expands&limit=$($Limit)" } # --- Invoke the request to get the content endpoints $Response = Invoke-vLCMRestMethod -Method GET -URI $contentUrl Write-Verbose -Message "Response contains $($Response.count) content endpoint records" # --- Initialise an empty array $ResponseObject = @() #Loop over each Content Endpoint in the list and get detailed view to create new object foreach ($item in $Response.sortedDocuments) { $ResponseObject += StandardOutput($item) } # --- Return Contents return $ResponseObject break } catch [Exception] { throw } } end { } } <# - Function: Remove-vLCMContentEndpoint #> function Remove-vLCMContentEndpoint { <# .SYNOPSIS Remove a content endpoint from vRealize Lifecycle Manager content management service .DESCRIPTION Remove a content endpoint from vRealize Lifecycle Manager content management service .PARAMETER EndpointId The content endpoint to remove .INPUTS System.String .OUTPUTS System.Management.Automation.PSObject .EXAMPLE Remove-vLCMContentEndpoint -EndpointId a50d0992-bf12-424e-8a4c-a502dba422bb #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = "High")] Param ( [parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Alias("id")] [ValidateNotNullOrEmpty()] [String[]]$EndpointId ) begin { #Initialize Write-Verbose -Message "Initializing..." } process { #Process Write-Verbose -Message "Processing..." try { foreach ($endpoint in $EndpointId) { if ($PSCmdlet.ShouldProcess($endpoint)) { $URI = "/cms/api/v1/endpoints/$($endpoint)" #Invoke REST request #This method will return an async request for the deletion operation. #In a future version it would be better to capture that and track the status until it is "COMPLETED" Write-Verbose -Message "Removing Content Management Endpoint $($endpoint)" Invoke-vLCMRestMethod -Method DELETE -URI $URI } } } catch [Exception] { throw } } end { #Finalize Write-Verbose -Message "Finalizing..." } } <# - Function: Get-vLCMContentItem #> function Get-vLCMContentItem { <# .SYNOPSIS Get content item from vRealize Lifecycle Manager content management service .DESCRIPTION Get all content or a single content by ID. .PARAMETER Id The id of the Content .PARAMETER PackageType The content type to get .PARAMETER Type The content type to filter .INPUTS System.String .OUTPUTS System.Management.Automation.PSObject .EXAMPLE Get-vLCMContentItem -Id 4e87ae12-75c8-4a8d-83ab-f02d30543a08 .EXAMPLE Get-vLCMContentItem -PackageType Automation-CompositeBlueprint #> [OutputType('System.Management.Automation.PSObject')] Param ( [Parameter(Mandatory=$false)] [ValidateSet("Automation-CompositeBlueprint","Automation-ComponentProfile","Automation-PropertyDefinition","Automation-PropertyGroup","Automation-ResourceAction","Automation-Software","Automation-Subscription","Automation-XaaSBlueprint")] [String]$PackageType ) begin{ #Initialize Write-Verbose -Message "Initializing..." #Create PSObject for Output function StandardOutput ($contentItem){ [pscustomobject]@{ Name = $contentItem.name UniqueID = $contentItem.UniqueID Id = ($contentItem.id).split('/')[5] PackageType = $contentItem.PackageType Releasable = $contentItem.releasable RequestedBy = $contentItem.requestedBy LatestVersion = $contentItem.latestVersion Tags = $contentItem.tags URL = $contentItem.id } } } process{ try { #URL for getting all Content list $contentUrl = "/cms/api/v1/content?expands=true" # change expands to parameter after testing # --- Make the first request to get all Content IDs $Response = Invoke-vLCMRestMethod -Method GET -URI $contentUrl Write-Verbose -Message "Response contains $($Response.Count) content records" # --- Initialise an empty array $ResponseObject = @() #Loop over each Content in the list and get detailed view to create new object foreach ($item in $Response.sortedDocuments) { $ResponseObject += StandardOutput($item) } # --- Return Contents return $ResponseObject break } catch [Exception]{ throw } } end{ } } <# - Function: Remove-vLCMContentItem #> function Remove-vLCMContentItem { <# .SYNOPSIS Remove a content item from vRealize Lifecycle Manager content management service .DESCRIPTION Remove a content item from vRealize Lifecycle Manager content management service .PARAMETER ContentId The content item to remove .INPUTS System.String .OUTPUTS System.Management.Automation.PSObject .EXAMPLE Remove-vLCMContentItem -ContentId a50d0992-bf12-424e-8a4c-a502dba422bb .EXAMPLE Get-vLCMContentItem | Remove-vLCMContentItem #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = "High")] Param ( [parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Alias("id")] [ValidateNotNullOrEmpty()] [String[]]$ContentId ) begin { #Initialize Write-Verbose -Message "Initializing..." } process { #Process Write-Verbose -Message "Processing..." try { foreach ($item in $ContentId) { if ($PSCmdlet.ShouldProcess($item)) { $URI = "/cms/api/v1/content/$($item)" #Invoke REST request #This method will return an async request for the deletion operation. #In a future version it would be better to capture that and track the status until it is "COMPLETED" Write-Verbose -Message "Removing Content Management Item $($item)" Invoke-vLCMRestMethod -Method DELETE -URI $URI } } } catch [Exception] { throw } } end { #Finalize Write-Verbose -Message "Finalizing..." } } <# - Function: Get-vLCMEnvironment #> function Get-vLCMEnvironment { <# .SYNOPSIS Get environment(s) from vRealize Lifecycle Manager .DESCRIPTION Get all Environments or a single Environment by ID. .PARAMETER Id The id of the Environment .INPUTS System.String .OUTPUTS System.Management.Automation.PSObject .EXAMPLE Get-vLCMEnvironment -Id 6da4b2a20c6b127557662cd1c8ff8 .EXAMPLE Get-vLCMEnvironment #> [CmdletBinding(DefaultParameterSetName="Standard")][OutputType('System.Management.Automation.PSObject', 'System.Object[]')] Param ( [parameter(Mandatory=$true,ParameterSetName="ById")] [ValidateNotNullOrEmpty()] [String[]]$Id ) try { switch ($PsCmdlet.ParameterSetName) { 'ById' { foreach ($EnvironmentId in $Id) { $URI = "//lcm/api/v1/view/environment?environmentId=$($EnvironmentId)" Write-Verbose -Message "Preparing GET to $($URI)" $Response = Invoke-vLCMRestMethod -Method GET -URI "$($URI)" Write-Verbose -Message "SUCCESS" if ($Response.Count -eq 0) { throw "Could not find Environment $($EnvironmentId)" } [pscustomobject] @{ EnvironmentName = $Response.name ID = $EnvironmentId Products = $Response.Products Properties = $Response.Properties } } break } 'Standard' { #URL for getting all Environment list $allURI = "/lcm/api/v1/view/environment" # --- Make the first request to get all Environment IDs $Response = Invoke-vLCMRestMethod -Method GET -URI $allURI Write-Verbose -Message "Response contains $($Response.Count) Environment records" # --- Initialise an empty array $ResponseObject = @() #Loop over each Environment in the list and get detailed view to create new object foreach ($Environment in $Response) { #Get the detailed view of each Environment $detailURI = "/lcm/api/v1/view/environment?environmentId=$($Environment.id)" Write-Verbose -Message "Getting Environment details for $Environment.name via $($detailURI)" $DetailResponse = Invoke-vLCMRestMethod -Method GET -URI $detailURI $Object = [pscustomobject] @{ EnvironmentName = $DetailResponse.name ID = $Environment.id #ID only exists on list view, so it must be retrieved from $Environment instead of $detailresponse Products = $DetailResponse.products Properties = $DetailResponse.properties } $ResponseObject += $Object } # --- Return Environments $ResponseObject break } } } catch [Exception]{ throw } } <# - 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 } } |