BuildMasterAutomation.psm1
enum BMRaftItemTypeCode { Module = 3 Script = 4 DeploymentPlan = 6 Pipeline = 8 } Add-Type -AssemblyName 'System.Web' $script:warnings = @{} function Write-WarningOnce { [CmdletBinding()] param( [Parameter(Mandatory, Position=0, ParameterSetName='Message', ValueFromPipeline)] [String] $Message ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState if( $script:warnings[$Message] ) { return } Write-Warning -Message $Message $script:warnings[$Message] = $true } } $functionsDir = Join-Path -Path $PSScriptRoot -ChildPath 'Functions' if( (Test-Path -Path $functionsDir -PathType Container) ) { foreach( $item in (Get-ChildItem -Path $functionsDir -Filter '*.ps1') ) { . $item.FullName } } function Add-BMObjectParameter { <# .SYNOPSIS Adds id or name values to a parameter hashtable (i.e. a hashtable used as the body of a request to a BuildMaster API endpoint). .DESCRIPTION Many of BuildMaster's APIs take an ID or a name. For example, many of the Release and Build Deployment methods accept either an `applicationId` parameter *or* an `applicationName` parameter. This function exists to allow BuildMasterAutomation functions to accept an object, an object's id or an object's name as a parameter. Pipe the hashtable that will be used as the body of a request to the BuildMaster APIs to `Add-BMObjectParameter`. Pass the name of the object type to the `Name` parameter and the object/id/name/value to the `Value` parameter. If the value passed is `$null`, nothing happens. If the value passed is a byte or an integer, the function adds a `$($Name)Id` parameter to the hashtable. If the value passed is a string, the function adds a `$($Name)Name` parameter. Otherwise, `Add-BMObjectParameter` the first property on the property named `id`, `$($Name)Id`, `name`, or `$($Name)Name` is added as `$($Name)Id` or `$($Name)Name` respectively. If the parameter must be a name parameter, use the `AsName` switch. If the parameter must be an id parameter, use the `AsID` switch. If the hashtable will be used as the body to a native API endpoint, use the `-ForNativeApi` switch. The native API uses `$($Name)_Id` and `$($Name)_Name` patterns for its id and name parameters. If you want to return the original hasthable so you can add more than one parameter to the hashtable, use the `-PassThru` switch. .EXAMPLE $parameters | Add-BMObjectParameter -Name 'release' -Value $release Demonstrates how to add the id property from an object to a hashtable used as the body to a BuildMaster API endpoint. In this case, `$release` is a release object returned by the BuildMaster APi, so has a `releaseId` property. `Add-BMObjectParameter` will add a `releaseId` key to the hashtable with a value of `$release.releaseId`. .EXAMPLE $parameters | Add-BMObjectParameter -Name 'release' -Value $releaseId Demonstrates how to add an id to a hashtable used as the body to a BuildMaster API. In this case, `$releaseId` is the id of a release. `Add-BMObjectParameter` will add a `releaseId` key to the hashtable with a value of `$releaseId`. .EXAMPLE $parameters | Add-BMObjectParameter -Name 'release' -Value $releaseName Demonstrates how to add a name to a hashtable used as the body to a BuildMaster API. In this case, `$releaseName` is the name of a release. `Add-BMObjectParameter` will add a `releaseName` key to the hashtable with a value of `$releaseName`. .EXAMPLE $parameters | Add-BMObjectParameter -Name 'pipeline' -Value $pipeline -AsName Demonstrates how to force `Add-BMObjectParameter` to ignore any id properties and only use name properties, if they exist, by using the `AsName` switch. .EXAMPLE $parameters | Add-BMObjectParameter -Name 'application' -Value $app -ForNativeApi Demonstrates how to add an id parameter to a parameter hashtable used as the body of a request to the BuildMaster *Native* API. In this case, `$app` is an application object returned by the BuildMaster API. `Add-BMObjectParameter` will add an `application_Id` key to the hasthable with a value of `$app.application_Id`. .EXAMPLE $parameter | Add-BMObjectParameter -Name 'application' -Value $app -PassThru | Add-BMObjectParameter -Name 'pipeline' -Value $pipeline Demonstrates how you can use the `PassThru` switch to add multiple parameters to a parameters hashtable using a pipeline. #> [CmdletBinding(DefaultParameterSetName='IdOrName')] param( # The hashtable to add the parameter to. [Parameter(Mandatory, ValueFromPipeline)] [hashtable] $Parameter, # The name of the parameter, *without* the `Id` or `Name` suffix. The suffix is added automatically based on the # type of the parameter value. [Parameter(Mandatory)] [String] $Name, # The object, id, or name. [Parameter(Mandatory)] [AllowEmptyString()] [AllowNull()] [Object] $Value, # If true, will return the hashtable. [switch] $PassThru, # The parameters are being used in the native API, which has a different naming convention. If true, parameter # names will use an underscore in the parameter name added to the hashtable, e.g. `_Id` or `_Name`. [switch] $ForNativeApi, # If set, id properties on the incoming object will be ignored. [Parameter(Mandatory, ParameterSetName='AsName')] [switch] $AsName, # If set, name properties on the incoming object will be ignored. [Parameter(Mandatory, ParameterSetName='AsID')] [switch] $AsID ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState try { if ($null -eq $Value) { return } $nameParamNameSuffix = 'Name' $idParamNameSuffix = 'Id' if ($ForNativeApi) { $nameParamNameSuffix = "_$($nameParamNameSuffix)" $idParamNameSuffix = "_$($idParamNameSuffix)" } $nameParamName = "$($Name)$($nameParamNameSuffix)" $idParamName = "$($Name)$($idParamNameSuffix)" if ($AsName) { $name = $Value | Get-BMObjectName -ObjectTypeName $Name if (-not $name) { return } $Parameter[$nameParamName] = $name return } if ($AsId) { $id = $Value | Get-BMObjectID -ObjectTypeName $Name if (-not $id) { return } $Parameter[$idParamName] = $id return } $id = $Value | Get-BMObjectId -ObjectTypeName $Name -ErrorAction Ignore if ($id) { $Parameter[$idParamName] = $id return } $name = $Value | Get-BMObjectName -ObjectTypeName $Name -ErrorAction Ignore if ($name) { $Parameter[$nameParamName] = $name return } $msg = "Object ""$($Value)"" isn't an id or name, nor does it have any $($Name)Id, $($Name)_Id, " + "$($Name)Name, or $($Name)_Name properties." Write-Error -Message $msg -ErrorAction $ErrorActionPreference } finally { if ($PassThru) { $Parameter | Write-Output } } } } function Add-BMParameter { <# .SYNOPSIS Adds values to a parameter hashtable (i.e. a hashtable used as the body of a request to a BuildMaster API endpoint). .DESCRIPTION The `Add-BMParameter` function adds values to a parameter hashtable. Pipe the hashtable to the function (or pass it to the `Parameter` parameter). Pass the parameter name to the `Name` parameter and the value to the `Value` parameter. If the value is not null, it will be added to the hashtable. This function lets you simplify adding optional parameters to a parameter hashtable. Instead of: if ($null -ne $Value) { $parameters[$Name] = $Value } this function lets you write: $parameters | Add-BMParameter -Name $Name -Value $Value It also lets you chain multiple parameters together by using the `-PassThru` switch: $parameters | Add-BMParameter -Name $Name1 -Value $Value1 -PassThru | Add-BMParameter -Name $Name2 -Value $Value2 -PassThru | Add-BMParameter -Name $Name3 -Value $Value3 .EXAMPLE $parameters | Add-BMParameter -Name $Name -Value $Value Demonstrates how to add an optional parameter to the parameter hashtable `$parameters`. In this case, if `$Value` is not null, `Add-BMParameter` adds `$Value` into `$parameters` using key `$Name`, e.g. `$parameters[$Name] = $Value`. .EXAMPLE $parameters | Add-BMParameter -Name $Name -Value $Value -PassThru | Add-BMParameter -Name $Name2 -Value $Value2 Demonstrates how you can add multiple parameters to a parameter hashtable by using the `-PassThru` switch, which returns the parameter hashtable, which be piped to `Add-BMParameter`. #> [CmdletBinding()] param( # The hashtable to add the parameter to. [Parameter(Mandatory, ValueFromPipeline)] [hashtable] $Parameter, # The name of the parameter. [Parameter(Mandatory)] [String] $Name, # The value of the parameter. If the value is not null, it is added to the `$Parameter` hashtable using the # name argument as the key. [Parameter(Mandatory)] [AllowEmptyString()] [AllowNull()] [Object] $Value, # If set, returns the hashtable piped (or passed to parameter `$Parameter). This lets you create a pipeline of # calls to `Add-BMParameter`. [switch] $PassThru ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState if ($null -ne $Value) { if ($Value -is [hashtable]) { $Parameter[$Name] = $Value[$Name] } elseif ($Value -is [Enum]) { $enumType = [Enum]::GetUnderlyingType($Value.GetType()) $Parameter[$Name] = [Convert]::ChangeType($Value, $enumType) } else { $Parameter[$Name] = $Value } } if ($PassThru) { return $Parameter } } } function Add-BMPipelineMember { <# .SYNOPSIS Adds `Pipeline_Name` and `Pipeline_Id` properties to an object. .DESCRIPTION In BuildMaster 6.2, pipeline objects are now rafts and now have `RaftItem_Name` and `RaftItem_Id` properties instead of `Pipeline_Name` and `Pipeline_Id` objects. This function adds `Pipeline_Name` and `Pipeline_Id` *alias* properties to an object that alias the `RaftItem_Name` and `RaftItem_Id` properties, respectively. You should only pipe raft items that represent pipelines to this function. It does *not* validate the incoming object. #> [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline)] [Object] $Pipeline, [switch] $PassThru ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState if (-not $Pipeline) { return } $Pipeline | Add-Member -Name 'Pipeline_Name' -MemberType AliasProperty -Value 'RaftItem_Name' -PassThru | Add-Member -Name 'Pipeline_Id' -MemberType AliasProperty -Value 'RaftItem_Id' -PassThru:$PassThru } } function Add-PSTypeName { <# .SYNOPSIS Adds a BuildMaster type name to an object. .DESCRIPTION The `Add-PSTypeName` function adds BuildMaster type names to an object. These types don't actually exist. The type names are used by PowerShell to decide what formats to use when displaying an object. If the `Server` switch is set, it adds a `Inedo.BuildMaster.Server` type name. If the `RaftItem` switch is set, it adds a `Inedo.BuildMaster.RaftItem` type name. #> [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline)] [Object] $InputObject, [Parameter(Mandatory, ParameterSetName='Server')] [switch] $Server, [Parameter(Mandatory, ParameterSetName='RaftItem')] [switch] $RaftItem ) process { Set-StrictMode -Version 'Latest' $typeName = 'Inedo.BuildMaster.{0}' -f $PSCmdlet.ParameterSetName $InputObject.pstypenames.Add( $typeName ) $InputObject | Write-Output } } function ConvertFrom-BMNativeApiByteValue { <# .SYNOPSIS Converts a binary value returned from the BuildMaster native API as a `byte[]` object to a string. .DESCRIPTION Some of the objects returned by the BuildMaster native API have properties that are typed as byte arrays, i.e. `byte[]`.This function converts these values into strings. Pipe the value to the function (or pass it to the `InputObject` parameter). .EXAMPLE ConvertFrom-BMNativeApiByteValue 'ZW1wdHk=' Demonstrates how to convert a `byte[]` value returned by a BuildMaster native API into its original string/text. .EXAMPLE 'ZW1wdHk=' | ConvertFrom-BMNativeApiByteValue Demonstrates that you can pipe values to `ConvertFrom-BMNativeApiByteValue`. #> [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline, Position=0)] [String] $InputObject ) begin { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState } process { $bytes = [Convert]::FromBase64String($InputObject) [Text.Encoding]::UTF8.GetString($bytes) | Write-Output } end { } } function ConvertFrom-BMOtterScriptExpression { <# .SYNOPSIS Converts an Otterscript expression into a PowerShell object. .DESCRIPTION The `ConvertFrom-BMOtterScriptExpression` function takes an OtterScript expression as an input and converts it into a PowerShell representation of the object. This function supports converting both `vector` and `map` types into their respective `array` and `hashtable` types in PowerShell. .LINK https://docs.inedo.com/docs/executionengine-otterscript-strings-and-literals .EXAMPLE "@(1, 2, 3, 4)" | ConvertFrom-BMOtterScriptExpression Demonstrates converting an OtterScript vector into a PowerShell array. .EXAMPLE "%(hello: world)" | ConvertFrom-BMOtterScriptExpression Demonstrates converting an OtterScript map into a PowerShell hashtable. .EXAMPLE "%(hello: %(hi: world))" | ConvertFrom-BMOtterScriptExpression Demonstrates converting nested OtterScript maps into nested PowerShell hashtables. .EXAMPLE "@(1, 2, @(3, 4))" | ConvertFrom-BMOtterScriptExpression Demonstrates converting nested OtterScript vectors into nested PowerShell arrays. .EXAMPLE "@(1, 2, %(hello: world, hi there: @(5, 6, 7)))" | ConvertFrom-BMOtterScriptExpression Demonstrates converting nested OtterScript vectors and maps into nested PowerShell arrays and hashtables. #> [CmdletBinding()] param( # The OtterScript expression to convert to a PowerShell object. [Parameter(Mandatory, ValueFromPipeline)] [AllowEmptyString()] [String] $Value ) begin { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState function Edit-Output { param( [Parameter(Mandatory, ValueFromPipeline)] $InputObject ) $InputObject = $InputObject.Trim() $maybeInt = 0 if (([Int64]::TryParse($InputObject, [ref] $maybeInt))) { return $maybeInt } return $InputObject } } process { $originalValue = $Value $Value = $Value.Trim() $isMap = $Value.StartsWith('%(') -and $Value.EndsWith(')') $isVector = $Value.StartsWith('@(') -and $Value.EndsWith(')') $isScalar = -not $isMap -and -not $isVector if ($isScalar) { if ($Value.StartsWith('@(') -or $Value.StartsWith('%(')) { $msg = "Unable to convert '${originalValue}' to a PowerShell Object because of invalid syntax. " + 'Returning original value.' Write-Warning -Message $msg } return $Value | Edit-Output } $Value = $Value -replace '\)$' if ($isMap) { $Value = $Value -replace '^%\(' if (-not $Value) { return @{} } } else { $Value = $Value -replace '^@\(' if (-not $Value) { return ,@() } } $closesNeeded = 0 # Splitting up array or map by comma and collecting into array. $parsedItems = &{ $start = 0 $end = 0 foreach ($i in 0..($Value.Length - 1)) { $char = $Value[$i] if ($char -eq '(' -and ($Value[$i - 1] -eq '@' -or $Value[$i - 1] -eq '%')) { $closesNeeded++ continue } if ($char -eq ')' -and $closesNeeded) { $closesNeeded-- if ($i -ne ($Value.Length - 1)) { continue } } if ($closesNeeded -or ($char -ne ',' -and $i -ne ($Value.Length - 1))) { continue } $end = $i $lengthOfSubstring = $end - $start if ($i -eq ($Value.Length - 1)) { $lengthOfSubstring++ } $Value.Substring($start, $lengthOfSubstring).Trim() | Write-Output $start = $i + 1 } } $invalidSyntax = $closesNeeded -gt 0 if ($isMap) { foreach ($mapItem in $parsedItems) { if ($mapItem -notmatch '^[\w\d\s\-]+:') { $invalidSyntax = $true break } } } if ($invalidSyntax) { $msg = "Unable to convert '${originalValue}' to a PowerShell Object because of invalid syntax. " + 'Returning original value.' Write-Warning -Message $msg return $originalValue | Edit-Output } if ($isVector) { return ,@($parsedItems | ConvertFrom-BMOtterScriptExpression) } $hashtable = @{} foreach ($kvpair in $parsedItems) { $colonIndex = $kvpair.IndexOf(':') $mapKey = $kvpair.Substring(0, $colonIndex) | Edit-Output $mapValue = $kvpair.Substring($colonIndex + 1) | ConvertFrom-BMOtterScriptExpression $hashtable[$mapKey] = $mapValue } return $hashtable } } function ConvertTo-BMNativeApiByteValue { <# .SYNOPSIS Converts a string into a value that can be passed to a `byte[]` parameter in the BuildMaster native API. .DESCRIPTION Some of the parameters of the BuildMaster native API are typed as `byte[]` object. This function converts strings into a value that can be passed as one of these parameters. Pipe the string you want to convert (or pass it to the `InputObject` parameter). The function will return a value that you can pass to the BuildMaster API. If you pipe multiple strings to `ConvertTo-BMNativeApiByteValue`, the strings will be concatenated together before conversion. .EXAMPLE ConvertTo-BMNativeApiByteValue 'hello example' Demonstrates how to convert a string into value that can be passed to a `byte[]`-typed parameter on the BuildMaster native API. .EXAMPLE 'hello','example' | ConvertTo-BMNativeApiByteValue Demonstrates that you can pipe strings to `ConvertTo-BMNativeApiByteValue`. All the strings piped in will be concatenated together before conversion. #> [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline, Position=0)] [String] $InputObject ) begin { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $allStrings = [Text.StringBuilder]::New() } process { [void] $allStrings.Append($InputObject) } end { $stringBytes = [Text.Encoding]::UTF8.GetBytes($allStrings.ToString()) [Convert]::ToBase64String($stringBytes) | Write-Output } } function ConvertTo-BMOtterScriptExpression { <# .SYNOPSIS Converts a PowerShell object into an OtterScript expression. .DESCRIPTION The `ConvertTo-BMOtterScriptExpression` function takes a PowerShell object as an input and returns a representation of the object in OtterScript. This function converts .NET IEnumerable and IDictionary objects to OtterScript vector and map types respectively. .LINK https://docs.inedo.com/docs/executionengine-otterscript-strings-and-literals .EXAMPLE ,@(1, 2, 3, 4) | ConvertTo-BMOtterScriptExpression Demonstrates turning an IEnumerable of PowerShell integers into an array of OtterScript integers. Output will be `@(1, 2, 3, 4)` .EXAMPLE @{ 'hello' = 'world'; 'goodbye' = 'world' } | ConvertTo-BMOtterScriptExpression Demonstrates turning a PowerShell IDictionary into an OtterScript map. Output will be `%(hello: world, goodbye: world)` #> [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline)] [Object] $Value ) begin { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState } process { $isDict = $Value -is [System.Collections.IDictionary] $isList = $Value -is [System.Collections.IEnumerable] -and $Value -is [System.Collections.ICollection] if ($Value -is [String] -or $Value -is [Int]) { return $Value.ToString() } if (-not $isDict -and -not $isList) { $valueType = ($Value | Get-Member).TypeName | Select-Object -Unique $msg = "Unable to convert '${valueType}' to OtterScript expression. All values must either inherit " + 'the IDictionary or the IEnumarable interface or be of type String or Int.' Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } if ($isDict) { $mapExpression = '%(' $sortedKeys = $Value.Keys | Sort-Object foreach ($key in $sortedKeys) { $keyValue = $Value[$key] if ($keyValue -is [System.Collections.ICollection]) { $keyValue = ConvertTo-BMOtterScriptExpression -Value $keyValue } if ($keyValue -eq '') { $keyValue = '""' } $mapExpression += "${key}: $($keyValue), " } $mapExpression = $mapExpression -replace ', $' $mapExpression += ')' return $mapExpression } $result = & { foreach ($item in $Value) { if ($item -is [System.Collections.ICollection]) { $item = ConvertTo-BMOtterScriptExpression -Value $item $item | Write-Output continue } if ($item -eq '') { $item = '""' } $item | Write-Output } } return "@($($result -join ', '))" } } function Disable-BMApplication { <# .SYNOPSIS Disables a BuildMaster application .DESCRIPTION The `Disable-BMApplication` function disables an application in BuildMaster, which removes the application from the BuildMaster UI and reports. Pass the application name, id, or application object to the `Application` parameter. Or, pipe the name, id, or applicatoin object into the function. This function uses the native API, which can change without notice between releases. The API key you use must have access to the native API. .EXAMPLE Disable-BMApplication -Session $session -Application 494 Demonstrates how to delete an application using its ID. .EXAMPLE 'Disable Me!' | Get-BMApplication -Session $session | Disable-BMApplication -Session $session Demonstrates that you can pipe applications into `Disable-BMApplication`. #> [Diagnostics.CodeAnalysis.SuppressMessage('PSShouldProcess', '')] [CmdletBinding(SupportsShouldProcess)] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [Object] $Session, # The application to get. Pass an application name, id, or application object. [Parameter(Mandatory, ValueFromPipeline)] [Alias('ID')] [Object] $Application ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $bmApp = $Application | Get-BMApplication -Session $Session if (-not $bmApp) { return } $deactivateParams = @{} | Add-BMObjectParameter -Name 'Application' -Value $bmApp -AsID -ForNativeApi -PassThru Invoke-BMNativeApiMethod -Session $Session ` -Name 'Applications_DeactivateApplication' ` -Parameter $deactivateParams ` -Method Post } } function Get-BMApplication { <# .SYNOPSIS Gets BuildMaster applications. .DESCRIPTION The `Get-BMApplication` function gets all active applications from an instance of BuildMaster. Use the `Force` switch to include inactive applications. To get a specific application, pass its id, name (wildcards supported), or object to the `Application` parameter. The function writes an error if the application does not exist. .EXAMPLE Get-BMApplication -Session $session Demonstrates how to get all active BuildMaster applications .EXAMPLE Get-BMApplication -Session $session -Force Demonstrates how to get all active *and* inactive/disabled BuildMaster applications. .EXAMPLE Get-BMApplication -Session $session -Name 'MyApplication' Demonstrates how to get a specific application. #> [CmdletBinding(DefaultParameterSetName='AllApplications')] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [Object] $Session, # The application to get. Pass an application id, name (wildcards supported), or object. [Parameter(Mandatory, ValueFromPipeline, ParameterSetName='SpecificApplication')] [Alias('Name')] [Object] $Application, # Force `Get-BMApplication` to return inactive/disabled applications. [Parameter(ParameterSetName='AllApplications')] [switch] $Force ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState # Invoke-BMNativeApiMethod uses POST, but we're reading data, so always make the request. $WhatIfPreference = $false $searching = $Application -and ` ($Application | Test-BMName) -and ` [wildcardpattern]::ContainsWildcardCharacters($Application) $parameters = @{ Application_Count = 0; IncludeInactive_Indicator = ($Force.IsPresent -or $PSCmdlet.ParameterSetName -eq 'SpecificApplication'); } | Add-BMObjectParameter -Name 'Application' -Value $Application -ForNativeApi -PassThru $endpoint = 'Applications_GetApplication' if ($PSCmdlet.ParameterSetName -eq 'AllApplications' -or $searching) { $endpoint = 'Applications_GetApplications' } $apps = @() Invoke-BMNativeApiMethod -Session $Session -Name $endpoint -Parameter $parameters -Method Post | ForEach-Object { if ($_ | Get-Member -Name 'Applications_Extended') { return $_.Applications_Extended } return $_ } | Where-Object { if ($searching) { return $_.Application_Name -like $Application } return $true } | Tee-Object -Variable 'apps' | Write-Output if ($Application -and -not $apps -and -not $searching) { $msg = "Application ""$($Application | Get-BMObjectName -ObjectTypeName 'Application')"" does not exist." Write-Error -Message $msg -ErrorAction $ErrorActionPreference } } } function Get-BMApplicationGroup { <# .SYNOPSIS Gets BuildMaster application groups. .DESCRIPTION The `Get-BMApplicationGroup` function gets all application groups from an instance of BuildMaster. To get a specific application group, pass its id, name (wildcards supported), or an application group object to the `ApplicationGroup` parameter, or pipe them into the function. If the application group isn't found, the function writes an error. .EXAMPLE Get-BMApplicationGroup -Session $session Demonstrates how to get all BuildMaster application groups. .EXAMPLE Get-BMApplicationGroup -Session $session -ApplicationGroup 'My Application Group' Demonstrates how to get a specific application group. #> [CmdletBinding()] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [Object] $Session, # The application group to get. Pass an id, name (wildcards supported), or application group object. [Parameter(ValueFromPipeline)] [Alias('Name')] [Object] $ApplicationGroup ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $WhatIfPreference = $false $appGroups = @() $appGroupName = $ApplicationGroup | Get-BMObjectName -Strict -ErrorAction Ignore Invoke-BMNativeApiMethod -Session $Session -Name 'ApplicationGroups_GetApplicationGroups' -Method Post | Where-Object { if( $appGroupName ) { return $_.ApplicationGroup_Name -like $appGroupName } return $true } | Tee-Object -Variable 'appGroups' | Write-Output $searching = $appGroupName -and [wildcardpattern]::ContainsWildcardCharacters($appGroupName) if ($ApplicationGroup -and -not $appGroups -and -not $searching) { $msg = "Application group ""$($appGroupName)"" does not exist." Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } } } function Get-BMBuild { <# .SYNOPSIS Gets a build from BuildMaster. .DESCRIPTION The `Get-BMBuild` function gets a build from BuildMaster. With no parameters, it returns all builds. To get all the builds that are part of a release, pass a release id or object to the `Release` parameter. To get a specific build, pass a build id or object to the `Build` parameter. This function uses BuildMaster's [Release and Build Deployment API](https://docs.inedo.com/docs/buildmaster-reference-api-release-and-build). .EXAMPLE Get-BMBuild -Session $session Demonstrates how to get all builds. .EXAMPLE Get-BMBuild -Session $session -Build $build Demonstrates how to get a specific build using a build object. .EXAMPLE Get-BMBuild -Session $session -Build 500 Demonstrates how to get a specific build using its id. .EXAMPLE Get-BMBuild -Session $session -Release $release Demonstrates how to get all the builds that are part of a release using a release object. .EXAMPLE Get-BMBuild -Session $session -Release 438 Demonstrates how to get all the builds that are part of a release using the release's id. #> [CmdletBinding(DefaultParameterSetName='AllBuilds')] param( # A session object to BuildMaster. Use the `New-BMSession` function to create a session. [Parameter(Mandatory)] [Object] $Session, # The build to get. Can be a build id or object. [Parameter(Mandatory, ParameterSetName='SpecificBuild')] [Object] $Build, # The release whose builds to get. Can be a release id or object. [Parameter(Mandatory, ParameterSetName='ReleaseBuilds')] [Object] $Release ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $parameter = @{} if( $PSCmdlet.ParameterSetName -eq 'SpecificBuild' ) { $parameter | Add-BMObjectParameter -Name 'build' -Value $Build } elseif( $PSCmdlet.ParameterSetName -eq 'ReleaseBuilds' ) { $bmRelease = $Release | Get-BMRelease -Session $session if (-not $bmRelease) { $msg = "Failed to get builds for release ""$($Release | Get-BMObjectName)"" because the release does not " + 'exist.' Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } $parameter | Add-BMObjectParameter -Name 'release' -Value $bmRelease } $parameterParam = @{ } if ($parameter.Count) { $parameterParam['Parameter'] = $parameter } $builds = @() Invoke-BMRestMethod -Session $Session -Name 'releases/builds' @parameterParam -Method Post | Where-Object { # There's a bug in BuildMaster's API that returns builds for multiple releases. We don't want this. if( $PSCmdlet.ParameterSetName -eq 'ReleaseBuilds' ) { return $_.releaseId -eq $parameter.releaseId } return $true } | Tee-Object -Variable 'builds' | Write-Output if ($PSCmdlet.ParameterSetName -eq 'SpecificBuild' -and -not $builds) { $msg = "Build ""$($Build | Get-BMObjectName -PropertyName 'buildNumber')"" does not exist." Write-Error -Message $msg -ErrorAction $ErrorActionPreference } } function Get-BMDeployment { <# .SYNOPSIS Gets a deployment from BuildMaster. .DESCRIPTION The Get-BMDeployment function gets deployments from BuildMaster. Pass a deployment ID to the Deployment parameter to get a single deployment. To filter for one or more deployments, pass the criteria to filter by to the rest of the parameters. Each parameter is combined into a logical "AND" that is used to filter for deployments. Only the deployments that match all the parameters are returned. Pass the current BuildMaster session to the `Session` parameter. Pass the deployment id or deployment object to the `Deployment` parameter. Pass the application name, id, or object to the `Application` parameter. Pass the release name, id, or object to the `Release` parameter. Pass the build name, id, or object to the `Build` parameter. Pass the environment name, id, or object to the `Environment` parameter. Pass the release number to the `ReleaseNumber` parameter. Pass the build number to the `BuildNumber` parameter. Pass the pipeline name to the `PipelineName` parameter. Pass the pipeline stage name to the `PipelineStageName` parameter. This function uses the [Release and Build Deployment API](https://docs.inedo.com/docs/buildmaster-reference-api-release-and-build). .EXAMPLE Get-BMDeployment -Session $session Demonstrates how to get all deployments from the instance of BuildMaster. .EXAMPLE Get-BMDeployment -Session $session -Deploytment $deployment Demonstrates how to get a specific deployment by passing a deployment object to the `Deployment` parameter. The `Get-BMDeployment` function looks for an `id` property on the object. #> [CmdletBinding()] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [Object] $Session, # The deployment to get. You can pass a deployment id or object. [Parameter(Mandatory, ParameterSetName='ById')] [Alias('ID')] [Object] $Deployment, # The application to get deployments for. You can pass an application id, application name, or application object. [Parameter(ParameterSetName='ByFilter')] [Object] $Application, # The release to get deployments for. You can pass an release id, release name, or release object. [Parameter(ParameterSetName='ByFilter')] [Object] $Release, # The build to get deployments for. You can pass an build id, build name, build number, or build object. [Parameter(ParameterSetName='ByFilter')] [Object] $Build, # The environment to get deployments for. You can pass an environment id, environment name, or environment object. [Parameter(ParameterSetName='ByFilter')] [Object] $Environment, # The name of the pipeline to get deployments for. [Parameter(ParameterSetName='ByFilter')] [String] $Pipeline, # The name of the pipeline stage to get deployments for. [Parameter(ParameterSetName='ByFilter')] [String] $Stage, # The status of the deployments to get. Accepted values are 'pending', 'executing', 'succeeded', 'warned', or 'failed'. [Parameter(ParameterSetName='ByFilter')] [ValidateSet('pending', 'executing', 'succeeded', 'warned', 'failed')] [String] $Status ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $WhatIfPreference = $false $parameter = @{ } | Add-BMObjectParameter -Name 'deployment' -Value $Deployment -PassThru | Add-BMObjectParameter -Name 'application' -Value $Application -PassThru | Add-BMObjectParameter -Name 'environment' -Value $Environment -PassThru | Add-BMObjectParameter -Name 'release' -Value $Release -PassThru if($Build) { if ($Build -is [string] -and -not [Int64]::TryParse($Build, [ref] $Build)) { $parameter['buildNumber'] = $Build } else { $parameter = $parameter | Add-BMObjectParameter -Name 'build' -Value $Build -PassThru } } if($Pipeline) { $parameter['pipelineName'] = $Pipeline } if($Stage) { $parameter['pipelineStageName'] = $Stage } if($Status) { $parameter['status'] = $Status } $deployments = @() Invoke-BMRestMethod -Session $Session -Name 'releases/builds/deployments' -Parameter $parameter -Method Post | Tee-Object -Variable 'deployments' | Write-Output if (-not $deployments) { if ($PSCmdlet.ParameterSetName -eq 'ById') { $msg = "Unable to get deployment ""$($Deployment | Get-BMObjectName)"" because it does not exist." } else { $params = ($parameter.Keys | ForEach-Object { "$($_) = $($parameter[$_])"}) -join ', ' $msg = "No deployments exist that match: ""$($params)""." } Write-Error -Message $msg -ErrorAction $ErrorActionPreference } } } function Get-BMEnvironment { <# .SYNOPSIS Returns environments from a BuildMaster instance. .DESCRIPTION The `Get-BMEnvironment` function gets all the environments from an instance of BuildMaster. To return a specific environment, pass its name to the `Name` parameter. If an environment with the given name doesn't exist, you'll get an error. You can use wildcards to search for active environments. Pass a session object representing the instance of BuildMaster to use to the `Session` parameter. Use `New-BMSession` to create a session object. This function uses BuildMaster's native APIs. .EXAMPLE Get-BMEnvironment Demonstrates how to return a list of all BuildMaster active environments. .EXAMPLE Get-BMEnvironment -Name '*Dev*' Demonstrates how to use wildcards to search for active environments. #> [CmdletBinding()] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [Object] $Session, # The name of the environment to return. If one doesn't exist, you'll get an error. Wildcards supported when # passing an environment name. If no environments match the wildcard pattern, no error is returned. [Parameter(ValueFromPipeline)] [Alias('Name')] [Object] $Environment ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $WhatIfPreference = $false $environments = $null $environmentName = $Environment | Get-BMObjectName -Strict -ErrorAction Ignore $searching = $environmentName -and [wildcardpattern]::ContainsWildcardCharacters($environmentName) Invoke-BMRestMethod -Session $Session -Name 'infrastructure/environments/list' | Where-Object { # Only return environments that match the user's search. if ($environmentName) { return $_.name -like $environmentName } return $true } | ForEach-Object { # BuildMaster API doesn't always return these properties. $_ | Add-Member -MemberType NoteProperty -Name 'parentName' -Value '' -ErrorAction Ignore return $_ } | Tee-Object -Variable 'environments' | Write-Output if ($Environment -and -not $environments -and -not $searching) { $msg = "Environment ""$($Environment | Get-BMObjectName)"" does not exist." Write-Error -Message $msg -ErrorAction $ErrorActionPreference } } } function Get-BMObjectID { <# .SYNOPSIS Gets the ID from a BuildMaster object. .DESCRIPTION The `Get-BMObjectID` gets the value of the ID from a BuildMaster object. Pipe the object to the function (or pass it to the `InputObject` property). Pass the object type name to the `ObjectTypeName` property. The function inspects the object passed in and: * if the object is $null, returns $null. * if the object is a numeric value, returns it. * returns the value of the object's `id` property, if it exists. * returns the value of the object's `$(ObjectTypeName)_Id` (e.g. Raft_Id, Application_Id) property, if it exists. * returns the value of the object's `$(ObjectTypeName)Id` property, if it exists. * if it can't find an id, writes an error and returns nothing. If you know the exact name of the property you want returned as an id, pass its name to the `PropertyName` parameter. In this case, the function inspects the object passed in and: * if the object is $null, returns $null. * if the object is a numeric value, returns it. * returns the value of the object's `$PropertyName` property, if it exists. .EXAMPLE 1 | Get-BMObjectID -ObjectNameType DoesNotMatter Demonstrates that `Get-BMObjectID` will always return any integer value it is passed. .EXAMPLE $raft | Get-BMObjectID -ObjectTypeName 'Raft' Demonstrates how to get the id from an object returned by any BuildMaster API. In this case, the object is a raft, and the function will return the value of the first of these properties to exist: `id`, `Raft_Id`, `RaftId`. .EXAMPLE $raftItem | Get-BMObjectID -PropertyName 'ApplicationGroup_Id' Demonstrates how to get the value of an id using a specific property name. In this example, if `$raftItem` is an integer, it will be returned, otherwise, the value of the `$raftItem.ApplicationGroup_Id` is returned. #> [CmdletBinding(DefaultParameterSetName='Default')] param( [Parameter(Mandatory, ValueFromPipeline)] [Object] $InputObject, [Parameter(Mandatory, ParameterSetName='ByPropertyName')] [String] $PropertyName, [Parameter(Mandatory, ParameterSetName='ByObjectTypeName')] [String] $ObjectTypeName ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState if ($null -eq $InputObject) { return $null } if ($InputObject | Test-BMID) { return [int]$InputObject } if (-not $PropertyName) { $PropertyName = 'Id' } if ($InputObject | Get-Member -Name $PropertyName) { return [int]($InputObject.$PropertyName) } if ($PSBoundParameters.ContainsKey('PropertyName')) { $msg = "Object does not have a ""${PropertyName}"" property." Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } if (-not $ObjectTypeName) { $ObjectTypeName = '*' } $idProperty = $InputObject | Get-Member -Name "$($ObjectTypeName)_Id" if (-not $idProperty) { $idProperty = $InputObject | Get-Member -Name "$($ObjectTypeName)Id" if (-not $idProperty) { $msg = "Object ""$($InputObject)"" is not an id and does not have ""Id"", ""$($ObjectTypeName)_Id"", " + "or ""$($ObjectTypeName)Id"" properties." Write-Error $msg -ErrorAction $ErrorActionPreference return } } $nameCount = ($idProperty | Measure-Object).Count if ($nameCount -gt 1) { $msg = "Object has multiple id properties: ""$($idProperty -join '", "')"". Use the " + '"PropertyName" parameter to set the name of the property to get.' Write-Error $msg -ErrorAction $ErrorActionPreference return } return [int]($InputObject.($idProperty.Name)) } } function Get-BMObjectName { <# .SYNOPSIS Returns the name of an object that was returned by the BuildMaster API. .DESCRIPTION The BuildMasterAutomation module allows you to pass ids, names, or objects as the value to many parameters. Use the `Get-BMObjectName` function to get the name of one of these parameter values. If passed a string or an id, those will be returned as the name. Otherwise, the function looks for a `Name` property, a property matching wildcard `*_Name`, and then a property matching wildcard `*Name`, and returns the value of the first property found. If no properties are found, the function writes an error. If an object has multiple properties that could be its name, pass the name of the property to use to the `PropertyName` function. .EXAMPLE $app | Get-BMObjectName Demonstrates how to get the name of an application object. In this case, the value of the application's `Application_Name` property will be returned. #> [CmdletBinding(DefaultParameterSetName='Default')] param( [Parameter(Mandatory, ValueFromPipeline)] [Object] $InputObject, [Parameter(Mandatory, ParameterSetName='ByPropertyName')] [String] $PropertyName, [Parameter(Mandatory, ParameterSetName='ByObjectTypeName')] [String] $ObjectTypeName, [switch] $Strict ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState if ($null -eq $InputObject) { return $null } if ($InputObject | Test-BMName) { return $InputObject } if (-not $PropertyName) { $PropertyName = 'Name' } if ($InputObject | Get-Member -Name $PropertyName) { return $InputObject.$PropertyName } if ($PSBoundParameters.ContainsKey('PropertyName')) { if (-not $Strict -and ($InputObject | Test-BMID)) { return $InputObject } $msg = "Object does not have a ""${PropertyName}"" property." Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } if (-not $ObjectTypeName) { $ObjectTypeName = '*' } $nameProperty = $InputObject | Get-Member -Name "$($ObjectTypeName)_Name" if (-not $nameProperty) { $nameProperty = $InputObject | Get-Member -Name "$($ObjectTypeName)Name" if (-not $nameProperty) { if (-not $Strict -and ($InputObject | Test-BMID)) { return $InputObject } $msg = "Object ""$($InputObject)"" does not have ""Name"", ""$($ObjectTypeName)_Name"", or " + """$($ObjectTypeName)Name"" properties." Write-Error $msg -ErrorAction $ErrorActionPreference return } } $nameCount = ($nameProperty | Measure-Object).Count if ($nameCount -gt 1) { $msg = "Object has multiple name properties: ""$($nameProperty -join '", "')"". Use the " + '"PropertyName" parameter to set the name of the property to get.' Write-Error $msg -ErrorAction $ErrorActionPreference return } return $InputObject.($nameProperty.Name) } } function Get-BMPackage { <# .SYNOPSIS Obsolete. Use `Get-BMBuild` instead. #> [CmdletBinding(DefaultParameterSetName='AllBuilds')] param( [Parameter(Mandatory)] [Object] $Session, [Parameter(Mandatory, ParameterSetName='SpecificPackage')] [Object] $Package, [Parameter(Mandatory, ParameterSetName='ReleasePackages')] [Object] $Release ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $msg = 'The BuildMasterAutomation module''s "Get-BMPackage" function is obsolete and will be removed in a future ' + 'version of BuildMasterAutomation. Use the "Get-BMBuild" function instead.' Write-WarningOnce $msg $getArgs = @{} if ($PSCmdlet.ParameterSetName -eq 'SpecificPackage') { $getArgs['Build'] = $Package } elseif( $PSCmdlet.ParameterSetName -eq 'ReleasePackages') { $getArgs['Release'] = $Release } Get-BMBuild -Session $Session @getArgs } function Get-BMPipeline { <# .SYNOPSIS Gets pipelines from BuildMaster. .DESCRIPTION The `Get-BMPipeline` function gets all pipelines. You can filter the list of pipelines by raft, pipeline name, and application by using the `Raft`, `Pipeline`, and `Application` parameters, respectively. To get only pipelines in a specific raft, pass the raft id or a raft object to the `Raft` parameter. To get a specific pipeline, pass its name or a pipeline object to the `Pipeline` parameter. To get pipelines for a specific application, pass the application id or application object to the `Application` parameter. If using multiple filter parameters, only pipelines that match all the filter parameters are returned. To search for a pipeline using a wildcard, pass a wildcard pattern to the `Pipeline` parameter. This function uses the `Rafts_GetRaftItems` native API method. .EXAMPLE Get-BMPipeline -Session $session -Raft $raft Demonstrates how to get all the pipelines across all rafts and applications. .EXAMPLE Get-BMPipeline -Session $session -Raft $raft Demonstrates how to get all the pipelines for a specific raft. .EXAMPLE Get-BMPipeline -Session $session -Pipeline 'BuildMaster Automation' Demonstrates how to get pipelines by name. If there are multiple pipelines across rafts and applications with the same name, they will all be returned. .EXAMPLE Get-BMPipeline -Session $session -Pipeline '*Automation' Demonstrates that you can use wildcards in the `Name` parameter's value to search for pipelines. .EXAMPLE Get-BMPipeline -Session $session -Raft $raft -Application 39 Demonstrates how to get a specific application's pipelines stored in a specific raft. .EXAMPLE Get-BMPipeline -Session $session -Raft $raft -Application $app -Pipeline 'Pipeline 2' Demonstrates how to get an application's pipeline using an application object and the pipeline's name. #> [CmdletBinding()] param( # A session object to BuildMaster. Use the `New-BMSession` function to creates a session. [Parameter(Mandatory)] [Object] $Session, # The raft in which to search for the pipeline. [Object] $Raft, # The pipeline to get. Pass a pipeline name (wildcards supported), or a pipeline object. [Parameter(ValueFromPipeline)] [Alias('Name')] [Object] $Pipeline, # The application whose pipelines to get. Passing application ids or objects are supported. [Alias('ApplicationID')] [Object] $Application ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState Get-BMRaftItem -Session $session ` -Raft $Raft ` -RaftItem $Pipeline ` -Application $Application ` -TypeCode ([BMRaftItemTypeCode]::Pipeline) | Add-BMPipelineMember -PassThru } } function Get-BMRaft { <# .SYNOPSIS Gets rafts from BuildMaster. .DESCRIPTION The `Get-BMRaft` function returns all rafts from BuildMaster. To get a specific raft, pass its name, id, or raft object to the `Raft` parameter (or pipe them into the function). If a raft with the given ID or represented by the object doesn't exist, the function writes an error and returns. If a string is passed to the `Raft` parameter, and it contains wildcards, the function will return all rafts whose names match the wildcard pattern. Otherwise, it will return the raft with that name and if it doesn't find a raft with that name, it writes an error and returns nothing. This function uses the native API. .EXAMPLE Get-BMRaft -Session $session Demonstrates how to use `Get-BMRaft` to get all rafts. #> [CmdletBinding()] param( # The session to BuildMaster. Use the `New-BMSession` function to create a session. [Parameter(Mandatory)] [Object] $Session, # The raft id, name, or raft object to get. If you pass a string, and the string has wildcards, all rafts whose # name matches the wildcard pattern are returned. [Parameter(ValueFromPipeline)] [Object] $Raft ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $WhatIfPreference = $false # We only get stuff in this function. $searching = ($Raft | Test-BMName) -and [wildcardpattern]::ContainsWildcardCharacters($Raft) $raftName = $Raft | Get-BMObjectName -ObjectTypeName 'Raft' -ErrorAction Ignore $endpointName = 'Rafts_GetRaft' if ($searching -or -not $Raft) { $endpointName = 'Rafts_GetRafts' } $parameters = @{} if ($endpointName -eq 'Rafts_GetRaft') { $raftID = $Raft | Get-BMObjectID -ObjectTypeName 'Raft' -ErrorAction Ignore if ($raftID) { $parameters['Raft_Id'] = $raftID } elseif ($raftName) { $parameters['Raft_Name'] = $raftName } } $raftPrefixScriptBlock = { if ($this.Raft_Id -eq 1) { return 'global' } return $this.Raft_Name } $rafts = @() Invoke-BMNativeApiMethod -Session $Session -Name $endpointName -Method Post -Parameter $parameters | Where-Object { if ($searching) { return $_.Raft_Name -like $raftName } return $true } | Add-Member -Name 'Raft_Prefix' ` -MemberType ScriptProperty ` -Value $raftPrefixScriptBlock ` -PassThru ` -ErrorAction Ignore | Tee-Object -Variable 'rafts' | Write-Output if ($Raft -and -not $rafts -and -not $searching) { $msg = "Raft ""$($Raft | Get-BMObjectName)"" does not exist." Write-Error -Message $msg -ErrorAction $ErrorActionPreference } } } function Get-BMRaftItem { <# .SYNOPSIS Gets raft items from BuildMaster. .DESCRIPTION The `Get-RaftItem` function gets all raft items across rafts and applications. To get only raft items in a specific raft, pass the raft's id or raft object to the `Raft` parameter. To get a specific raft item by its name, pass the name or raft item's object to the `RaftItem` parameter. To get raft items assigned to a specific application, pass the application id or application object to the `Application` parameter. To get raft items for a specific type, pass the type code to the `TypeCode parameter. Raft items are only returned if they match all parameters passed. Uses the BuildMaster native API. .EXAMPLE Get-BMRaftItem -Session $session -Raft $raftID Demonstrates how to get all the items from a specific raft. In this case, all raft items in the raft with id `$raftID` in any or no application are returned. .EXAMPLE Get-BMRaftItem -Session $session -Name '*yolo*' Demonstrates how to get raft items whose name matches a specific wildcard pattern. In this case, all raft items across rafts and applications whose names match `*yolo*` will be returned. .EXAMPLE Get-BMRaftItem -Session $session -Application $appOrIdOrName Demonstrates how to get raft items from a specific application. You can pass an application id or object to the `-Application` parameter. .EXAMPLE Get-BMRaftItem -Session $session -Raft $raftID -TypeCode Pipeline Demonstrates how to get all raft items of a specific type. In this case, all pipeline raft items across all rafts and applications are returned. .EXAMPLE Get-BMRaftItem -Session $session -Raft $raft -RaftItem 'specific' -Application $app -TypeCode Pipeline Demonstrates how to get a specific pipeline. In this case, it will return the pipeline raft item named `specific` from the `$raft` raft, assigned to application `$app`. #> [CmdletBinding()] param( # A session object to the BuildMaster instance to use. Use the `New-BMSession` function to create a session. [Parameter(Mandatory)] [Object] $Session, # The raft id or raft object whose items to return. [Object] $Raft, # The raft item to get. Pass the raft name (wildcards supported) or raft item object. [Parameter(ValueFromPipeline)] [Object] $RaftItem, # The application id or application object whose items to get. [Object] $Application, # The raft item types to return. [BMRaftItemTypeCode] $TypeCode ) begin { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $WhatIfPreference = $false # Gets items, but the API requires a POST. $appFilter = $null } process { $getRaftArgs = @{} if ($Raft) { $getRaftArgs['Raft'] = $Raft } $searching = ($RaftItem | Test-BMName) -and [wildcardpattern]::ContainsWildcardCharacters($RaftItem) $raftItems = $null & { # BuildMaster's API requires a raft ID at minimum, so use the one provided by the user or search all # rafts. foreach ($currentRaft in (Get-BMRaft -Session $Session @getRaftArgs)) { $getArgs = @{} | Add-BMObjectParameter -Name 'Raft' -Value $currentRaft -ForNativeApi -AsID -PassThru if ($RaftItem -and -not $searching) { $getArgs | Add-BMObjectParameter -Name 'RaftItem' -Value $RaftItem -AsName -ForNativeApi } if ($PSBoundParameters.ContainsKey('TypeCode')) { $getArgs | Add-BMParameter -Name 'RaftItemType_Code' -Value $TypeCode } if (-not $Application) { # If no Application_Id parameter, BuildMaster's API only returns pipelines that are not # associated with an application. Invoke-BMNativeApiMethod -Session $Session ` -Name 'Rafts_GetRaftItems' ` -Method Post ` -Parameter $getArgs } if ($null -eq $appFilter) { if ($Application) { $appFilter = $Application } else { $appFilter = Get-BMApplication -Session $Session } } # Get all raft items associated with the users application or any application. foreach ($appItem in $appFilter) { $getArgs | Add-BMObjectParameter -Name 'Application' -Value $appItem -ForNativeApi -AsID Invoke-BMNativeApiMethod -Session $Session ` -Name 'Rafts_GetRaftItems' ` -Method Post ` -Parameter $getArgs } } } | Where-Object { if ($searching) { return $_.RaftItem_Name -like $RaftItem } return $true } | Tee-Object -Variable 'raftItems' | Add-PSTypeName -RaftItem | Add-Member -Name 'Type' -MemberType ScriptProperty -Value { switch ($this.RaftItemType_Code) { 3 { return 'Module' } 4 { return 'Script' } 6 { return 'DeploymentPlan' } 8 { return 'Pipeline' } default { return $this.RaftItemType_Code } } } -PassThru | Add-Member -Name 'Content' -MemberType ScriptProperty -Value { $this.Content_Bytes | ConvertFrom-BMNativeApiByteValue } -PassThru | Write-Output if ($RaftItem -and -not $searching -and -not $raftItems) { $appMsg = '' if ($Application) { $appMsg = " in application ""$($Application | Get-BMObjectName -ObjectTypeName 'Application')""" } $typeCodeName = $TypeCode | Get-BMRaftTypeDisplayName -ErrorAction Ignore $msg = "$($typeCodeName) ""$($RaftItem | Get-BMObjectName -ObjectTypeName 'RaftItem')""$($appMsg) " + 'does not exist.' Write-Error -Message $msg -ErrorAction $ErrorActionPreference } } } function Get-BMRaftTypeDisplayName { [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline)] [AllowNull() ] [BMRaftItemTypeCode] $TypeCode ) process { if ($null -eq $TypeCode) { return 'Raft Item' } switch ($TypeCode) { 'DeploymentPlan' { return 'Deployment Plan' } default { $TypeCode.ToString() } } } } function Get-BMRelease { <# .SYNOPSIS Gets the release for an application in BuildMaster. .DESCRIPTION The `Get-BMRelease` function gets releases in BuildMaster. It uses the [Release and Build Deployment API](https://docs.inedo.com/docs/buildmaster-reference-api-release-and-build). To get a specific release, pass a release object, release ID, or release name to the `Release` parameter. If the release doesn't exist, the function will write an error. To get all the releases for a specific application, pass an application object, application ID, or application name to the `Application` parameter. You can get a specific application's release by passing the release's name to the `Name` parameter. .EXAMPLE Get-BMRelease -Session $session -Release $release Demonstrates how to get a specific release by passing a release object to the `Release` parameter. The `Get-BMRelease` function looks for an `id` or `name` property on the object. .EXAMPLE Get-BMRelease -Session $session -Application $app Demonstrates how to get all the releases for an application by passing an application object to the `Application` parameter. The application object must have a `Application_Id`, `id`, `Application_Name`, or `name` properties. .EXAMPLE Get-BMRelease -Session $session -Application 34 Demonstrates how to get all the releases for an application by passing its ID to the `Application` parameter. .EXAMPLE Get-BMRelease -Session $session -Application 'BuildMasterAutomation' Demonstrates how to get all the releases for an application by passing its name to the `Application` parameter. .EXAMPLE Get-BMRelease -Session $session -Application 'BuildMasterAutomation' -Name '4.1' Demonstrates how to get a specific release for an application by passing the release's name to the `Name` parameter. In this example, the '4.1' release will be returned, if it exists. #> [CmdletBinding()] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [Object] $Session, # The release to get. Pass a release id, name, or object. [Parameter(ValueFromPipeline)] [Alias('Name')] [Object] $Release, # The application whose releases to get. Pass an application id, name, or object. [Object] $Application ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $WhatIfPreference = $false if ($Application -and -not ($Application | Get-BMApplication -Session $Session)) { return } $parameter = @{} | Add-BMObjectParameter -Name 'release' -Value $Release -PassThru | Add-BMObjectParameter -Name 'application' -Value $Application -PassThru $releases = @() Invoke-BMRestMethod -Session $Session -Name 'releases' -Parameter $parameter -Method Post | Tee-Object -Variable 'releases' | Write-Output if ($Release -and -not $releases) { $appMsg = '' if ($Application) { $appMsg = " in application ""$($Application | Get-BMObjectName)""" } $msg = "Release ""$($Release | Get-BMObjectName)""$($appMsg) does not exist." Write-Error -Message $msg -ErrorAction $ErrorActionPreference } } } function Get-BMServer { <# .SYNOPSIS Returns servers in BuildMaster. .DESCRIPTION The `Get-BMServer` function gets all the servers from an instance of BuildMaster. To return a specific server, pipe the server's id, name (wildcards supported), or a server object to the function (or pass to the `Server` parameter). If the server doesn't exist, the function writes an error. The BuildMaster API returns plaintext versions of a server's API key (if it is using AES encryption). This function converts those keys into `SecureString` objects to make it harder to accidentally view/save them. This function uses BuildMaster's infrastructure management API. .EXAMPLE Get-BMServer Demonstrates how to return a list of all BuildMaster servers. .EXAMPLE '*example*' | Get-BMServer Demonstrates how to use wildcards to search for a server. #> [CmdletBinding()] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [Object]$Session, # The name of the server to return. Wildcards supported. By default, all servers are returned. [Parameter(ValueFromPipeline)] [Alias('Name')] [Object] $Server ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $WhatIfPreference = $false $servers = $null $serverName = $Server | Get-BMObjectName -Strict -ErrorAction Ignore $searching = $serverName -and [wildcardpattern]::ContainsWildcardCharacters($serverName) # BuildMaster API doesn't always return all a server's members. $memberNames = @( 'name', 'roles', 'environments', 'serverType', 'hostName', 'port', 'encryptionType', 'encryptionKey', 'requireSsl', 'credentialsName', 'tempPath', 'wsManUrl', 'active', 'variables' ) Invoke-BMRestMethod -Session $Session -Name 'infrastructure/servers/list' | Where-Object { if ($serverName) { return ($_.name -like $serverName) } return $true } | Add-PSTypeName -Server | ForEach-Object { $server = $_ foreach ($memberName in $memberNames) { if( -not ($server | Get-Member -Name $memberName) ) { $server | Add-Member -MemberType NoteProperty -Name $memberName -Value $null } } if( $server.encryptionKey ) { $server.encryptionKey = ConvertTo-SecureString -String $_.encryptionKey -AsPlainText -Force } $server } | Tee-Object -Variable 'servers' | Write-Output if (-not $searching -and $Server -and -not $servers) { $msg = "Server ""$($Server | Get-BMObjectName)"" does not exist." Write-Error -Message $msg -ErrorAction $ErrorActionPreference } } } function Get-BMServerRole { <# .SYNOPSIS Returns the server roles. .DESCRIPTION The `Get-BMServerRole` function gets all the server roles from an instance of BuildMaster. To return a specific role, pipe a server role id, name (wildcards supported), or a server role object to the function (or pass to the `ServerRole` parameter). If the server isn't found, the function write an error. This function uses BuildMaster's infrastructure management API. .EXAMPLE Get-BMServerRole Demonstrates how to return a list of all BuildMaster server roles. .EXAMPLE '*Service*' | Get-BMServerRole Demonstrates how to use wildcards to search for a service role. #> [CmdletBinding()] param( # The session to BuildMaster. New `New-BMSession` to create a session. [Parameter(Mandatory)] [Object] $Session, # The server role to return. Pass a server role id, name (wildcards supported), or server role object. [Parameter(ValueFromPipeline)] [Object] $ServerRole ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $roles = $null $serverRoleName = $ServerRole | Get-BMObjectName -Strict -ErrorAction Ignore $searching = $serverRoleName -and [wildcardpattern]::ContainsWildcardCharacters($serverRoleName) Invoke-BMRestMethod -Session $Session -Name 'infrastructure/roles/list' | Where-Object { if ($serverRoleName) { return ($_.name -like $serverRoleName) } return $true } | Tee-Object -Variable 'roles' | Write-Output if (-not $searching -and $ServerRole -and -not $roles) { $msg = "Server role ""$($ServerRole | Get-BMObjectName)"" does not exist." Write-Error -Message $msg -ErrorAction $ErrorActionPreference } } } function Get-BMVariable { <# .SYNOPSIS Gets BuildMaster variables. .DESCRIPTION The `Get-BMVariable` function gets BuildMaster variables. By default, it gets all global variables. It can also get all variables for a specific environment, server, server role, application group, application, release, and build. To get a specific variable, pass the variable's id, name, or object `Variable` parameter. If the variable doesn't exist, the function writes an error. To search for a variable, pass a wildcard string to the `Variable` parameter. To get an environment's variables, pass the environment's id, name, or object to the `Environment` parameter. To get a server role's variables, pass the server role's name to the `ServerRole` parameter. To get a server's variables, pass the server's name to the `Server` parameter. To get an application group's variables, pass the application group's name to the `ApplicationGroup` parameter. To get an application's variables, pass the application's name to the `Application` parameter. To get a release's variables, pass the release object to the `Release` parameter. Use the `Get-BMRelease` function to get a release object. To get a build's variables, pass the build object to the `Build` parameter. Use the `Get-BMBuild` function to get a build object. This function returns the variable value as a PowerShell data structure. If the variable is an OtterScript vector, it converts it to a PowerShell array; if it is an OtterScript map, it converts it to a PowerShell hashtable. To return the variable value in its original OtterScript form as a PowerShell string, use the `Raw` switch. This function uses BuildMaster's [Variables Management](https://docs.inedo.com/docs/buildmaster-reference-api-variables) API. Due to a bug in BuildMaster, when getting application or application group variables, it uses BuildMaster's native API. .EXAMPLE Get-BMVariable Demonstrates how to get all global variables. .EXAMPLE Get-BMVariable -Session $session -Name 'Var' Demonstrates how to get a specific global variable. .EXAMPLE Get-BMVariable -Session $session -Environment 'Dev' Demonstrates how to all an environment's variables. .EXAMPLE Get-BMVariable -Session $session -Name 'Var' -Environment 'Dev' Demonstrates how to get a specific variable in an environment. .EXAMPLE Get-BMVariable -Session $session -ServerRole 'WebApp' Demonstrates how to get all variables in a specific server role. .EXAMPLE Get-BMVariable -Session $session -Name 'Var' -ServerRole 'WebApp' Demonstrates how to get a specific variable in a server role. .EXAMPLE Get-BMVariable -Session $session -Server 'example.com' Demonstrates how to get all variables for a specific server. .EXAMPLE Get-BMVariable -Session $session -Name 'Var' -Server 'example.com' Demonstrates how to get a specific variable in a server. .EXAMPLE Get-BMVariable -Session $session -ApplicationGroup 'WebApps' Demonstrates how to get all variables from a specific application group. .EXAMPLE Get-BMVariable -Session $session -Name 'Var' -ApplicationGroup 'WebApps' Demonstrates how to get a specific variable from an application group. .EXAMPLE Get-BMVariable -Session $session -Application 'www' Demonstrates how to get all variables from a specific application. .EXAMPLE Get-BMVariable -Session $session -Name 'Var' -Application 'www' Demonstrates how to get a specific variable from an application. .EXAMPLE Get-BMVariable -Session $session -Release (Get-BMRelease -Session $session -Release 'gitflow' -Application 'WebApp') Demonstrates how to get all the variables for the "gitflow" release on the "WebApp" application. .EXAMPLE Get-BMVariable -Session $session -Build (Get-BMBuild -Session $session -Build 123) Demonstrates how to get all the variables for build id 123. .EXAMPLE Get-BMVariable -Session $session -Name 'Var' -Application 'www' -Raw Demonstrates how to get a specific variable from an application as a string in its OtterScript expression form. #> [CmdletBinding(DefaultParameterSetName='global')] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [object] $Session, # The variable to get. Pass a variable id, name, or object. If you pass a string, wildcards are supported, and # only variables whose name equal or match the string will be returned. [Parameter(ValueFromPipeline)] [Object] $Name, # The application of the variable. Pass an application id, name, or object. [Parameter(Mandatory, ParameterSetName='application')] [Alias('ApplicationName')] [Object] $Application, # The application group of the variable. Pass an application group id, name, or object. [Parameter(Mandatory, ParameterSetName='application-group')] [Alias('ApplicationGroupName')] [Object] $ApplicationGroup, # The environment of the variable. Pass an environment id, name, or object. [Parameter(Mandatory, ParameterSetName='environment')] [Alias('EnvironmentName')] [Object] $Environment, # The server of the variable. Pass an server id, name, or object. [Parameter(Mandatory, ParameterSetName='server')] [Alias('ServerName')] [Object] $Server, # The server role of the variable. Pass an server role id, name, or object. [Parameter(Mandatory, ParameterSetName='role')] [Alias('ServerRoleName')] [Object] $ServerRole, # Specific release of the variable. Must be a Release object returned from the `Get-BMRelease` function. [Parameter(Mandatory, ParameterSetName='releases')] [Object] $Release, # Specific build of the variable. Must be a Build object returned from the `Get-BMBuild` function. [Parameter(Mandatory, ParameterSetName='builds')] [Object] $Build, # Return the variable's value, not an object representing the variable. [switch] $ValueOnly, # Return the variable's value as a string rather than converting to a PowerShell object. [switch] $Raw ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $WhatIfPreference = $false # This function does not modify any data, but uses POST requests. $variableArg = @{} if ($Name) { $variableArg['Variable'] = $Name } Invoke-BMVariableEndpoint -Session $session ` @variableArg ` -EntityTypeName $PSCmdlet.ParameterSetName ` -BoundParameter $PSBoundParameters | ForEach-Object { if ($ValueOnly -and $Raw) { return $_.Value } if ($ValueOnly) { return ConvertFrom-BMOtterScriptExpression $_.Value } if ($Raw) { return $_ } $_.Value = ConvertFrom-BMOtterScriptExpression $_.Value return $_ } | Write-Output } } function Invoke-BMNativeApiMethod { <# .SYNOPSIS Calls a method on BuildMaster's "native" API. .DESCRIPTION The `Invoke-BMNativeApiMethod` calls a method on BuildMaster's "native" API. From Inedo: > This API endpoint should be avoided if there is an alternate API endpoint available, as those are much easier to use and will likely not change. In other words, use a native API at your own peril. When using the `WhatIf` parameter, only web requests that use the `Get` HTTP method are made. .EXAMPLE Invoke-BMNativeApiMethod -Session $session -Name 'Applications_CreateApplication' -Parameter @{ Application_Name = 'fubar' } Demonstrates how to call `Invoke-BMNativeApiMethod`. In this example, it is calling the `Applications_CreateApplication` method to create a new application named `fubar`. #> [CmdletBinding(SupportsShouldProcess=$true)] param( [Parameter(Mandatory=$true)] [object] # A session object that represents the BuildMaster instance to use. Use the `New-BMSession` function to create session objects. $Session, [Parameter(Mandatory=$true)] [string] # The name of the API method to use. The list can be found at http://inedo.com/support/documentation/buildmaster/reference/api/native, or under your local BuildMaster instance at /reference/api $Name, [Microsoft.PowerShell.Commands.WebRequestMethod] # The HTTP/web method to use. The default is `GET`. $Method = [Microsoft.PowerShell.Commands.WebRequestMethod]::Get, [hashtable] # Any parameters to pass to the endpoint. The keys/values are sent in the body of the request as a JSON object. $Parameter ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $parameterParam = @{ } if( $Parameter -and $Parameter.Count ) { $parameterParam['Parameter'] = $Parameter $parameterParam['AsJson'] = $true } Invoke-BMRestMethod -Session $Session -Name ('json/{0}' -f $Name) -Method $Method @parameterParam } function Invoke-BMRestMethod { <# .SYNOPSIS Invokes a BuildMaster REST method. .DESCRIPTION The `Invoke-BMRestMethod` invokes a BuildMaster REST API method. You pass the path to the endpoint (everything after `/api/`) via the `Name` parameter, the HTTP method to use via the `Method` parameter, and the parameters to pass in the body of the request via the `Parameter` parameter. This function converts the `Parameter` hashtable to a URL-encoded query string and sends it in the body of the request. You can send the parameters as JSON by adding the `AsJson` parameter. You can pass your own custom body to the `Body` parameter. If you do, make sure you set an appropriate content type for the request with the `ContentType` parameter. You also need to pass an object that represents the BuildMaster instance and API key to use when connecting via the `Session` parameter. Use the `New-BMSession` function to create a session object. When using the `WhatIf` parameter, only web requests that use the `Get` HTTP method are made. #> [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName='NoBody')] param( # A session object to BuildMaster. Use the `New-BMSession` function to create a session. [Parameter(Mandatory)] [Object] $Session, # The name of the API to use. The should be everything after `/api/` in the method's URI. [Parameter(Mandatory)] [String] $Name, # The HTTP/web method to use. The default is `GET`. [Microsoft.PowerShell.Commands.WebRequestMethod] $Method = [Microsoft.PowerShell.Commands.WebRequestMethod]::Get, # The parameters to pass to the method's endpoint. They are sent in the request body as URL-encoded, name/value # pairs, e.g. `name1=value1&name2=value2`. To send them as a JSON object, use the `AsJson` switch. [Parameter(Mandatory, ParameterSetName='BodyFromHashtable')] [hashtable] $Parameter, # Send the request body as JSON. Otherwise, the data is sent as name/value pairs. [Parameter(ParameterSetName='BodyFromHashtable')] [switch] $AsJson, # The body to send. [Parameter(Mandatory, ParameterSetName='CustomBody')] [AllowEmptyString()] [String] $Body, # The content type of the web request. # # By default, # # * if passing a value to the `Parameter` parameter, the content type is set to # `application/x-www-form-urlencoded` # * if passing a value to the `Parameter` parameter and you're using the `AsJson` switch, the content type is # set to `application/json`. # # Otherwise, the content type is not set. If you're passing your own body to the `Body` parameter, you may have # to set the appropriate content type for BuildMaster to respond. [String] $ContentType ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $uri = '{0}api/{1}' -f $Session.Url,$Name $debugBody = '' $webRequestParam = @{ } if ($Body) { $webRequestParam['Body'] = $debugBody = $Body } elseif( $Parameter ) { if( $AsJson ) { $Body = $Parameter | ConvertTo-Json -Depth 100 $debugBody = $Body -replace '("API_Key": +")[^"]+','$1********' $encryptionKeyRegex = '"encryptionKey":( +)"([^"]+)"' if( $debugBody -match $encryptionKeyRegex ) { $maskLength = $Matches[2].Length $mask = '*' * $maskLength $debugBody = $debugBody -replace $encryptionKeyRegex,('"encryptionKey":$1"{0}"' -f $mask) } if( -not $ContentType ) { $ContentType = 'application/json; charset=utf-8' } } else { $bodyBuilder = [Text.StringBuilder]::New() $valueToMask = '' foreach ($paramName in $Parameter.Keys) { $paramValue = $Parameter[$paramName] if ($bodyBuilder.Length -gt 0) { [void]$bodyBuilder.Append('&') } [void]$bodyBuilder.Append([Web.HttpUtility]::UrlEncode($paramName)) [void]$bodyBuilder.Append('=') [void]$bodyBuilder.Append([Web.HttpUtility]::UrlEncode($paramValue)) if ($paramName -eq 'API_Key') { $valueToMask = $paramValue } } $Body = $bodyBuilder.ToString() $debugBody = $Body if ($valueToMask) { $debugBody = $debugBody -replace [regex]::Escape($valueToMask), '********' } if( -not $ContentType ) { $ContentType = 'application/x-www-form-urlencoded; charset=utf-8' } } $webRequestParam['Body'] = $Body } if( $ContentType ) { $webRequestParam['ContentType'] = $ContentType } $headers = @{ 'X-ApiKey' = $Session.ApiKey; } # $DebugPreference = 'Continue' Write-Debug -Message ('{0} {1}' -f $Method.ToString().ToUpperInvariant(),($uri -replace '\b(API_Key=)([^&]+)','$1********')) if( $ContentType ) { Write-Debug -Message ('Content-Type: {0}' -f $ContentType) } foreach( $headerName in $headers.Keys ) { $value = $headers[$headerName] if( $headerName -eq 'X-ApiKey' ) { $value = '*' * 8 } Write-Debug -Message ('{0}: {1}' -f $headerName,$value) } if ($debugBody) { ($debugBody -split ([regex]::Escape([Environment]::NewLine))) | Write-Debug } try { if( $Method -eq [Microsoft.PowerShell.Commands.WebRequestMethod]::Get -or $PSCmdlet.ShouldProcess($Uri,$Method) ) { Invoke-RestMethod -Method $Method -Uri $uri @webRequestParam -Headers $headers | ForEach-Object { $_ } | Where-Object { $_ } } } catch { $Global:Error.RemoveAt(0) Write-Error -ErrorRecord $_ -ErrorAction $ErrorActionPreference } } function Invoke-BMVariableEndpoint { [CmdletBinding(DefaultParameterSetName='Get')] param( [Parameter(Mandatory)] [Object] $Session, [Parameter(Mandatory, ParameterSetName='Delete')] [Parameter(ParameterSetName='Get')] [Parameter(Mandatory, ParameterSetName='Set')] [Object] $Variable, [Parameter(Mandatory, ParameterSetName='Set')] [AllowEmptyString()] [String] $Value, [Parameter(Mandatory)] [ValidateSet('application', 'application-group', 'environment', 'global', 'server', 'role', 'releases', 'builds')] [String] $EntityTypeName, [Parameter(Mandatory)] [hashtable] $BoundParameter, [Parameter(Mandatory, ParameterSetName='Delete')] [switch] $ForDelete ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $variableName = '' $getting = $PSCmdlet.ParameterSetName -eq 'Get' $deleting = $ForDelete.IsPresent $updating = $PSCmdlet.ParameterSetName -eq 'Set' if ($Variable) { $variableName = $Variable | Get-BMObjectName -Strict if (-not $variableName -and ($deleting -or $updating)) { return } } $searching = $getting -and $variableName -and [wildcardpattern]::ContainsWildcardCharacters($variableName) $variablePathSegment = '' if ($variableName -and -not $searching) { $variablePathSegment = "/$([Uri]::EscapeDataString($variableName))" } $entityPathSegment = "global$($variablePathSegment)" $entityName = '' $bmEntity = $null $entityDesc = '' if ($EntityTypeName -ne 'global') { $entityTypeDescriptions = @{ 'application' = 'application'; 'application-group' = 'application group'; 'environment' = 'environment'; 'server' = 'server'; 'role' = 'server role'; 'releases' = 'release'; 'builds' = 'build'; } $entityDesc = $entityTypeDescriptions[$EntityTypeName] $entityDescCapitalized = [char]::ToUpperInvariant($entityDesc[0]) + $entityDesc.Substring(1) $entityToParamNameMap = @{ 'application' = 'Application'; 'application-group' = 'ApplicationGroup'; 'environment' = 'Environment'; 'server' = 'Server'; 'role' = 'ServerRole'; 'releases' = 'Release'; 'builds' = 'Build'; } # What parameter has the variable's entity? $paramName = $entityToParamNameMap[$EntityTypeName] # Get the entity. $entity = $BoundParameter[$paramName] $getEntityArg = @{ $paramName = $entity; } if ($EntityTypeName -in @('releases', 'builds')) { if ($entity.GetType().Name -ne 'PSCustomObject') { $msg = "The ${paramName} parameter must be a ${paramName} object from the Get-BM${paramName} " + "function, but it was a $($entity.GetType().Name) ""${entity}""." Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } # It's required to pass in an object for variables on Releases and Builds, therefore we know those already # exists and can use the objects directly. $entityPathSegment = "${EntityTypeName}/$([Uri]::EscapeDataString($entity.applicationName))/$([Uri]::EscapeDataString($entity.releaseNumber))" if ($EntityTypeName -eq 'builds') { $entityPathSegment = "${entityPathSegment}/$([Uri]::EscapeDataString($entity.buildNumber))" } $entityPathSegment = "${entityPathSegment}${variablePathSegment}" } else { # Check if the entity exists in BuildMaster. $bmEntity = & "Get-BM$($paramName)" -Session $Session @getEntityArg -ErrorAction Ignore if (-not $bmEntity) { $entityName = $entity | Get-BMObjectName $msg = "$($entityDescCapitalized) ""$($entityName)"" does not exist." if ($deleting) { $msg = "Unable to delete variable ""$($variableName)"" because $($entityDesc) " + """$($entityName)"" does not exist." } elseif ($updating) { $msg = "Unable to set variable ""$($variableName)"" because $($entityDesc) ""$($entityName)"" " + 'does not exist.' } Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } $entityName = $bmEntity | Get-BMOBjectName -Strict -ObjectTypeName $paramName # Create the entity-specific endpoint path. $entityPathSegment = "$($EntityTypeName)/$([Uri]::EscapeDataString($entityName))$($variablePathSegment)" } } $endpointPath = "variables/$($entityPathSegment)" $variables = @{} $nativeApiEntityIdParam = @{} [Object[]] $nativeVariables = @() $useNativeApi = $EntityTypeName -in @('application', 'application-group') if ($EntityTypeName -eq 'application') { $nativeApiEntityIdParam['Application_Id'] = $bmEntity.Application_Id } elseif ($EntityTypeName -eq 'application-group') { $nativeApiEntityIdParam['ApplicationGroup_Id'] = $bmEntity.ApplicationGroup_Id } if ($getting -or $deleting) { $variableExists = $false if ($useNativeApi) { $nativeVariables = Invoke-BMNativeApiMethod -Session $Session ` -Name 'Variables_GetVariablesForScope' ` -Method Post ` -Parameter $nativeApiEntityIdParam foreach ($nativeVar in $nativeVariables) { $variableExists = $true $bytes = [Convert]::FromBase64String($nativeVar.Variable_Value) $variables[$nativeVar.Variable_Name] = [Text.Encoding]::UTF8.GetString($bytes) } $variables = [pscustomobject]$variables } else { try { $variables = Invoke-BMRestMethod -Session $session -Name $endpointPath -ErrorAction Stop $variableExists = $true } catch { $Global:Error.RemoveAt(0) Write-Error -ErrorRecord $_ -ErrorAction $ErrorActionPreference } } if (-not $searching -and -not $variableExists) { $msg = "Variable ""$($variableName)"" does not exist." if ($bmEntity) { $msg = "$($entityDescCapitalized) ""$($entityName)"" variable ""$($variableName)"" does not exist." } if ($deleting) { $msg = "Unable to delete variable ""$($variableName)"" because it does not exist." if ($bmEntity) { $msg = "Unable to delete $($entityDesc) ""$($entityName)"" variable ""$($variableName)"" because the " + "variable does not exist." } } Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } } if ($deleting) { if ($useNativeApi) { $nativeVar = $nativeVariables | Where-Object 'Variable_Name' -EQ $variableName Invoke-BMNativeApiMethod -Session $session ` -Name 'Variables_DeleteVariable' ` -Method Post ` -Parameter @{ Variable_Id = $nativeVar.Variable_Id } } Invoke-BMRestMethod -Session $session -Name $endpointPath -Method Delete return } if ($updating) { Invoke-BMRestMethod -Session $session -Name $endpointPath -Body $Value -Method Post return } if ($variables -eq $null) { $variables = '' } if ($variables.GetType().Name -ne 'PSCustomObject') { return [pscustomobject]@{ Name = $variableName; Value = $variables; } } $variables | Get-Member -MemberType NoteProperty | ForEach-Object { return [pscustomobject]@{ 'Name' = $_.Name; 'Value' = $variables.($_.Name); } } | Where-Object { if ($variableName) { return $_.Name -like $variableName } return $true } | Write-Output } function New-BMApplication { <# .SYNOPSIS Creates an application in BuildMaster. .DESCRIPTION The `New-BMApplication` function creates an application in BuildMaster. This function uses the native BuildMaster API. Only a name is required to create an application. The name must be unique and not in use. These parameters are also available: * `ReleaseNumberScheme`: sets the release number scheme to use when you create a new release for the application Options are `MajorMinorRevision`, `MajorMinor`, or `DateBased`. * `BuildNumberScheme`: sets the build number scheme to use when creating new builds for an application. Options are `Unique`, `Sequential`, `DateBased`. * `Raft` to set the raft in which the application's scripts, pipelines, etc. should be saved. .EXAMPLE New-BMApplication -Session $session -Name 'MyNewApplication' Demonstrates the simplest way to create an application. In this example, a `MyNewApplication` application will be created and all its fields set to BuildMaster's default values. .EXAMPLE New-BMApplication -Session $session -Name 'MyNewApplication' -ReleaseNumberSchemeName MajorMinor -BuildNumberSchemeName Sequential This example demonstrates all the fields you can set when creating a new application. In this example, the new application will be called `MyNewApplication`, its release number scheme will be `MajorMinor`, and its build number schema will be `Sequential`. #> [CmdletBinding()] param( # A session object that represents the BuildMaster instance to use. Use the `New-BMSession` function to create # session objects. [Parameter(Mandatory)] [Object] $Session, # The name of the application. [Parameter(Mandatory)] [String] $Name, # The name of the release number scheme. Should be one of: # # * `MajorMinorRevision` # * `MajorMinor` # * `DateBased` [ValidateSet('MajorMinorRevision', 'MajorMinor', 'DateBased')] [String] $ReleaseNumberSchemeName, # The name of the build number scheme. Should be one of: # # * `Unique` # * `Sequential` # * `DateTimeBased` [ValidateSet('Unique', 'Sequential', 'DateTimeBased')] [String] $BuildNumberSchemeName, # The application group to assign. By default, the application will be ungrouped. Pass an application group id # or object. [Alias('ApplicationGroupID')] [Object] $ApplicationGroup, # The raft where the application's raft items will be stored. Pass a raft id, name, or raft object. [Object] $Raft ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $application = $Name | Get-BMApplication -Session $Session -ErrorAction Ignore if ($application) { Write-Error -Message "Application ""$($Name)"" already exists." -ErrorAction $ErrorActionPreference return } # We use the value in $PSBoundParameters because it is $null if not provided by the user. PowerShell sets a # not-provided [String] argument value to empty string. We need $null so `Add-BMParameter` knows the parameter was # not provided and won't add it to the parameter hashtable. $parameters = @{} | Add-BMParameter -Name 'Application_Name' -Value $Name -PassThru | Add-BMObjectParameter -Name 'ApplicationGroup' -Value $ApplicationGroup -ForNativeApi -PassThru | Add-BMParameter -Name 'ReleaseNumber_Scheme_Name' ` -Value $PSBoundParameters['ReleaseNumberSchemeName'] ` -PassThru | Add-BMParameter -Name 'BuildNumber_Scheme_Name' -Value $PSBoundParameters['BuildNumberSchemeName'] -PassThru $appID = Invoke-BMNativeApiMethod -Session $Session ` -Name 'Applications_CreateApplication' ` -Parameter $parameters ` -Method Post if( -not $appID ) { return } if ($Raft) { $editArgs = @{} | Add-BMParameter -Name 'Application_Id' -Value $appID -PassThru | Add-BMParameter -Name 'Application_Name' -Value $Name -PassThru | Add-BMObjectParameter -Name 'Raft' -Value $Raft -AsName -ForNativeApi -PassThru Invoke-BMNativeApiMethod -Session $Session ` -Name 'Applications_EditApplication' ` -Parameter $editArgs ` -Method Post } Invoke-BMNativeApiMethod -Session $Session ` -Name 'Applications_GetApplication' ` -Parameter @{ 'Application_Id' = $appID } ` -Method Post | Select-Object -ExpandProperty 'Applications_Extended' } function New-BMBuild { <# .SYNOPSIS Creates a new build for a release. .DESCRIPTION The `New-BMBuild` creates a new version/build of an application. In order to deploy an application, the application must have a release. Then you create builds in that release, and each build is then deployed using the release's pipeline. .EXAMPLE New-BMBuild -Session $session -Release $release Demonstrates how to create a new build in the `$release` release. BuildMaster detects what application based on the release (since releases are always tied to applications). Verion numbers and build numbers are incremented and handled based on the release settings. The `$release` parameter can be: * A release object with an `id` property. * A release ID integer. .EXAMPLE New-BMBuild -Session $session -ReleaseName '53' -Application $applicatoin Demonstrates how to create a new build by using the release's name. Since release names are only unique within an application, you must also specify the application via the `Application` parameter. .EXAMPLE New-BMBuild -Session $session -Release $release -PacakgeName '56.develop' -Variable @{ ProGetPackageName = '17.1.54+developer.deadbee' } Demonstrates how to create a release with a specific name, `56.develop`, and with a build-level variable, `ProGetPackageName`. #> [CmdletBinding()] param( # An object that represents the instance of BuildMaster to connect to. Use the `New-BMSession` function to # creates a session object. [Parameter(Mandatory)] [Object] $Session, # The release where the build should be created. Can be: # # * a release object with an `id` property # * the release ID as an integer [Parameter(Mandatory, ParameterSetName='ByReleaseID')] [Object] $Release, # The release number where the build should be created. Release numbers are unique within an application and # can be duplicated between applications. If you use this parameter to identify the release, you must also # provide a value for the `Application` parameter. [Parameter(Mandatory, ParameterSetName='ByReleaseNumber')] [String] $ReleaseNumber, # The application where the release identified by the `ReleaseNumber` parameter can be found. Can be: # # * An application object with a `Application_Id`, `id`, `Application_Name`, or `name` properties. # * The application ID as an integer. # * The application name as a string. [Parameter(Mandatory, ParameterSetName='ByReleaseNumber')] [Object] $Application, # The build number/name. If not provided, BuildMaster generates one based on the release settings. [string] $BuildNumber, # Any build variables to set. Build variables are unique to each build. [hashtable] $Variable ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $parameters = @{ } if( $PSCmdlet.ParameterSetName -eq 'ByReleaseID' ) { $parameters | Add-BMObjectParameter -Name 'release' -Value $Release } else { $parameters['releaseNumber'] = $ReleaseNumber $parameters | Add-BMObjectParameter -Name 'application' -Value $Application } if( $BuildNumber ) { $parameters['buildNumber'] = $BuildNumber } if( $Variable ) { foreach( $key in $Variable.Keys ) { $parameters[('${0}' -f $key)] = $Variable[$key] } } Invoke-BMRestMethod -Session $Session -Name 'releases/builds/create' -Parameter $parameters -Method Post } function New-BMEnvironment { <# .SYNOPSIS Creates a new environment in a BuildMaster instance. .DESCRIPTION The `New-BMEnvironment` creates a new environment in BuildMaster. Pass the name of the environment to the `Name` parameter. Names may only contain letters, numbers, periods, underscores, or dashes and may not end with an underscore or dash. Every environment must have a unique name. If you create a environment with a duplicate name, the BuildMaster error returns an error. You can set an new environment's parent environment with the `ParentName` parameter. You can create an inactive environment by using the `Inactive` switch. To return the environment, even if it already exists, use the `PassThru` switch. This function uses BuildMaster's infrastructure management API. .EXAMPLE New-BMEnvironment -Session $session -Name 'DevNew' Demonstrates how to create a new environment. .EXAMPLE New-BMEnvironment -Session $session -Name 'DevNew' -ErrorAction Ignore -PassThru Demonstrates how to ignore if an environment already exists and to return an enviornment object representing the new or already existing environment. #> [Diagnostics.CodeAnalysis.SuppressMessage('PSShouldProcess', '')] [CmdletBinding(SupportsShouldProcess)] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [Object] $Session, # The name of the environment to create. Must contain only letters, numbers, underscores, or dashes. Must begin # with a letter. Must not end with an underscore or dash. Must be between 1 and 50 characters long. [Parameter(Mandatory)] [ValidatePattern('^[A-Za-z][A-Za-z0-9_-]*(?<![_-])$')] [ValidateLength(1,50)] [String] $Name, # The name of this environment's parent environemnt. [String] $ParentName, # By default, new environments are active. If you want the environment to be inactive, use this switch. [switch] $Inactive, [switch] $PassThru ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $parameter = @{ name = $Name; parentName = $ParentName; active = (-not $Inactive); } $encodedName = [Uri]::EscapeDataString($Name) Invoke-BMRestMethod -Session $Session ` -Name ('infrastructure/environments/create/{0}' -f $encodedName) ` -Method Post ` -Parameter $parameter ` -AsJson if ($PassThru) { return Get-BMEnvironment -Session $Session -Environment ([pscustomobject]@{ 'Name' = $Name}) } } function New-BMPackage { <# .SYNOPSIS Obsolete. Use "New-BMBuild" instead. #> [CmdletBinding()] param( [Parameter(Mandatory)] [Object] $Session, [Parameter(Mandatory, ParameterSetName='ByReleaseID')] [Object] $Release, [Parameter(Mandatory, ParameterSetName='ByReleaseNumber')] [String] $ReleaseNumber, [Parameter(Mandatory, ParameterSetName='ByReleaseNumber')] [Object] $Application, [string] $PackageNumber, [hashtable] $Variable ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $msg = 'The BuildMasterAutomation module''s "New-BMPackage" function is obsolete and will be removed in a future ' + 'version of BuildMasterAutomation. Use the "Get-BMBuild" function instead.' Write-WarningOnce $msg $newArgs = @{} foreach ($paramName in @('Release', 'ReleaseNumber', 'Application', 'PackageNumber', 'Variable')) { if (-not $PSBoundParameters.ContainsKey($paramName)) { continue } $newParamName = $paramName if ($paramName -eq 'PackageNumber') { $newParamName = 'BuildNumber' } $newArgs[$newParamName] = $PSBoundParameters[$paramName] } New-BMBuild -Session $Session @newArgs } function New-BMPipelinePostDeploymentOptionsObject { <# .SYNOPSIS Creates an object to pass to `Set-BMPipeline` to set a pipeline's post-deployment options. .DESCRIPTION The `New-BMPipelinePostDeploymentOptionsObject` creates an object representing the post-deployment options for a pipeline. The object returned should be passed to the `Set-BMPipeline` function's `-PostDeploymentOption` parameter. If you don't pass any arguments, the post-deployment options object will have no properties. We don't know what the behavior of `Set-BMPipeline` will be in the case. We assume it will remove explicitly set values, reverting them to their defaults. .EXAMPLE New-BMPipelinePostDeploymentOptionsObject -CancelEarlierRelease $true -CreateNewRelease $true -DeployRelease $false Demonstrates how to create a post-deployment options object that sets the options to the opposite of BuildMaster's defaults. .EXAMPLE New-BMPipelinePostDeploymentOptionsObject -MarkDeployed $false Demonstrates how to turn off a single option. #> [CmdletBinding()] param( [bool] $CancelEarlierReleases, [bool] $CreateNewRelease, [bool] $MarkDeployed ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $options = @{ } if ($PSBoundParameters.ContainsKey('CancelEarlierReleases')) { $options['CancelReleases'] = $CancelEarlierReleases } if ($PSBoundParameters.ContainsKey('CreateNewRelease')) { $options['CreateRelease'] = $CreateNewRelease } if ($PSBoundParameters.ContainsKey('MarkDeployed')) { $options['DeployRelease'] = $MarkDeployed } return [pscustomobject]$options } function New-BMPipelineStageObject { <# .SYNOPSIS Creates a pipeline stage object that can be passed to `Set-BMPipeline`. .DESCRIPTION The `New-BMPipelineStageObject` creates an object that represents a stage of a pipeline. The object returned can be passed to the `Set-BMPipeline` function's `Stage` parameter. Pass the name of the stage to the `Name` parameter, the description to the `Description` parameter, and the stage targets to the `Target` parameter. Target objects can be created with the `New-BMPipelineStageTargetObject` function. .EXAMPLE New-BMPipelineStageObject -Name 'Example' Demonstrates how to create a stage object with just a name. #> [CmdletBinding()] param( # The stage's name. [Parameter(Mandatory)] [String] $Name, # The stage's description. [String] $Description, # A list of target objects for the stage. Target objects can be created with the # `New-BMPipelineStageTargetObject` function. [Parameter(ValueFromPipeline)] [Object[]] $Target ) begin { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $stage = [pscustomobject]@{ Name = $Name; Description = $Description; Targets = $null; } $targets = [Collections.ArrayList]::New() } process { foreach( $item in $Target ) { [void]$targets.Add($item) } } end { $stage.Targets = $targets.ToArray() return $stage } } function New-BMPipelineStageTargetObject { <# .SYNOPSIS Creates a stage target object that can be passed to the `New-BMPipelineStageObject` function. .DESCRIPTION The `New-BMPipelineStageTargetObject` function creates a pipeline stage target object. Pass the plan name to execute to the `PlanName` parameter. By default, creates an object that targets no servers. To target servers in a specific environment, pass the environment's name to the `EnvironmentName` parameter. To target all servers in an environment, use the `AllServers` switch. You must also pass an environment name. To target servers in specific roles, pass the role name(s) to the `ServerRoleName`. To target servers in specific server pools, pass the server pool names(s) to the `ServerPoolName` parameter. To target specific servers, pass the server name(s) to the `ServerName` parameter. .EXAMPLE New-BMPipelineStageTargetObject -PlanName 'Deploy' Demonstrates how to create a target object that executes a plan against no servers. .EXAMPLE New-BMPipelineStageTargetObject -PlanName 'Deploy' -EnvironmentName 'Integration' Demonstrates how to create a target object that executes a plan against servers in a specific environment. In this case, the `Integration` environment. .EXAMPLE New-BMPipelineStageTargetObject -PlanName 'Deploy' -EnvironmentName 'Integration' -ServerRoleName 'Build' Demonstrates how to create a target object that executes a plan against servers with a specific role. In this case, all servers with the `Build` role in the `Integration` environment will be targeted. .EXAMPLE New-BMPipelineStageTargetObject -PlanName 'Deploy' -EnvironmentName 'Integration' -ServerPoolName 'Build' Demonstrates how to create a target object that executes a plan against servers in a specific pool. In this case, all servers in the `Build` pool in the `Integration` environment will be targeted. .EXAMPLE New-BMPipelineStageTargetObject -PlanName 'Deploy' -EnvironmentName 'Integration' -AllServers Demonstrates how to create a target object that executes a plan against all servers in a specific environment. In this case, all servers in the `Integration` environment will be targeted. .EXAMPLE New-BMPipelineStageTargetObject -PlanName 'Deploy' -ServerName 'example.com' Demonstrates how to create a target object that executes a plan against a specific server. In this case, only the `example.com` server will be targed. #> [CmdletBinding(DefaultParameterSetName=0)] param( [Parameter(Mandatory)] [String] $PlanName, [Parameter(ParameterSetName=0)] [Parameter(ParameterSetName=1)] [Parameter(Mandatory, ParameterSetName=2)] [Parameter(ParameterSetName=3)] [Parameter(ParameterSetName=4)] [String] $EnvironmentName, [Parameter(Mandatory, ParameterSetName=1)] [String[]] $ServerName, [Parameter(Mandatory, ParameterSetName=2)] [switch] $AllServers, [Parameter(Mandatory, ParameterSetName=3)] [String[]] $ServerRoleName, [Parameter(Mandatory, ParameterSetName=4)] [String[]] $ServerPoolName ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $target = [pscustomobject]@{ PlanName = $PlanName; EnvironmentName = $EnvironmentName; ServerNames = @(); ServerRoleNames = @(); } if( $PSCmdlet.ParameterSetName -ne 0 ) { if( $PSCmdlet.ParameterSetName -eq 1 ) { $target.ServerNames = $ServerName } elseif( $PSCmdlet.ParameterSetName -eq 3 ) { $target.ServerRoleNames = $ServerRoleName } elseif( $PSCmdlet.ParameterSetName -eq 4 ) { $target.ServerRoleNames = $ServerPoolName } $target | Add-Member -Name 'DefaultServerContext' -Value $PSCmdlet.ParameterSetName -MemberType NoteProperty } return $target } function New-BMRelease { <# .SYNOPSIS Creates a new release for an application in BuildMaster. .DESCRIPTION The `New-BMRelease` function creates a release for an application in BuildMaster. It uses the BuildMaster [Release and Build Deployment API](https://docs.inedo.com/docs/buildmaster-reference-api-release-and-build). .EXAMPLE New-BMRelease -Session $session -Application 'BuildMasterAutomation' -Number '1.0' -Pipeline 'PowerShellModule' Demonstrates how to create a release using application/pipeline names. In this example, creates a `1.0` release for the `BuildMasterAutomation` application using the `PowerShellModule` pipeline. .EXAMPLE New-BMRelease -Session $session -Application 25 -Number '2.0' -Pipeline 'Deploy' Demonstrates how to create a release using an application id and pipeline name.. In this example, creates a `2.0` release for the application whose ID is `25` using the pipeline whose name is `Deploy`. .EXAMPLE New-BMRelease -Session $session -Application $app -Number '3.0' -Pipeline $pipeline Demonstrates how to create a release using application and pipeline objects. In this example, creates a `3.0` release for the application `$app` using the pipeline `$pipeline`. .EXAMPLE New-BMRelease -Session $session -Name 'BMA 1.0' -Application 'BuildMasterAutomation' -Number '1.0' -Pipeline 'PowerShellModule' Demonstrates how to create a release with a custom name. In this example, the release would be named `BMA 1.0`. #> [CmdletBinding()] param( # The session to BuildMaster. Use `New-BMSession` to create a session object. [Parameter(Mandatory)] [Object] $Session, # The application where the release should be created. Pass an application id, name, or object. [Parameter(Mandatory, ValueFromPipeline)] [Object] $Application, # The release number, e.g. 1, 2, 3, 1.0, 2.0, etc. [Parameter(Mandatory)] [String] $Number, # The pipeline the release should use. Pass a pipeline name or object. [Object] $Pipeline, # The name of the release. By default, BuildMaster uses the release number, i.e. the value of the `Number` # parameter. [String] $Name ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $parameters = @{ releaseNumber = $Number; releaseName = $Name; } $parameters | Add-BMObjectParameter -Name 'application' -Value $Application -PassThru | Add-BMObjectParameter -Name 'RaftItem' -Value $Pipeline -PassThru | Add-BMObjectParameter -Name 'pipeline' -Value $Pipeline -AsName Invoke-BMRestMethod -Session $Session -Name 'releases/create' -Method Post -Parameter $parameters } } function New-BMServer { <# .SYNOPSIS Creates a new server in a BuildMaster instance. .DESCRIPTION The `New-BMServer` function creates a new server in BuildMaster. Pass the name of the server to the `Name` parameter. Names may only contain letters, numbers, underscores, or dashes; they must begin with a letter; they must not end with dash or underscore. Pass the server type to the `Type` parameter. Type must be one of 'windows', 'powershell', 'ssh', or 'local'. Every server must have a unique name. If you create a server with a duplicate name, you'll get an error. This function uses BuildMaster's infrastructure management API. Pass a session object representing the instance of BuildMaster to use to the `Session` parameter. Use the `New-BMSession` function to create session objects. .LINK https://inedo.com/support/documentation/buildmaster/reference/api/infrastructure#data-specification .EXAMPLE New-BMServer -Session $session -Name 'example.com' -Windows Demonstrates how to create a new server that uses the Inedo Agent on Windows that doesn't encrypt the communication between the agent and the server. .EXAMPLE New-BMServer -Session $session -Name 'example.com' -Windows -EncryptionKey 'DEADBEEDEADBEEDEADBEEDEADBEEDEAD' Demonstrates how to create a new server that uses the Inedo Agent on Windows and uses an AES encryption key to encrypt the communication between the agent and server .EXAMPLE New-BMServer -Session $session -Name 'example.com' -Windows -Ssl -ForceSsl Demonstrates how to create a new server that uses the Inedo Agent on Windows and uses SSL to protect server to agent communications. As of BuildMaster 6.1.8, you *must* use the `ForceSsl` switch, otherwise SSL won't actually be enabled. .EXAMPLE New-BMServer -Session $session -Name 'example.com' -Ssh Demonstrates how to create a new server that uses SSH. .EXAMPLE New-BMServer -Session $session -Name 'example.com' -PowerShell Demonstrates how to create a new server that uses PowerShell Remoting. #> [Diagnostics.CodeAnalysis.SuppressMessage('PSShouldProcess', '')] [Diagnostics.CodeAnalysis.SuppressMessage('PSAvoidUsingPlainTextForPassword', '')] [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)] # An object representing the instance of BuildMaster to connect to. Use `New-BMSession` to create session objects. [object]$Session, [Parameter(Mandatory)] [ValidatePattern('^[A-Za-z][A-Za-z0-9_-]*(?<![_-])$')] [ValidateLength(1,50)] # The name of the server to create. Must contain only letters, numbers, underscores, or dashes. Must begin with a letter. Must not end with an underscore or dash. Must be between 1 and 50 characters long. [string]$Name, [Parameter(Mandatory,ParameterSetName='Local')] # Create a local server. [Switch]$Local, [Parameter(Mandatory,ParameterSetName='Windows')] [Parameter(Mandatory,ParameterSetName='WindowsAes')] [Parameter(Mandatory,ParameterSetName='WindowsSsl')] # Create a Windows server. [Switch]$Windows, [Parameter(Mandatory,ParameterSetName='Ssh')] # Create an SSH server. [Switch]$Ssh, [Parameter(ParameterSetName='Windows')] [Parameter(ParameterSetName='WindowsAes')] [Parameter(ParameterSetName='WindowsSsl')] [Parameter(ParameterSetName='Ssh')] # The server's host name. The default is to use the server's name. [string]$HostName, [Parameter(ParameterSetName='Windows')] [Parameter(ParameterSetName='WindowsAes')] [Parameter(ParameterSetName='WindowsSsl')] [Parameter(ParameterSetName='Ssh')] # The port to use. When adding a Windows server, the default is `46336`. When adding an SSH server, the default is `22`. [uint16]$Port, [Parameter(Mandatory,ParameterSetName='WindowsAes')] # The encryption key to use for the server. When passed, also automatically sets the server's encryption type to AES. Only used by Windows agents. [securestring]$EncryptionKey, [Parameter(Mandatory,ParameterSetName='WindowsSsl')] # Use SSL to communicate with the server's agent. Only used by Windows agents. [Switch]$Ssl, [Parameter(ParameterSetName='WindowsSsl')] # The server's agent only uses SSL. Only used by Windows agents. [Switch]$ForceSsl, [Parameter(Mandatory,ParameterSetName='PowerShell')] # Create a PowerShell server. [Switch]$PowerShell, [Parameter(ParameterSetName='PowerShell')] # The PowerShell remoting URL to use. [string]$WSManUrl, [Parameter(ParameterSetName='Ssh')] [Parameter(ParameterSetName='PowerShell')] # The name of the credential to use when connecting to the server via SSH or PowerShell Remoting. [string]$CredentialName, [Parameter(ParameterSetName='Ssh')] [Parameter(ParameterSetName='PowerShell')] # The temp path directory to use when connecting to the server via SSH or PowerShell Remoting. Default is `/tmp/buildmaster`. [string]$TempPath, # The environment(s) the server belongs in. [string[]]$Environment, # The server roles the server is part of. [string[]]$Role, # Any server-level variables to add to the server. [hashtable]$Variable, [Switch] # If set, creates the server but marks it as inactive. $Inactive ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $parameter = @{ 'active' = (-not $InActive.IsPresent); } if( -not $HostName ) { $HostName = $Name } if( -not $TempPath ) { $TempPath = '/tmp/buildmaster' } $serverType = $null if( $Windows ) { if( -not $Port ) { $Port = 46336 } $serverType = 'windows' $parameter['hostName'] = $HostName $parameter['port'] = $Port if( $EncryptionKey ) { $parameter['encryptionKey'] = (New-Object 'pscredential' 'encryptionkey',$EncryptionKey).GetNetworkCredential().Password $parameter['encryptionType'] = 'aes' } if( $Ssl ) { $parameter['encryptionType'] = 'ssl' $parameter['requireSsl'] = $ForceSsl.IsPresent } } elseif( $Ssh ) { if( -not $Port ) { $Port = 22 } $serverType = 'ssh' $parameter['hostName'] = $HostName $parameter['port'] = $Port } elseif( $PowerShell ) { $serverType = 'powershell' if( $WSManUrl ) { $parameter['wsManUrl'] = $WSManUrl } } elseif( $Local ) { $serverType = 'local' } else { throw 'Don''t know how you got to this code. Well done!' } $parameter['serverType'] = $serverType; if( $Ssh -or $PowerShell ) { if( $CredentialName ) { $parameter['credentialsName'] = $CredentialName } if( $TempPath ) { $parameter['tempPath'] = $TempPath } } if( $Environment ) { $parameter['environments'] = $Environment } if( $Role ) { $parameter['roles'] = $Role } if( $Variable ) { $parameter['variables'] = $Variable } $encodedName = [uri]::EscapeDataString($Name) Invoke-BMRestMethod -Session $Session -Name ('infrastructure/servers/create/{0}' -f $encodedName) -Method Post -Parameter $parameter -AsJson } function New-BMServerRole { <# .SYNOPSIS Creates a new server role in a BuildMaster instance. .DESCRIPTION The `New-BMServerRole` creates a new server role in BuildMaster. Pass the name of the role to the `Name` parameter. Names may only contain letters, numbers, spaces, periods, underscores, or dashes. Every role must have a unique name. If you create a role with a duplicate name, you'll get an error. This function uses BuildMaster's infrastructure management API. Pass a session object representing the instance of BuildMaster to use to the `Session` parameter. Use the `New-BMSession` function to create session objects. .EXAMPLE New-BMServerRole -Session $session -Name 'My Role' Demonstrates how to create a new server role. #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Mandatory)] # An object representing the instance of BuildMaster to connect to. Use `New-BMSession` to create session objects. [object]$Session, [Parameter(Mandatory)] [ValidatePattern('^[A-Za-z0-9 ._-]+$')] # The name of the server role to create. [string]$Name ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $encodedName = [uri]::EscapeDataString($Name) Invoke-BMRestMethod -Session $Session -Name ('infrastructure/roles/create/{0}' -f $encodedName) -Method Post -Body '{}' } function New-BMSession { <# .SYNOPSIS Creates a session object used to communicate with a BuildMaster instance. .DESCRIPTION The `New-BMSession` function creates and returns a session object that is required by any function in the BuildMasterAutomation module that communicates with BuildMaster. The session includes BuildMaster's URL and the credentials to use when making requests to BuildMaster's APIs .EXAMPLE $session = New-BMSession -Url 'https://buildmaster.com' -Credential $credential Demonstrates how to call `New-BMSession`. In this case, the returned session object can be passed to other BuildMasterAutomation module functions to communicate with BuildMaster at `https://buildmaster.com` with the credential in `$credential`. #> [CmdletBinding()] param( # The URI to the BuildMaster instance to use. [Parameter(Mandatory)] [Alias('Uri')] [Uri] $Url, # The API key to use when making requests to BuildMaster. [Parameter(Mandatory)] [String] $ApiKey ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState return [pscustomobject]@{ Url = $Url; ApiKey = $ApiKey; } | Add-Member -Name 'Uri' -MemberType AliasProperty -Value 'Url' -PassThru } function Publish-BMReleaseBuild { <# .SYNOPSIS Deploys a release build in BuildMaster. .DESCRIPTION The `Publish-BMReleaseBuild` deploys a release build in BuildMaster. The build is deployed using the pipeline assigned to the release the build is part of. This function uses BuildMaster's [Release and Build Deployment API](http://inedo.com/support/documentation/buildmaster/reference/api/release-and-build). Pass the build to deploy to the `Build` parameter. This can be a build object or a build ID (as an integer). To deploy a build, it must be part of a release that has a pipeline. That pipeline must have at least one stage and that stage must have a plan. If none of these conditions are met, you'll get no object back with no errors written. .EXAMPLE Publish-BMReleaseBuild -Session $session -Build $build Demonstrates how to deploy a build by passing a build object to the `Build` parameter. This object must have an `id` or `pipeline_id` property. .EXAMPLE Publish-BMReleaseBuild -Session $session -Build 383 Demonstrates how to deploy a build by passing its ID to the `Build` parameter. .EXAMPLE Publish-BMReleaseBuild -Session $session -Build $build -Stage $stage Demonstrates how to deploy a build to a specific stage of the release pipeline. By default, a build will deploy to the first stage of the assigned pipeline. #> [CmdletBinding()] param( # The session to BuildMaster. Use the `New-BMSession` function to create a session. [Parameter(Mandatory)] [Object] $Session, # The build to deploy. Can be a build id or object. [Parameter(Mandatory)] [Object] $Build, # The name of the pipeline stage where the build will be deployed. [String] $Stage, # Instructs BuildMaster to run the deploy even if the deploy to previous stages failed or the stage isn't the # first stage. [switch] $Force ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $parameters = @{} | Add-BMObjectParameter -Name 'build' -Value $Build -PassThru if( $Stage ) { $parameters['toStage'] = $Stage } if( $Force ) { $parameters['force'] = 'true' } Invoke-BMRestMethod -Session $Session -Name 'releases/builds/deploy' -Parameter $parameters -Method Post } function Publish-BMReleasePackage { <# .SYNOPSIS Obsolete. Use "Publish-BMReleaseBuild" instead. #> [CmdletBinding()] param( [Parameter(Mandatory)] [Object] $Session, [Parameter(Mandatory)] [Object] $Package, [String] $Stage, [switch] $Force ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $msg = 'The BuildMasterAutomation module''s "Publish-BMReleasePackage" function is obsolete and will be removed ' + 'in a future version of BuildMasterAutomation. Use the "Get-BMBuild" function instead.' Write-WarningOnce $msg $publishArgs = @{} foreach ($paramName in @('Stage', 'Force')) { if (-not $PSBoundParameters.ContainsKey($paramName)) { continue } $publishArgs[$newParamName] = $PSBoundParameters[$paramName] } Publish-BMReleaseBuild -Session $Session -Build $Package @publishArgs } function Remove-BMApplication { <# .SYNOPSIS Deletes applications in BuildMaster. .DESCRIPTION The `Remove-BMApplication` function removes an application from BuildMaster. Pass the application's id, name, or object to the `Application` parameter. If the application is disabled, it will be deleted. To delete the application even if it's still enabled, use the `Force` (switch). Use `Disable-BMApplication` to disable an application. Uses the BuildMaster native API. .EXAMPLE Remove-BMApplication -Session $session -Application $bmApp Demonstrates how to delete an application by passing an application object to the `Application` parameter. .EXAMPLE Remove-BMApplication -Session $session -Application 432 Demonstrates how to delete an application by passing its id to the `Application` parameter. .EXAMPLE Remove-BMApplication -Session $session -Application 'So Long' Demonstrates how to delete an application by passing its name to the `Application` parameter. .EXAMPLE $bmApp,433,'So Long 2' | Remove-BMApplication -Session $session Demonstrates that you can pipe application ids, names, and/or objects to `Remove-BMApplication`. .EXAMPLE Remove-BMApplication -Session $session -Application $bmApp -Force Demonstrates how to delete an application even if its still enabled by using the `Force` (switch). #> [CmdletBinding()] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [Object] $Session, # The application's id, name, or object to delete. Accepts pipeline input. [Parameter(Mandatory, ValueFromPipeline)] [Object] $Application, # If set, will delete an active application. [switch] $Force ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $bmApp = $Application | Get-BMApplication -Session $Session -ErrorAction Ignore if (-not $bmApp) { $msg = "Cannot delete application ""$($Application | Get-BMObjectName)"" because it does not exist." Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } if (-not $Force -and $bmApp.Active_Indicator -eq 'Y') { $msg = "Cannot delete application ""$($bmApp.Application_Name)"" because it is active. Use the " + '"Disable-BMApplication" function to disable the application then delete it, or use this ' + 'function''s -Force (switch) to delete this active application.' Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } $appArg = @{} | Add-BMObjectParameter -Name 'Application' -Value $bmApp -ForNativeApi -PassThru Invoke-BMNativeApiMethod -Session $Session ` -Name 'Applications_PurgeApplicationData' ` -Parameter $appArg ` -Method Post | Out-Null } } function Remove-BMEnvironment { <# .SYNOPSIS Deletes environments in BuildMaster. .DESCRIPTION The `Remove-BMEnvironment` function removes an environment from BuildMaster. Pass the environment's id, name, or object to the `Environment` parameter (or pipe them to `Remove-BMEnvironment`). Uses the BuildMaster [Infrastructure Management API](https://docs.inedo.com/docs/buildmaster-reference-api-infrastructure). .EXAMPLE Remove-BMEnvironment -Session $session -Environment $env Demonstrates how to delete an environment by passing an environment object to the `Environment` parameter. .EXAMPLE Remove-BMEnvironment -Session $session -Environment 432 Demonstrates how to delete an environment by passing its id to the `Environment` parameter. .EXAMPLE Remove-BMEnvironment -Session $session -Environment 'So Long' Demonstrates how to delete an environment by passing its name to the `Environment` parameter. .EXAMPLE $env,433,'So Long 2' | Remove-BMEnvironment -Session $session Demonstrates that you can pipe environment ids, names, and/or objects to `Remove-BMEnvironment`. #> [CmdletBinding()] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [Object] $Session, # The environment's id, name, or object to delete. Accepts pipeline input. [Parameter(Mandatory, ValueFromPipeline)] [Object] $Environment ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $env = $Environment | Get-BMEnvironment -Session $Session -ErrorAction Ignore if (-not $env) { $msg = "Cannot delete environment ""$($env | Get-BMObjectName)"" because it does not exist." Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } $apiName = "infrastructure/environments/delete/$($env.name)" Invoke-BMRestMethod -Session $Session -Name $apiName -Method Delete | Out-Null } } function Remove-BMPipeline { <# .SYNOPSIS Removes a pipeline from BuildMaster. .DESCRIPTION The `Remove-BMPipeline` function removes a pipeline from BuildMaster. Pass the pipeline's name or object to the `Pipeline` parameter (or pipe it into the function). The pipeline will be deleted, and its change history will be preserved. To also delete the pipeline's change history, use the `PurgeHistory` switch. .EXAMPLE Remove-BMPipeline -Session $session -Pipeline 'Tutorial' Demonstrates how to delete a pipeline using its name. .EXAMPLE Remove-BMPipeline -Session $session -Pipeline $pipeline Demonstrates how to delete a pipeline using a pipeline object. .EXAMPLE $pipeline, 'Tutorial' | Remove-BMPipeline -Session $session Demonstrates that you can pipe pipeline names and objects into `Remove-BMPipeline`. .EXAMPLE Remove-BMPipeline -Session $session -Pipeline $pipeline -PurgeHistory Demonstrates how to remove the pipeline's change history along with the pipeline by using the `PurgeHistory` switch. #> [CmdletBinding()] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [Object] $Session, # The raft in which the pipeline is stored. Pass the raft id or raft object. [Object] $Raft, # The name or pipeline object of the pipeline to delete. [Parameter(Mandatory, ValueFromPipeline)] [Object] $Pipeline, # If set, deletes the pipeline's change history. The default behavior preserve's the change history. [switch] $PurgeHistory ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $Pipeline | Remove-BMRaftItem -Session $session -Raft $Raft -PurgeHistory:$PurgeHistory } } function Remove-BMRaft { <# .SYNOPSIS Removes rafts from BuildMaster. .DESCRIPTION The `Remove-BMRaft` function removes a raft from BuildMaster. Pass its id, name, or raft object to the `Raft` parameter (or pipe to the function). If the raft exists, it is deleted. If it doesn't exist, an error is written. Uses BuildMaster's native API. .EXAMPLE Get-BMRaft -Session $session -Name 'delete me' | Remove-BMRaft -Session $Session Demonstrates how to delete a raft by using a raft object. .EXAMPLE 'delete me' | Remove-BMRaft -Session $Session Demonstrates how to delete a raft by using the raft's name. .EXAMPLE 134 | Remove-BMRaft -Session $Session Demonstrates how to delete a raft by using its id. #> [CmdletBinding()] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [Object] $Session, # The raft id, name, or raft object to delete. [Parameter(Mandatory, ValueFromPipeline)] [Object] $Raft ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $raftId = $Raft | Get-BMObjectID -ObjectTypeName 'Raft' -ErrorAction Ignore $raftName = $Raft | Get-BMObjectName -ObjectTypeName 'Raft' -ErrorAction Ignore $bmRaft = Get-BMRaft -Session $Session | Where-Object { if ($null -ne $raftId -and $_.Raft_Id -eq $raftId) { return $true } if ($null -ne $raftName -and $_.Raft_Name -eq $raftName) { return $true } return $false } if (-not $bmRaft) { $msg = "Unable to delete raft ""$($Raft | Get-BMObjectName)"" because it does not exist." Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } $parameter = @{ 'Raft_Id' = $bmRaft.Raft_Id } Invoke-BMNativeApiMethod -Session $Session -Name 'Rafts_DeleteRaft' -Method Post -Parameter $parameter } } function Remove-BMRaftItem { <# .SYNOPSIS Removes a raft item from BuildMaster. .DESCRIPTION The `Remove-BMRaftItem` function removes a raft item from BuildMaster. Pass the raft item's id or a raft item object to the `RaftItem` parameter (or pipe them into the function). The raft item will be deleted, and its change history will be preserved. To also delete the raft item's change history, use the `PurgeHistory` switch. .EXAMPLE Remove-BMRaftItem -Session $session -RaftItem 'Tutorial' Demonstrates how to delete a raft item using its name. .EXAMPLE Remove-BMRaftItem -Session $session -RaftItem $raftItem Demonstrates how to delete a raft item using a raft item object. .EXAMPLE $raftItem, 'Tutorial' | Remove-BMRaftItem -Session $session Demonstrates that you can pipe raft item names and objects into `Remove-BMRaftItem`. .EXAMPLE Remove-BMRaftItem -Session $session -RaftItem $raftItem -PurgeHistory Demonstrates how to remove the raft item's change history along with the raft item by using the `PurgeHistory` switch. #> [CmdletBinding()] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [Object] $Session, # The raft where the raft item is stored. [Object] $Raft, # The raft item id or raft item object of the raft item to delete. [Parameter(Mandatory, ValueFromPipeline)] [Object] $RaftItem, # If set, deletes the raft item's change history. The default behavior preserve's the change history. [switch] $PurgeHistory ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $existingRaftItem = $RaftItem | Get-BMRaftItem -Session $Session -Raft $Raft -ErrorAction Ignore if (-not $existingRaftItem) { $appMsg = $RaftItem | Get-BMObjectName -ObjectTypeName 'Application' -ErrorAction Ignore if ($appMsg) { $appMsg = " in application $($appMsg)" } $msg = "Could not delete raft item ""$($RaftItem | Get-BMObjectName -ObjectTypeName 'RaftItem')""" + "$($appMsg) because it does not exist." Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } $numRaftItems = ($existingRaftItem | Measure-Object).Count if ($numRaftItems -gt 1) { $msg = "Could not delete raft item ""$($RaftItem | Get-BMObjectName -ObjectTypeName 'RaftItem')"" " + "because there are $($numRaftItems) that match." Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } $raftParams = @{} | Add-BMObjectParameter -Name 'RaftItem' -Value $existingRaftItem -ForNativeApi -PassThru | Add-BMParameter -Name 'PurgeHistory_Indicator' -Value $PurgeHistory.IsPresent -PassThru Invoke-BMNativeApiMethod -Session $Session ` -Name 'Rafts_DeleteRaftItem' ` -Parameter $raftParams ` -Method Post | Out-Null } } function Remove-BMServer { <# .SYNOPSIS Removes a server from BuildMaster. .DESCRIPTION The `Remove-BMServer` function removes a server from BuildMaster. Pass the name of the server to remove to the `Name` parameter. If the server doesn't exist, an error is written. To ignore if the server exists or not, set the `ErrorAction` parameter to `Ignore`. Pass the session to the BuildMaster instance where you want to delete the server to the `Session` parameter. Use `New-BMSession` to create a session object. This function uses BuildMaster's infrastructure management API. .EXAMPLE Remove-BMServer -Session $session -Name 'example.com' Demonstrates how to delete a server. .EXAMPLE Get-BMServer -Session $session -Name 'example.com' | Remove-BMServer -Session $session Demonstrates that you can pipe the objects returned by `Get-BMServer` into `Remove-BMServer` to remove those servers. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "")] [CmdletBinding(SupportsShouldProcess)] param( # The instance of BuildMaster to connect to. [Parameter(Mandatory)] [Object] $Session, # The server to delete. Pass a server id, name, or a server object. [Parameter(Mandatory, ValueFromPipeline)] [Alias('Name')] [Object] $Server ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $foundServer = $Server | Get-BMServer -Session $session -ErrorAction Ignore if (-not $foundServer) { $msg = "Could not delete server ""$($Server | Get-BMObjectName)"" because it does not exist." Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } $encodedName = [Uri]::EscapeDataString(($Server | Get-BMObjectName)) Invoke-BMRestMethod -Session $Session ` -Name ('infrastructure/servers/delete/{0}' -f $encodedName) ` -Method Delete } } function Remove-BMServerRole { <# .SYNOPSIS Removes a server role from BuildMaster. .DESCRIPTION The `Remove-BMServerRole` removes a server role from BuildMaster. Pass the name of the role to remove to the `Name` parameter. If the server role doesn't exist, nothing happens. Pass the session to the BuildMaster instance where you want to delete the role to the `Session` parameter. Use `New-BMSession` to create a session object. This function uses BuildMaster's infrastructure management API. .EXAMPLE Remove-BMServerRole -Session $session -Name 'Server Role' Demonstrates how to delete a server role. .EXAMPLE Get-BMServerRole -Session $session -Name 'My Role' | Remove-BMServerRole -Session $session Demonstrates that you can pipe the objects returned by `Get-BMServerRole` into `Remove-BMServerRole` to remove those roles. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "")] [CmdletBinding(SupportsShouldProcess)] param( # An object representing the instance of BuildMaster to connect to. Use `New-BMSession` to create session objects. [Parameter(Mandatory)] [Object] $Session, # The server role to delete. Pass a server role id, name, or a server role object. [Parameter(Mandatory, ValueFromPipeline)] [Object] $ServerRole ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $role = $ServerRole | Get-BMServerRole -Session $Session -ErrorAction Ignore if (-not $role) { $msg = "Cannot delete server role ""$($ServerRole | Get-BMObjectName)"" because it does not exist." Write-Error -Message $msg -ErrorAction $ErrorActionPreference return } $encodedName = [uri]::EscapeDataString(($ServerRole | Get-BMObjectName)) Invoke-BMRestMethod -Session $Session -Name ('infrastructure/roles/delete/{0}' -f $encodedName) -Method Delete } } function Remove-BMVariable { <# .SYNOPSIS Deletes BuildMaster variables. .DESCRIPTION The `Remove-BMVariable` function deletes BuildMaster variables. By default, it deletes global variables. It can also delete variables for a specific environment, server, server role, application group, application, release, and build. Pass the name of the variable to delete to the `Name` parameter. If no variable exists to delete, you'll get an error. To delete an environment's variables, pass the environment's name to the `EnvironmentName` parameter. To delete a server role's variables, pass the server role's name to the `ServerRoleName` parameter. To delete a server's variables, pass the server's name to the `ServerName` parameter. To delete an application group's variables, pass the application group's name to the `ApplicationGroupName` parameter. To delete an application's variables, pass the application's name to the `ApplicationName` parameter. To delete a release's variables, pass the release object to the `Release` parameter. Use the `Get-BMRelease` function to get a release object. To delete a build's variables, pass the build object to the `Build` parameter. Use the `Get-BMBuild` function to get a build object. Pass a session object representing the instance of BuildMaster to use to the `Session` parameter. Use `New-BMSession` to create a session object. This function uses BuildMaster's [Variables Management](https://docs.inedo.com/docs/buildmaster-reference-api-variables) API. Due to a bug in BuildMaster, when getting application or application group variables, it uses BuildMaster's native API. .EXAMPLE Remove-BMVariable -Session $session -Name 'Var' Demonstrates how to delete a global variable. .EXAMPLE Remove-BMVariable -Session $session -Name 'Var' -EnvironmentName 'Dev' Demonstrates how to delete a variable in an environment. .EXAMPLE Remove-BMVariable -Session $session -Name 'Var' -ServerRoleName 'WebApp' Demonstrates how to delete a variable in a server role. .EXAMPLE Remove-BMVariable -Session $session -Name 'Var' -ServerName 'example.com' Demonstrates how to delete a variable in a server. .EXAMPLE Remove-BMVariable -Session $session -Name 'Var' -ApplicationGroupName 'WebApps' Demonstrates how to delete a variable from an application group. .EXAMPLE Remove-BMVariable -Session $session -Name 'Var' -Release (Get-BMRelease -Session $session -Release 'gitflow' -Application 'WebApp') Demonstrates how to delete a variable from a release. .EXAMPLE Remove-BMVariable -Session $session -Name 'Var' -Build (Get-BMBuild -Session $session -Build 123) Demonstrates how to delete a variable from a build. .EXAMPLE Remove-BMVariable -Session $session -Name 'Var' -ApplicationName 'www' Demonstrates how to delete a variable from an application. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSShouldProcess", "")] [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName='global')] param( # The session to BuildMaster. Use `New-PSSession` to create a new session. [Parameter(Mandatory)] [Object]$Session, # The variable to delete. Pass a variable name or variable object. [Parameter(Mandatory, ValueFromPipeline)] [Object] $Variable, # The application of the variable to delete. Pass an application id, name, or object. [Parameter(Mandatory, ParameterSetName='application')] [Object] $Application, # The application group of the variable to delete. Pass an application group id, name, or object. [Parameter(Mandatory, ParameterSetName='application-group')] [Object] $ApplicationGroup, # The environment of the variable to delete. Pass an environment id, name, or object. [Parameter(Mandatory, ParameterSetName='environment')] [Object] $Environment, # The server of the variable to delete. Pass a server id, name, or object. [Parameter(Mandatory, ParameterSetName='server')] [Object] $Server, # The server role of the variable to delete. Pass a server role id, name, or object. [Parameter(Mandatory, ParameterSetName='role')] [Object] $ServerRole, # Specific release of the variable to delete. Must be a Release object returned from the `Get-BMRelease` function. [Parameter(Mandatory, ParameterSetName='releases')] [Object] $Release, # Specific build of the variable to delete. Must be a Build object returned from the `Get-BMBuild` function. [Parameter(Mandatory, ParameterSetName='builds')] [Object] $Build ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState Invoke-BMVariableEndpoint -Session $session ` -Variable $Variable ` -EntityTypeName $PSCmdlet.ParameterSetName ` -BoundParameter $PSBoundParameters ` -ForDelete } } function Set-BMPipeline { <# .SYNOPSIS Creates a new pipeline in BuildMaster. .DESCRIPTION The `Set-BMPipeline` function creates or updates a pipeline in BuildMaster. Pass the name of the pipeline to the `Name` parameter. Pass the raft id or a raft object where the pipeline should be saved to the `Raft` parameter. A global pipeline will be created with no stages. To assign the pipeline to an application, pass the application's id, name or an application object to the `Application` parameter. To set the stages of the pipeline, use the `New-BMPipelineStageObject` and `New-BMPipelineStageTargetObject` functions to create the stages, then pass them to the `Stage` parameter. If the pipeline exists, you can use `Get-BMPipeline` to get the pipeline, modify its stage objects, then pass them to the `Stage` parameter. To set the post-deployment options of the pipeline, use `New-BMPipelinePostDeploymentOptionsObject` to create a post-deployment options object and pass that object to the `PostDeploymentOption` parameter. To set the color of the pipeline, pass the color in CSS RGB color format (e.g. `#aabbcc`) to the `Color` parameter. If you want stage order to be enforced by the pipeline, use the `EnforceStageSequence` switch. Any parameters *not* provided are not sent to BuildMaster in the create/update request. Those values won't be updated by BuildMaster. Any parameter you pass will cause the respective pipeline property to get updated to that value. This function uses [BuildMaster's native API](http://inedo.com/support/documentation/buildmaster/reference/api/native). .EXAMPLE Set-BMPipeline -Session $session -Name 'Powershell Module' Demonstrates how to create or update a global pipeline. In this example a pipeline named `PowerShell Module` will be created/updated that has no stages and uses BuildMaster's default values. .EXAMPLE Set-BMPipeline -Session $session -Name 'PowerShell Module' -Application $app Demonstrates how to create or update a pipeline for a specific application. In this example, the pipeline will be called `PowerShell Module` and it will be assigned to the `$app` application. #> [CmdletBinding(DefaultParameterSetName='Global')] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [Object] $Session, # The name of the pipeline. [Parameter(Mandatory)] [String] $Name, # The raft where the pipeline should be saved. Use `Get-BMRaft` to see a list of rafts. By default, uses # BuildMaster's default raft. Can be the ID of a raft or a raft object. [Parameter(Mandatory, ParameterSetName='Global')] [Object] $Raft, # The application to assign the pipeline to. Pass an application's id, name or an application object. [Parameter(Mandatory, ParameterSetName='Application')] [Object] $Application, # The background color BuildMaster should use when displaying the pipeline's name in the UI. Should be a CSS # hexadecimal color, e.g. `#ffffff` [String] $Color, # Stage configuration for the pipeline. Should be a list of objects returned by `New-BMPipelineStageObject` or # returned from `Get-BMPipeline`. [Object[]] $Stage, # If set, stage sequences will be enforced, i.e. builds can't be deployed to any stage. The default value in the # BuildMaster UI for this property is `true`. [switch] $EnforceStageSequence, # The post deploy options to use when creating the pipeline. Use the `New-BMPipelinePostDeploymentOptionsObject` # function to create a post-deployment option object. [Object] $PostDeploymentOption, # If set, a pipeline object will be returned. [switch] $PassThru ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $pipeline = [pscustomobject]@{ Name = $Name; Color = $Color; EnforceStageSequence = $EnforceStageSequence.IsPresent; Stages = $Stage; } if ($PostDeploymentOption) { $pipeline | Add-Member -Name 'PostDeploymentOptions' -MemberType NoteProperty -Value $PostDeploymentOption } $setRaftItemArgs = @{} if ($Raft) { $setRaftItemArgs['Raft'] = $Raft } if ($Application) { $setRaftItemArgs['Application'] = $Application } $Name | Set-BMRaftItem -Session $Session ` -TypeCode ([BMRaftItemTypeCode]::Pipeline) ` -Content ($pipeline | ConvertTo-Json -Depth 100) ` -PassThru:$PassThru ` @setRaftItemArgs | Add-BMPipelineMember -PassThru } function Set-BMRaft { <# .SYNOPSIS Creates and updates rafts in BuildMaster. .DESCRIPTION The `Set-BMRaft` function creates and updates rafts in BuildMaster. To create a raft, pass its name to the `Raft` parameter (or pipe the name to `Set-BMRaft`), its optional XML configuration to the `Configuration` parameter, and the raft's environment id, name, or environment object to the `Environment` parameter. To update a raft, pass its name, id, or raft object to the `Raft` parameter, and any new/changed values passed to the `Configuration` and `Environment` parameter. If you want the newly created or updated raft to be returned, use the `PassThru` switch. Uses the BuildMaster native API. .EXAMPLE 'New Raft' | Set-Raft -Session $session Demonstrates how to create a new Raft by piping its name to the `Set-BMRaft` function. .EXAMPLE Get-BMRaft -Name 'Update Me!' | Set-Raft -Session $session -Configuration $newConfig -Environment $newEnv Demonstrates how to update an existing raft by piping the raft object to `Set-Raft`, new configuration to the `Configuration` parameter, and new environment to the `Environment` parameter. .EXAMPLE $bmRaft = 'New Or Updated Raft' | Set-Raft -Session $session -PassThru Demonstrates how to get a raft object for the new or updated raft by using the `PassThru` switch. #> [CmdletBinding()] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [Object] $Session, # The raft's name, id, or raft object. When creating a raft, this *must* be the new raft's name. [Parameter(Mandatory, ValueFromPipeline)] [Object] $Raft, # The XML configuration for the raft. [String] $Configuration, # ***OBSOLETE.*** Not used and has no affect. [Parameter(DontShow)] [Object] $Environment, # If set, the new/updated raft will be returned. [switch] $PassThru ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $bmEnv = $null if ($Environment) { $msg = 'The Set-BMRaft function''s "Environment" parameter is obsolete and usages should be removed.' Write-Warning -Message $msg } $raftID = $Raft | Get-BMObjectID -ObjectTypeName 'Raft' -ErrorAction Ignore $raftName = $Raft | Get-BMObjectName -ObjectTypeName 'Raft' -ErrorAction Ignore $bmRaft = Get-BMRaft -Session $Session | Where-Object { if ($null -ne $raftID -and ($_.Raft_Id -eq $raftID)) { return $true } if ($null -ne $raftName -and $_.Raft_Name -eq $raftName) { return $true } return $false } if ($bmRaft -and $null -eq $raftName) { $raftName = $bmRaft.Raft_Name } $parameters = @{} | Add-BMObjectParameter -Name 'Raft' -Value $bmRaft -AsID -ForNativeApi -PassThru | ` Add-BMObjectParameter -Name 'Raft' -Value $raftName -AsName -ForNativeApi -PassThru | ` Add-BMParameter -Name 'Raft_Configuration' -Value $PSBoundParameters['Configuration'] -PassThru | ` Add-BMObjectParameter -Name 'Environment' -Value $bmEnv -PassThru $id = Invoke-BMNativeApiMethod -Session $Session ` -Name 'Rafts_CreateOrUpdateRaft' ` -Method Post ` -Parameter $parameters if ($PassThru) { return Get-BMRaft -Session $Session | Where-Object 'Raft_Id' -EQ $id } } } function Set-BMRaftItem { <# .SYNOPSIS Creates or updates a raft item in BuildMaster. .DESCRIPTION The `Set-BMRaftItem` function creates or updates a raft item in BuildMaster. Pass the raft item's name to the `Name` parameter. Pass the raft item's raft id or a raft object to the `Raft` parameter. Pass the object's type to the `TypeCode` parameter. The raft item will be created if it doesn't exist, or updated if it does. To assign the raft item to a specific application, pass the application's id, name or an application object to the `Application` parameter. The application must be configured to use the same raft as the raft item. If it doesn't, you'll get an error. Pass the raft item's content to the `Content` parameter. Pass the username of the user creating/updating the raft item to the `UserName` parameter. The default username is `DOMAIN\UserName` if the current computer is in a Microsoft domain, `UserName@MachineName` otherwise. If you want the created/updated raft item's object to be returned, use the `PassThru` switch. When creating scripts, the name of the raft item should end with an extension for the type of script it is, e.g. `.ps1` for PowerShell scripts, `.sh` for shell scripts, etc. Parameters not passed will not be sent to BuildMaster, and typically BuildMaster leaves those values as-is. Any parameter that you pass will get sent to BuildMaster and the respective raft item properties will be updated. .EXAMPLE Set-BMRaftItem -Session $session -Raft $raft -TypeCode Pipeline -Name 'Pipeline' Demonstrates how to use Set-BMRaftItem. In this example, an empty, global pipeline will be created in the raft represented by the `$raft` object. .EXAMPLE Set-BMRaftItem -Session $session -Raft $raft -TypeCode Module -Name 'Module' -Application $app -Content $otterScript Demonstrates how to use Set-BMRaftItem. In this example, a module will be created/updated for the application represented by the `$app` object with the content in the `$otterScript` variable. #> [CmdletBinding(DefaultParameterSetName='Global')] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [Object] $Session, # The raft where the raft item should be saved. Pass the raft id, name or a raft object. [Parameter(Mandatory, ParameterSetName='Global')] [Object] $Raft, # The type of the raft item. Valid values are: # # * Module (for creating OtterScript modules) # * Script (for creating PowerShell, batch, or shell scripts; make sure the raft item's name ends with the # extension for that script type) # * DeploymentPlan (for creating a deployment plan) # * Pipeline (for creating a pipeline; use `Set-BMPipeline` instead) [Parameter(Mandatory)] [BMRaftItemTypeCode] $TypeCode, # The raft item. To create a raft item, must be a name. If updating an existing raft item, can be a raft item # id, name, or raft item object. # # If the raft item is a script, its name must end with the extension of the script type, e.g. `.ps1` for # PowerShell scripts, `.sh` for shell scripts, etc. [Parameter(Mandatory, ValueFromPipeline)] [Object] $RaftItem, # The application the raft item belongs to. Pass the application's id, name, or an application object. [Parameter(Mandatory, ParameterSetName='Application')] [Object] $Application, # The content of the raft item. [String] $Content, # The username of the individual who is creating/updating the raft item. [String] $UserName, # If set, will return an object representing the created/update raft item. [switch] $PassThru ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState if( -not $UserName ) { $UserName = [Environment]::UserName if ([Environment]::UserDomainName) { $UserName = "$([Environment]::UserDomainName)\$($UserName)" } else { $UserName = "$($UserName)@$([Environment]::MachineName)" } } $contentBytes = $Content | ConvertTo-BMNativeApiByteValue $setRaftArgs = @{ RaftItem_Name = ($RaftItem | Get-BMObjectName); RaftItemType_Code = $TypeCode; ModifiedOn_Date = [DateTimeOffset]::Now; ModifiedBy_User_Name = $UserName; } | Add-BMParameter -PassThru -Name 'ModifiedBy_User_Name' -Value $UserName | Add-BMParameter -PassThru -Name 'Content_Bytes' -Value $contentBytes | Add-BMParameter -PassThru -Name 'Active_Indicator' -Value $true if ($Raft) { $Raft = $Raft | Get-BMRaft -Session $Session if (-not $Raft) { return } } # Make sure the application exists and use its raft to store the raft item. if ($Application) { $bmApp = Get-BMApplication -Session $Session -Application $Application if (-not $bmApp) { return } $setRaftArgs['Application_Id'] = $bmApp.Application_Id if ($bmApp.Raft_Name) { $Raft = $bmApp.Raft_Name | Get-BMRaft -Session $Session } if (-not $Raft) { # If an application isn't assigned to a raft, BuildMaster stores its code in the default raft. $Raft = Get-BMRaft -Session $Session -Raft 1 if (-not $Raft) { $appName = $bmApp.Application_Name $raftItemName = $RaftItem | Get-BMObjectName $typeName = $TypeCode | Get-BMRaftTypeDisplayName $msg = "Failed to save the ""$($appName)"" application's ""$($raftItemName)"" $($typeName) because " + 'the application is configured to use the default raft but the default raft does not exist.' Write-Error -Message $msg -ErrorAction $ErrorActionPreference } } } $setRaftArgs['Raft_Id'] = $Raft.Raft_Id Invoke-BMNativeApiMethod -Session $Session ` -Name 'Rafts_CreateOrUpdateRaftItem' ` -Parameter $setRaftArgs ` -Method Post | Out-Null if ($PassThru) { $RaftItem | Get-BMRaftItem -Session $Session -Raft $Raft -Application $Application -TypeCode $TypeCode } } function Set-BMRelease { <# .SYNOPSIS Updates a release in BuildMaster. .DESCRIPTION The `Set-BMRelease` function creates a BuildMaster release or updates an existing release. Pass the release's pipeline name or a pipeline object to the `Pipeline` object. Pass the release's name to the `Name` parameter. This function uses the BuildMaster native API endpoint "Releases_CreateOrUpdateRelease". If any parameter isn't passed, and the release exists, the respective properties on the release won't be updated. .EXAMPLE Set-BMRelease -Session $session -Release $release -Pipeline 'My Pipeline' -Name 'My New Name' Demonstrates how to update the pipeline and name of a release. #> [CmdletBinding()] param( # The session to BuildMaster. Use the `New-BMSession` object to create the session. [Parameter(Mandatory)] [Object] $Session, # The release to update. Pass the release's id, name, or a release object. [Parameter(Mandatory)] [Object] $Release, # The release's pipeline. [Alias('PipelineID')] [Object] $Pipeline, # The release's name. If the release exists, its name will be changed to this value. [String] $Name ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $bmRelease = Get-BMRelease -Session $Session -Release $Release if( -not $bmRelease ) { return } if ($Pipeline) { $bmPipeline = $Pipeline | Get-BMPipeline -Session $Session } else { $bmPipeline = $bmRelease.pipelineName | Get-BMPipeline -Session $Session -Application $bmRelease.applicationId } if (-not $bmPipeline) { return } $raft = $bmPipeline.Raft_Id | Get-BMRaft -Session $Session if (-not $raft) { return } if( -not $Name ) { $Name = $bmRelease.name } $parameter = @{ Application_Id = $bmRelease.ApplicationId; Release_Number = $bmRelease.number; Pipeline_Name = "$($raft.Raft_Prefix)::$($bmPipeline.RaftItem_Name)"; Release_Name = $Name; } Invoke-BMNativeApiMethod -Session $Session ` -Name 'Releases_CreateOrUpdateRelease' ` -Method Post ` -Parameter $parameter | Out-Null Get-BMRelease -Session $Session -Release $bmRelease -Application $bmRelease.ApplicationId } } function Set-BMVariable { <# .SYNOPSIS Create or set a BuildMaster variable. .DESCRIPTION The `Set-BMVariable` function creates or sets the value of a BuildMaster variable. By default, it creates/sets global variables. It can also set variables for a specific environment, server, server role, application group, application, release, and build. Pass the variable's name to the `Name` parameter and pass the variable's value to the `Value` parameter. The function takes variable values as PowerShell data structures and converts them to OtterScript expressions before they're passed to BuildMaster. A PowerShell hashtable is converted to an OtterScript map, a PowerShell array is converted to an OtterScript vector, and any other types are passed as their default string representation. Use the `Raw` switch to pass the variable value as-is to BuildMaster, i.e. no type conversion. To set an environment's variable, pass the environment's name to the `EnvironmentName` parameter. To set a server role's variable, pass the server role's name to the `ServerRoleName` parameter. To set a server's variable, pass the server's name to the `ServerName` parameter. To set an application group's variable, pass the application group's name to the `ApplicationGroupName` parameter. To set an application's variable, pass the application's name to the `ApplicationName` parameter. To set a release's variable, pass the release object to the `Release` parameter. Use the `Get-BMRelease` function to get a release object. To set a build's variable, pass the build object to the `Build` parameter. Use the `Get-BMBuild` function to get a build object. Pass a session object representing the instance of BuildMaster to use to the `Session` parameter. Use `New-BMSession` to create a session object. This function uses BuildMaster's variables API. .EXAMPLE Set-BMVariable -Session $session -Name 'Var' -Value 'Value' Demonstrates how to create or set a global variable. .EXAMPLE Set-BMVariable -Session $session -Name 'Var' -Value 'Value' -EnvironmentName 'Dev' Demonstrates how to create or set a variable in an environment. .EXAMPLE Set-BMVariable -Session $session -Name 'Var' -Value 'Value' -ServerRoleName 'WebApp' Demonstrates how to create or set a variable for a server role. .EXAMPLE Set-BMVariable -Session $session -Name 'Var' -Value 'Value' -ServerName 'example.com' Demonstrates how to create or set a variable for a server. .EXAMPLE Set-BMVariable -Session $session -Name 'Var' -Value 'Value' -ApplicationGroupName 'WebApps' Demonstrates how to create or set a variable for an application group. .EXAMPLE Set-BMVariable -Session $session -Name 'Var' -Value 'Value' -ApplicationName 'www' Demonstrates how to create or set a variable for an application. .EXAMPLE Set-BMVariable -Session $session -Name 'Var' -Value 'Value' -Release (Get-BMRelease -Session $session -Release 'gitflow' -Application 'WebApp') Demonstrates how to set a variable for a release. .EXAMPLE Set-BMVariable -Session $session -Name 'Var' -Value 'Value' -Build (Get-BMBuild -Session $session -Build 123) Demonstrates how to set a variable for a build. .EXAMPLE Set-BMVariable -Session $session -Name 'var' -Value @('hi', 'there') -ApplicationName 'www' Demonstrates how to set the variable 'var' to an OtterScript vector. #> [Diagnostics.CodeAnalysis.SuppressMessage('PSShouldProcess', '')] [CmdletBinding(SupportsShouldProcess, DefaultParameterSetName='global')] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [Object] $Session, # The name of the variable to create. [Parameter(Mandatory)] [String] $Name, # The variable's value. If a PowerShell array or hashtable is passed in it will be converted to the equivalent # OtterScript expression. [Parameter(Mandatory)] [Object] $Value, # The name of the application where the variable should be created. The default is to create a global variable. [Parameter(Mandatory,ParameterSetName='application')] [Alias('ApplicationName')] [Object] $Application, # The name of the application group where the variable should be created. The default is to create a global variable. [Parameter(Mandatory,ParameterSetName='application-group')] [Alias('ApplicationGroupName')] [Object] $ApplicationGroup, # The name of the environment where the variable should be created. The default is to create a global variable. [Parameter(Mandatory,ParameterSetName='environment')] [Alias('EnvironmentName')] [Object] $Environment, # The name of the server where the variable should be created. The default is to create a global variable. [Parameter(Mandatory,ParameterSetName='server')] [Alias('ServerName')] [Object] $Server, # The name of the server role where the variable should be created. The default is to create a global variable. [Parameter(Mandatory,ParameterSetName='role')] [Alias('ServerRoleName')] [Object] $ServerRole, # Specific release where the variable will be created. Must be a Release object returned from the `Get-BMRelease` function. [Parameter(Mandatory, ParameterSetName='releases')] [Object] $Release, # Specific build where the variable will be created. Must be a Build object returned from the `Get-BMBuild` function. [Parameter(Mandatory, ParameterSetName='builds')] [Object] $Build, # Pass the value as-is to BuildMaster, do not attempt to convert to OtterScript expression. [switch] $Raw ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState if (-not $Raw) { $Value = ConvertTo-BMOtterScriptExpression -Value $Value } Invoke-BMVariableEndpoint -Session $Session ` -Variable $Name ` -Value $Value ` -EntityTypeName $PSCmdlet.ParameterSetName ` -BoundParameter $PSBoundParameters } function Stop-BMRelease { <# .SYNOPSIS Cancels a release. .DESCRIPTION The `Stop-BMRelease` function cancels a BuildMaster release. It calls the `Releases_CancelRelease` native API endpoint. Pass the application name, id, or application object to the `Application` parameter and the release number to the `Number parameter. You can optionally provide a reason for cancelling the release by using the `Release` parameter. .EXAMPLE Stop-BMRelease -Session $session -Application 11 -Number 1.1 Demonstrates how to cancel a release. In this case, the `1.1` release of the application whose ID is `11` is cancelled. .EXAMPLE Stop-BMRelease -Session $session -Application 'BuildMaster Automation' -Number 1.1 Demonstrates how to cancel a release. In this case, the `1.1` release of the `BuildMaster Automation` application is cancelled. #> [CmdletBinding()] param( # The session to BuildMaster. Use `New-BMSession` to create a session. [Parameter(Mandatory)] [Object] $Session, # The application name, id, or application object that should be cancelled. [Parameter(Mandatory)] [Alias('ApplicationID')] [Object] $Application, # The release number, e.g. 1, 2, 3, 1.0, 2.0, etc. [Parameter(Mandatory)] [String] $Number, # The reason for cancelling the release. [String] $Reason ) Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState $bmApp = $Application | Get-BMApplication -Session $Session if (-not $bmApp) { return } $parameter = @{ Application_Id = $bmApp.Application_Id; Release_Number = $Number; CancelledReason_Text = $Reason; } Invoke-BMNativeApiMethod -Session $Session -Name 'Releases_CancelRelease' -Parameter $parameter -Method Post } function Test-BMID { <# .SYNOPSIS Tests if an object is a BuildMaster ID. .DESCRIPTION The `Test-BMID` function tests if an object is actually an ID. An ID is any signed or unsigned integer type, including bytes. .EXAMPLE 1 | Test-BMID Returns `$true`. .EXAMPLE '1' | Test-BMID Returns `$false`. .EXAMPLE $null | Test-BMID Returns `$false`. #> [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline, Position=0)] [AllowNull()] [AllowEmptyString()] [Object] $ID ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState if ($null -eq $ID) { return $false } $intTypes = @( [TypeCode]::Byte, [TypeCode]::Int16, [TypeCode]::Int32, [TypeCode]::Int64, [TypeCode]::SByte, [TypeCode]::UInt16, [TypeCode]::UInt32, [TypeCode]::UInt64 ) return ([Type]::GetTypeCode($ID.GetType()) -in $intTypes) } } function Test-BMName { <# .SYNOPSIS Tests if an object is a BuildMaster name. .DESCRIPTION The `Test-BMName` function tests if an object is actually a name. .EXAMPLE 1 | Test-BMName Returns `$false`. .EXAMPLE 'YOLO' | Test-BMName Returns `$true`. .EXAMPLE '$null | Test-BMName Returns `$false`. #> [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline, Position=0)] [AllowNull()] [AllowEmptyString()] [Object] $Name ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState if ($null -eq $Name) { return $false } return ($Name -is [String]) } } function Test-BMObject { <# .SYNOPSIS Tests if an object is a BuildMaster object. .DESCRIPTION The `Test-BMObject` function tests if an object is actually a name. .EXAMPLE 1 | Test-BMObject Returns `$false`. .EXAMPLE 'YOLO' | Test-BMObject Returns `$false`. .EXAMPLE Get-BMApplication -Session $session -Name 'MyApp' | Test-BMObject Returns `$true`. .EXAMPLE $null | Test-BMObject Returns `$false`. #> [CmdletBinding()] param( [Parameter(Mandatory, ValueFromPipeline, Position=0)] [AllowNull()] [AllowEmptyString()] [Object] $Object ) process { Set-StrictMode -Version 'Latest' Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState if ($null -eq $Object) { return $false } return (-not ($Object | Test-BMID) -and -not ($Object | Test-BMName)) } } # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. function Use-CallerPreference { <# .SYNOPSIS Sets the PowerShell preference variables in a module's function based on the callers preferences. .DESCRIPTION Script module functions do not automatically inherit their caller's variables, including preferences set by common parameters. This means if you call a script with switches like `-Verbose` or `-WhatIf`, those that parameter don't get passed into any function that belongs to a module. When used in a module function, `Use-CallerPreference` will grab the value of these common parameters used by the function's caller: * ErrorAction * Debug * Confirm * InformationAction * Verbose * WarningAction * WhatIf This function should be used in a module's function to grab the caller's preference variables so the caller doesn't have to explicitly pass common parameters to the module function. This function is adapted from the [`Get-CallerPreference` function written by David Wyatt](https://gallery.technet.microsoft.com/scriptcenter/Inherit-Preference-82343b9d). There is currently a [bug in PowerShell](https://connect.microsoft.com/PowerShell/Feedback/Details/763621) that causes an error when `ErrorAction` is implicitly set to `Ignore`. If you use this function, you'll need to add explicit `-ErrorAction $ErrorActionPreference` to every function/cmdlet call in your function. Please vote up this issue so it can get fixed. .LINK about_Preference_Variables .LINK about_CommonParameters .LINK https://gallery.technet.microsoft.com/scriptcenter/Inherit-Preference-82343b9d .LINK http://powershell.org/wp/2014/01/13/getting-your-script-module-functions-to-inherit-preference-variables-from-the-caller/ .EXAMPLE Use-CallerPreference -Cmdlet $PSCmdlet -SessionState $ExecutionContext.SessionState Demonstrates how to set the caller's common parameter preference variables in a module function. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] #[Management.Automation.PSScriptCmdlet] # The module function's `$PSCmdlet` object. Requires the function be decorated with the `[CmdletBinding()]` attribute. $Cmdlet, [Parameter(Mandatory = $true)] [Management.Automation.SessionState] # The module function's `$ExecutionContext.SessionState` object. Requires the function be decorated with the `[CmdletBinding()]` attribute. # # Used to set variables in its callers' scope, even if that caller is in a different script module. $SessionState ) Set-StrictMode -Version 'Latest' # List of preference variables taken from the about_Preference_Variables and their common parameter name (taken from about_CommonParameters). $commonPreferences = @{ 'ErrorActionPreference' = 'ErrorAction'; 'DebugPreference' = 'Debug'; 'ConfirmPreference' = 'Confirm'; 'InformationPreference' = 'InformationAction'; 'VerbosePreference' = 'Verbose'; 'WarningPreference' = 'WarningAction'; 'WhatIfPreference' = 'WhatIf'; } foreach( $prefName in $commonPreferences.Keys ) { $parameterName = $commonPreferences[$prefName] # Don't do anything if the parameter was passed in. if( $Cmdlet.MyInvocation.BoundParameters.ContainsKey($parameterName) ) { continue } $variable = $Cmdlet.SessionState.PSVariable.Get($prefName) # Don't do anything if caller didn't use a common parameter. if( -not $variable ) { continue } if( $SessionState -eq $ExecutionContext.SessionState ) { Set-Variable -Scope 1 -Name $variable.Name -Value $variable.Value -Force -Confirm:$false -WhatIf:$false } else { $SessionState.PSVariable.Set($variable.Name, $variable.Value) } } } |