AtlassianPS.Configuration.psm1
#region Dependencies # Load the Module's namespace from C# if (-not("AtlassianPS.ServerData" -as [Type])) { Add-Type -Path (Join-Path $PSScriptRoot AtlassianPS.Configuration.Types.cs) -ReferencedAssemblies Microsoft.CSharp, Microsoft.PowerShell.Commands.Utility, System.Management.Automation, System.Runtime.Extensions, System.Security.Cryptography.X509Certificates } if ($PSVersionTable.PSVersion.Major -lt 5) { Add-Type -Path (Join-Path $PSScriptRoot AtlassianPS.Configuration.Attributes.cs) -ReferencedAssemblies Microsoft.CSharp, Microsoft.PowerShell.Commands.Utility, System.Management.Automation, System.Runtime.Extensions, System.Security.Cryptography.X509Certificates } #endregion Dependencies #region ModuleConfig # Add our own Converters for serialization Add-MetadataConverter @{ [AtlassianPS.MessageStyle] = { "AtlassianPSMessageStyle -Indent {0} -TimeStamp {1} -BreadCrumbs {2} -FunctionName {3}" -f (ConvertTo-Metadata $_.Indent), (ConvertTo-Metadata $_.TimeStamp), (ConvertTo-Metadata $_.BreadCrumbs), (ConvertTo-Metadata $_.FunctionName) } AtlassianPSMessageStyle = { param($Indent, $TimeStamp, $BreadCrumbs, $FunctionName) [AtlassianPS.MessageStyle]$PSBoundParameters } [AtlassianPS.ServerData] = { "AtlassianPSServerData -Id {0} -Name '{1}' -Uri '{2}' -Type '{3}' -Headers {4}" -f $_.Id, $_.Name, $_.Uri, $_.Type, (ConvertTo-Metadata $_.Headers) } AtlassianPSServerData = { param($Id, $Name, $Uri, $Type, $Headers) if ([string]::IsNullOrEmpty($Headers)) { $Headers = $null } [AtlassianPS.ServerData]$PSBoundParameters } } #region LoadFunctions #region Add-ServerConfiguration function Add-ServerConfiguration { # .ExternalHelp ..\AtlassianPS.Configuration-help.xml [CmdletBinding()] [OutputType( [void] )] param( [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [Alias('Url', 'Address')] [Uri] $Uri, [Parameter( ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [Alias('ServerName', 'Alias')] [String] $Name, [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [AtlassianPS.ServerType] $Type, [Parameter( ValueFromPipelineByPropertyName )] [Microsoft.PowerShell.Commands.WebRequestSession] $Session, [Parameter( ValueFromPipelineByPropertyName )] [Hashtable] $Headers = @{} ) begin { Write-Verbose "Function started" if (-not ($script:Configuration.ServerList)) { $script:Configuration.ServerList = $null } $serverList = [System.Collections.Generic.List[AtlassianPS.ServerData]]::new() if (Get-ServerConfiguration) { [System.Collections.Generic.List[AtlassianPS.ServerData]]$serverList = Get-ServerConfiguration } } process { Write-DebugMessage "ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "PSBoundParameters: $($PSBoundParameters | Out-String)" if (-not $Name) { $Name = $Uri.Authority } if (Get-ServerConfiguration | Where-Object Name -eq $Name) { $writeErrorSplat = @{ ExceptionType = "System.ApplicationException" Message = "An entry with name [$Name] already exists" ErrorId = "AtlassianPS.ServerData.EntryExists" Category = "InvalidData" TargetObject = $Name } WriteError @writeErrorSplat } else { if (-not ($index = ((Get-ServerConfiguration).Id | Measure-Object -Maximum).Maximum)) { $index = 0 } $index++ $config = [AtlassianPS.ServerData]@{ Id = $index Name = $Name Uri = ([Uri]($Uri.AbsoluteUri -replace "\/$", "")) Type = $Type # IsCloudServer = (Test-ServerIsCloud -Type $Type -Uri $Uri -Headers $Headers -ErrorAction Stop -verbose) Session = $Session Headers = $Headers } Write-Verbose "Adding server #$($index): [$($config.Name)]" Write-DebugMessage "Adding server `$config: $($config.Name) @ index $index" -BreakPoint $serverList.Add($config) } } end { Write-DebugMessage "Persisting ServerList" $script:Configuration["ServerList"] = $serverList Save-Configuration Write-Verbose "Function ended" } } #endregion Add-ServerConfiguration #region Get-Configuration function Get-Configuration { # .ExternalHelp ..\AtlassianPS.Configuration-help.xml [CmdletBinding( DefaultParameterSetName = 'asObject' )] [OutputType( [PSCustomObject], ParameterSetName = 'asObject' )] [OutputType( [PSObject], ParameterSetName = 'asValue' )] [OutputType( [Hashtable], ParameterSetName = 'asHashTable' )] param( [Parameter( ValueFromPipeline, ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [SupportsWildcards()] [ArgumentCompleter( { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) $command = "Get-Configuration" $module = (Get-command -Name $commandName).Module $commandName = $module.ExportedCommands.Keys | Where-Object {$_ -like ($command -replace "-", "-$($module.Prefix)")} & $commandName | Where-Object { $_.Name -like "$wordToComplete*" } | ForEach-Object { [System.Management.Automation.CompletionResult]::new( $_.Name, $_.Name, [System.Management.Automation.CompletionResultType]::ParameterValue, $_.Name ) } } )] [String[]] $Name = '*', [Parameter( Mandatory, ParameterSetName = 'asValue' )] [Switch] $ValueOnly, [Parameter( Mandatory, ParameterSetName = 'asHashtable' )] [Switch] $AsHashtable ) begin { Write-Verbose "Function started" } process { Write-DebugMessage "ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "PSBoundParameters: $($PSBoundParameters | Out-String)" $data = @{} foreach ($_name in $Name) { Write-Verbose "Filtering for [name = $_name]" foreach ($key in ($script:Configuration.Keys | Where-Object { $_ -like $_name })) { Write-DebugMessage "Found [key = $key]" $data[$key] = $script:Configuration[$key] } } if ($AsHashtable) { $data } elseif ($ValueOnly) { $data.Values } else { foreach ($key in $data.Keys) { New-Object -TypeName PSCustomObject -Property @{ Name = $key; Value = $data[$key] } } } } end { Write-Verbose "Function ended" } } #endregion Get-Configuration #region Get-ServerConfiguration function Get-ServerConfiguration { # .ExternalHelp ..\AtlassianPS.Configuration-help.xml [CmdletBinding( DefaultParameterSetName = '_All' )] [OutputType( [AtlassianPS.ServerData] )] param( [Parameter( Position = 0, Mandatory, ParameterSetName = 'ServerDataByUri' )] [ArgumentCompleter( { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) $command = "Get-ServerConfiguration" $module = (Get-command -Name $commandName).Module $commandName = $module.ExportedCommands.Keys | Where-Object {$_ -like ($command -replace "-", "-$($module.Prefix)")} & $commandName | Where-Object { $_.Name -like "$wordToComplete*" } | ForEach-Object { [System.Management.Automation.CompletionResult]::new( $_.Name, $_.Name, [System.Management.Automation.CompletionResultType]::ParameterValue, $_.Name ) } } )] [Alias('Url', 'Address')] [Uri] $Uri, [Parameter( Position = 0, Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName, ParameterSetName = 'ServerDataByName' )] [ArgumentCompleter( { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) $command = "Get-ServerConfiguration" $module = (Get-command -Name $commandName).Module $commandName = $module.ExportedCommands.Keys | Where-Object {$_ -like ($command -replace "-", "-$($module.Prefix)")} & $commandName | Where-Object { $_.Uri -like "$wordToComplete*" } | ForEach-Object { [System.Management.Automation.CompletionResult]::new( $_.Name, $_.Name, [System.Management.Automation.CompletionResultType]::ParameterValue, $_.Name ) } } )] [Alias('ServerName', 'Alias')] [String[]] $Name ) begin { Write-Verbose "Function started" $serverList = Get-Configuration -Name ServerList -ValueOnly } process { Write-DebugMessage "ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "PSBoundParameters: $($PSBoundParameters | Out-String)" switch ($PsCmdlet.ParameterSetName) { 'ServerDataByName' { Write-Verbose "Filtering ServerList for [Name = $Name]" $serverList | Where-Object { $_.Name -in $Name } } 'ServerDataByUri' { Write-Verbose "Filtering ServerList for [URI = $Uri]" $serverList | Where-Object { $_.Uri -like $Uri } } '_All' { $serverList } } } end { Write-Verbose "Function ended" } } #endregion Get-ServerConfiguration #region Remove-Configuration function Remove-Configuration { # .ExternalHelp ..\AtlassianPS.Configuration-help.xml [CmdletBinding( ConfirmImpact = 'Low', SupportsShouldProcess = $false )] [OutputType( [void] )] [System.Diagnostics.CodeAnalysis.SuppressMessage( 'PSUseShouldProcessForStateChangingFunctions', '' )] param( [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [ArgumentCompleter( { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) $command = "Get-Configuration" $module = (Get-command -Name $commandName).Module $commandName = $module.ExportedCommands.Keys | Where-Object {$_ -like ($command -replace "-", "-$($module.Prefix)")} & $commandName | Where-Object { $_.Name -like "$wordToComplete*" } | ForEach-Object { [System.Management.Automation.CompletionResult]::new( $_.Name, $_.Name, [System.Management.Automation.CompletionResultType]::ParameterValue, $_.Name ) } } )] [String[]] $Name ) begin { Write-Verbose "Function started" } process { Write-DebugMessage "ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "PSBoundParameters: $($PSBoundParameters | Out-String)" foreach ($_name in $Name) { Write-Verbose "Filtering for [name = $_name]" $script:Configuration.Remove($_name) } } end { Save-Configuration Write-Verbose "Function ended" } } #endregion Remove-Configuration #region Remove-ServerConfiguration function Remove-ServerConfiguration { # .ExternalHelp ..\AtlassianPS.Configuration-help.xml [CmdletBinding( ConfirmImpact = 'Low', SupportsShouldProcess = $false )] [OutputType( [void] )] [System.Diagnostics.CodeAnalysis.SuppressMessage('PSUseShouldProcessForStateChangingFunctions', '')] param( [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [ArgumentCompleter( { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) $commandName = (Get-Command -Module "AtlassianPS.Configuration" -Name "Get-*ServerConfiguration").Name & $commandName | Where-Object { $_.Name -like "$wordToComplete*" } | ForEach-Object { [System.Management.Automation.CompletionResult]::new( $_.Name, $_.Name, [System.Management.Automation.CompletionResultType]::ParameterValue, $_.Name ) } } )] [Alias('ServerName', 'Alias')] [String[]] $Name ) begin { Write-Verbose "Function started" $serverList = Get-ServerConfiguration } process { Write-DebugMessage "ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "PSBoundParameters: $($PSBoundParameters | Out-String)" foreach ($serverToRemove in $Name) { if ($serverToRemove -notin $serverList.Name) { $writeErrorSplat = @{ ExceptionType = "System.ApplicationException" ErrorId = "AtlassianPS.ServerData.ServerNotFound" Category = "ObjectNotFound" Message = "No server '$serverToRemove' could be found." TargetObject = $serverToRemove Cmdlet = $PSCmdlet } WriteError @writeErrorSplat } } $serverList = $serverList | Where-Object { $_.Name -notin $Name } } end { Write-DebugMessage "Persisting ServerList" $script:Configuration.ServerList = $serverList Save-Configuration Write-Verbose "Function ended" } } #endregion Remove-ServerConfiguration #region Set-Configuration function Set-Configuration { # .ExternalHelp ..\AtlassianPS.Configuration-help.xml [CmdletBinding( ConfirmImpact = 'Low', SupportsShouldProcess = $false )] [OutputType( [PSCustomObject] )] [System.Diagnostics.CodeAnalysis.SuppressMessage( 'PSUseShouldProcessForStateChangingFunctions', '' )] param( [Parameter( Mandatory, ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [ArgumentCompleter( { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameter) $command = "Get-Configuration" $module = (Get-command -Name $commandName).Module $commandName = $module.ExportedCommands.Keys | Where-Object {$_ -like ($command -replace "-", "-$($module.Prefix)")} & $commandName | Where-Object { $_.Name -like "$wordToComplete*" } | ForEach-Object { [System.Management.Automation.CompletionResult]::new( $_.Name, $_.Name, [System.Management.Automation.CompletionResultType]::ParameterValue, $_.Name ) } } )] [String] $Name, [Parameter( ValueFromPipelineByPropertyName )] [AllowNull()] [AllowEmptyCollection()] [AllowEmptyString()] [Object] $Value, [Switch] $Append, [Switch] $Passthru ) begin { Write-Verbose "Function started" } process { Write-DebugMessage "ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "PSBoundParameters: $($PSBoundParameters | Out-String)" If ($Append) { Write-Verbose "Appending to existing value" $oldValue = (Get-Configuration -Name $Name -ValueOnly) try { $newValue = @(@($oldValue) + @($Value)) -as ($oldValue.GetType()) if (-not $newValue) { throw "failed to case to $($oldValue.GetType().Name)" } } catch { Write-DebugMessage $_ $newValue = @(@($oldValue) + @($Value)) } $Value = $newValue } if ($Value) { $dataType = $Value.GetType().Name } else { $dataType = "null" } Write-Verbose "Storing value [$dataType] to [name = $Name]" $script:Configuration.Remove($Name) $script:Configuration.Add($Name, $Value) if ($Passthru) { Get-Configuration -Name $Name } } end { Save-Configuration Write-Verbose "Function ended" } } #endregion Set-Configuration #region Set-ServerConfiguration function Set-ServerConfiguration { # .ExternalHelp ..\AtlassianPS.Configuration-help.xml [CmdletBinding( ConfirmImpact = 'Low', SupportsShouldProcess = $false )] [OutputType( [void] )] [System.Diagnostics.CodeAnalysis.SuppressMessage('PSUseShouldProcessForStateChangingFunctions', '')] param( [Parameter( Mandatory, ValueFromPipeline, ValueFromPipelineByPropertyName )] [UInt32] $Id, [Parameter()] [ValidateNotNullOrEmpty()] [Alias('Url', 'Address')] [Uri] $Uri, [Parameter()] [ValidateNotNullOrEmpty()] [Alias('ServerName', 'Alias')] [String] $Name = $Uri.Authority, [Parameter()] [ValidateNotNullOrEmpty()] [AtlassianPS.ServerType] $Type, [Parameter()] [Microsoft.PowerShell.Commands.WebRequestSession] $Session, [Parameter()] [Hashtable] $Headers ) begin { Write-Verbose "Function started" $parametersToIgnore = @( 'Id' 'Verbose' 'Debug' 'ErrorAction' 'WarningAction' 'InformationAction' 'ErrorVariable' 'WarningVariable' 'InformationVariable' 'OutVariable' 'OutBuffer' 'PipelineVariable' 'WhatIf' 'Confirm' ) } process { Write-DebugMessage "ParameterSetName: $($PsCmdlet.ParameterSetName)" Write-DebugMessage "PSBoundParameters: $($PSBoundParameters | Out-String)" $serverEntry = Get-ServerConfiguration | Where-Object { $_.Id -eq $Id } if ($serverEntry) { foreach ($property in ($PSBoundParameters.Keys | Where-Object { $_ -notin $parametersToIgnore} )) { Write-Verbose "Changing [$property] of entry #$Id" $serverEntry.$property = Get-Variable $property -ValueOnly } } else { $writeErrorSplat = @{ ExceptionType = "System.ApplicationException" Message = "No entry could be found at index $Id" ErrorId = "AtlassianPS.ServerData.NoEntryExists" Category = "InvalidData" TargetObject = $Id } WriteError @writeErrorSplat } } end { Save-Configuration Write-Verbose "Function ended" } } #endregion Set-ServerConfiguration #region ConvertTo-Hashtable function ConvertTo-HashTable { <# .SYNOPSIS Converts a PSCustomObject to Hashtable .DESCRIPTION PowerShell v4 on Windows 8.1 seems to have trouble casting [PSCustomObject] to custom classes. This function is a workaround, as casting from [Hashtable] is no problem. #> [CmdletBinding()] [OutputType( [Hashtable] )] param( # Object to convert [Parameter( Mandatory, ValueFromPipeline )] [PSCustomObject] $InputObject ) process { $hash = @{} $InputObject.PSObject.Properties | Foreach-Object { $hash[$_.Name] = $_.Value } $hash } } #endregion ConvertTo-Hashtable #region Get-BreadCrumb function Get-BreadCrumb { param( [String]$Delimiter = " > " ) $depth = 1 $path = New-Object -TypeName System.Collections.ArrayList while ($depth) { try { $null = $path.Add((Get-Variable MyInvocation -Scope $depth -ValueOnly).MyCommand.Name) $depth++ } catch { $depth = 0 } } $path.Remove("") $path -join $Delimiter } #endregion Get-BreadCrumb #region Import-MqcnAlias function Import-MqcnAlias { <# .SYNOPSIS Create an alias for a full command name .DESCRIPTION Create an alias for a full command name This can be used to create a mockable call to a full command name .EXAMPLE Import-MqcnAlias -Alias "GetItem" -Command Microsoft.PowerShell.Management\Get-Item --------- Description Create an alias "GetItem" for the normal Get-Item #> [CmdletBinding()] param( # Name of the alias to be used [Parameter( Mandatory )] [String] $Alias, # Name of the command for which to create the alias [Parameter( Mandatory )] [String] $Command ) begin { Set-Alias -Name $Alias -Value $Command -Scope 1 } } #endregion Import-MqcnAlias #region Invoke-WebRequest function Invoke-WebRequest { # For Version up to 5.1 <# .ForwardHelpTargetName Microsoft.PowerShell.Utility\Invoke-WebRequest .ForwardHelpCategory Cmdlet #> [CmdletBinding(HelpUri = 'https://go.microsoft.com/fwlink/?LinkID=217035')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute( "PSAvoidUsingConvertToSecureStringWithPlainText", "", Justification = "Converting received plaintext token to SecureString" )] param( [switch] ${UseBasicParsing}, [Parameter(Mandatory = $true, Position = 0)] [ValidateNotNullOrEmpty()] [uri] ${Uri}, [Microsoft.PowerShell.Commands.WebRequestSession] ${WebSession}, [Alias('SV')] [string] ${SessionVariable}, [pscredential] [System.Management.Automation.CredentialAttribute()] ${Credential} = [System.Management.Automation.PSCredential]::Empty, [switch] ${UseDefaultCredentials}, [ValidateNotNullOrEmpty()] [string] ${CertificateThumbprint}, [ValidateNotNull()] [System.Security.Cryptography.X509Certificates.X509Certificate] ${Certificate}, [string] ${UserAgent}, [switch] ${DisableKeepAlive}, [ValidateRange(0, 2147483647)] [int32] ${TimeoutSec}, [System.Collections.IDictionary] ${Headers}, [ValidateRange(0, 2147483647)] [int] ${MaximumRedirection}, [Microsoft.PowerShell.Commands.WebRequestMethod] ${Method}, [uri] ${Proxy}, [pscredential] [System.Management.Automation.CredentialAttribute()] ${ProxyCredential} = [System.Management.Automation.PSCredential]::Empty, [switch] ${ProxyUseDefaultCredentials}, [Parameter(ValueFromPipeline = $true)] [System.Object] ${Body}, [string] ${ContentType}, [ValidateSet('chunked', 'compress', 'deflate', 'gzip', 'identity')] [string] ${TransferEncoding}, [string] ${InFile}, [string] ${OutFile}, [switch] ${PassThru}) begin { if ($Credential) { $SecureCreds = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes( $('{0}:{1}' -f $Credential.UserName, $Credential.GetNetworkCredential().Password) )) $Headers["Authorization"] = "Basic $($SecureCreds)" $PSBoundParameters.Remove("Credential") } if ($InFile) { $boundary = [System.Guid]::NewGuid().ToString() $enc = [System.Text.Encoding]::GetEncoding("iso-8859-1") $fileName = Split-Path -Path $InFile -Leaf $readFile = Get-Content -Path $InFile -Encoding Byte $fileEnc = $enc.GetString($readFile) $PSBoundParameters["Body"] = @' --{0} Content-Disposition: form-data; name="file"; filename="{1}" Content-Type: application/octet-stream {2} --{0}-- '@ -f $boundary, $fileName, $fileEnc $PSBoundParameters["Headers"]['X-Atlassian-Token'] = 'nocheck' $PSBoundParameters["ContentType"] = "multipart/form-data; boundary=`"$boundary`"" $null = $PSBoundParameters.Remove("InFile") } try { $outBuffer = $null if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) { $PSBoundParameters['OutBuffer'] = 1 } $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Utility\Invoke-WebRequest', [System.Management.Automation.CommandTypes]::Cmdlet) $scriptCmd = {& $wrappedCmd @PSBoundParameters } $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin) $steppablePipeline.Begin($PSCmdlet) } catch { throw } } process { try { $steppablePipeline.Process($_) if ($SessionVariable) { Set-Variable -Name $SessionVariable -Value (Get-Variable $SessionVariable).Value -Scope 1 } } catch { throw } } end { try { $steppablePipeline.End() } catch { throw } } } if ($PSVersionTable.PSVersion.Major -ge 6) { function Invoke-WebRequest { #require -Version 6 <# .ForwardHelpTargetName Microsoft.PowerShell.Utility\Invoke-WebRequest .ForwardHelpCategory Cmdlet #> [CmdletBinding(DefaultParameterSetName = 'StandardMethod', HelpUri = 'https://go.microsoft.com/fwlink/?LinkID=217035')] param( [switch] ${UseBasicParsing}, [Parameter(Mandatory = $true, Position = 0)] [ValidateNotNullOrEmpty()] [uri] ${Uri}, [Microsoft.PowerShell.Commands.WebRequestSession] ${WebSession}, [Alias('SV')] [string] ${SessionVariable}, [switch] ${AllowUnencryptedAuthentication}, [Microsoft.PowerShell.Commands.WebAuthenticationType] ${Authentication}, [pscredential] [System.Management.Automation.CredentialAttribute()] ${Credential}, [switch] ${UseDefaultCredentials}, [ValidateNotNullOrEmpty()] [string] ${CertificateThumbprint}, [ValidateNotNull()] [X509Certificate] ${Certificate}, [switch] ${SkipCertificateCheck}, [Microsoft.PowerShell.Commands.WebSslProtocol] ${SslProtocol}, [securestring] ${Token}, [string] ${UserAgent}, [switch] ${DisableKeepAlive}, [ValidateRange(0, 2147483647)] [int32] ${TimeoutSec}, [System.Collections.IDictionary] ${Headers}, [ValidateRange(0, 2147483647)] [int] ${MaximumRedirection}, [Parameter(ParameterSetName = 'StandardMethod')] [Parameter(ParameterSetName = 'StandardMethodNoProxy')] [Microsoft.PowerShell.Commands.WebRequestMethod] ${Method}, [Parameter(ParameterSetName = 'CustomMethod', Mandatory = $true)] [Parameter(ParameterSetName = 'CustomMethodNoProxy', Mandatory = $true)] [Alias('CM')] [ValidateNotNullOrEmpty()] [string] ${CustomMethod}, [Parameter(ParameterSetName = 'CustomMethodNoProxy', Mandatory = $true)] [Parameter(ParameterSetName = 'StandardMethodNoProxy', Mandatory = $true)] [switch] ${NoProxy}, [Parameter(ParameterSetName = 'StandardMethod')] [Parameter(ParameterSetName = 'CustomMethod')] [uri] ${Proxy}, [Parameter(ParameterSetName = 'StandardMethod')] [Parameter(ParameterSetName = 'CustomMethod')] [pscredential] [System.Management.Automation.CredentialAttribute()] ${ProxyCredential}, [Parameter(ParameterSetName = 'StandardMethod')] [Parameter(ParameterSetName = 'CustomMethod')] [switch] ${ProxyUseDefaultCredentials}, [Parameter(ValueFromPipeline = $true)] [System.Object] ${Body}, [string] ${ContentType}, [ValidateSet('chunked', 'compress', 'deflate', 'gzip', 'identity')] [string] ${TransferEncoding}, [string] ${InFile}, [string] ${OutFile}, [switch] ${PassThru}, [switch] ${PreserveAuthorizationOnRedirect}, [switch] ${SkipHeaderValidation}) begin { if ($Credential -and (-not ($Authentication))) { $PSBoundParameters["Authentication"] = "Basic" } if ($InFile) { $multipartContent = [System.Net.Http.MultipartFormDataContent]::new() $FileStream = [System.IO.FileStream]::new($InFile, [System.IO.FileMode]::Open) $fileHeader = [System.Net.Http.Headers.ContentDispositionHeaderValue]::new("form-data") $fileHeader.Name = "file" $fileHeader.FileName = ([System.io.FileInfo]$InFile).name $fileContent = [System.Net.Http.StreamContent]::new($FileStream) $fileContent.Headers.ContentDisposition = $fileHeader $fileContent.Headers.ContentType = [System.Net.Http.Headers.MediaTypeHeaderValue]::Parse("application/octet-stream") $multipartContent.Add($fileContent) $PSBoundParameters["Headers"]['X-Atlassian-Token'] = 'nocheck' $PSBoundParameters["Body"] = $multipartContent $null = $PSBoundParameters.Remove("InFile") } try { $outBuffer = $null if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer)) { $PSBoundParameters['OutBuffer'] = 1 } $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Microsoft.PowerShell.Utility\Invoke-WebRequest', [System.Management.Automation.CommandTypes]::Cmdlet) $scriptCmd = {& $wrappedCmd @PSBoundParameters } $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin) $steppablePipeline.Begin($PSCmdlet) } catch { throw } } process { try { $steppablePipeline.Process($_) if ($SessionVariable) { Set-Variable -Name $SessionVariable -Value (Get-Variable $SessionVariable).Value -Scope 1 } } catch { throw } } end { try { $steppablePipeline.End() } catch { throw } } } } #endregion Invoke-WebRequest #region Save-Configuration function Save-Configuration { [CmdletBinding()] param() begin { Write-Verbose "Function started" Import-MqcnAlias -Alias "ExportConfiguration" -Command "Configuration\Export-Configuration" $export = Get-Configuration -AsHashtable $export["ServerList"] | Where-Object { $_.Session } | Foreach-Object { $_.Session = $null } ExportConfiguration -InputObject $export 3>$null Write-Verbose "Function ended" } } #endregion Save-Configuration #region ThrowError function ThrowError { <# .SYNOPSIS Utility to throw a terminating errorrecord .NOTES Thanks to Jaykul: https://github.com/PoshCode/Configuration/blob/master/Source/Metadata.psm1 #> param ( [Parameter()] [ValidateNotNullOrEmpty()] [System.Management.Automation.PSCmdlet] $Cmdlet = $((Get-Variable -Scope 1 PSCmdlet).Value), [Parameter(Mandatory = $true, ParameterSetName = "ExistingException", Position = 1, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Parameter(ParameterSetName = "NewException")] [ValidateNotNullOrEmpty()] [System.Exception] $Exception, [Parameter(ParameterSetName = "NewException", Position = 2)] [ValidateNotNullOrEmpty()] [System.String] $ExceptionType = "System.Management.Automation.RuntimeException", [Parameter(Mandatory = $true, ParameterSetName = "NewException", Position = 3)] [ValidateNotNullOrEmpty()] [System.String] $Message, [Parameter(Mandatory = $false)] [System.Object] $TargetObject, [Parameter(Mandatory = $true, ParameterSetName = "ExistingException", Position = 10)] [Parameter(Mandatory = $true, ParameterSetName = "NewException", Position = 10)] [ValidateNotNullOrEmpty()] [System.String] $ErrorId, [Parameter(Mandatory = $true, ParameterSetName = "ExistingException", Position = 11)] [Parameter(Mandatory = $true, ParameterSetName = "NewException", Position = 11)] [ValidateNotNull()] [System.Management.Automation.ErrorCategory] $Category, [Parameter(Mandatory = $true, ParameterSetName = "Rethrow", Position = 1)] [System.Management.Automation.ErrorRecord]$ErrorRecord ) process { if (!$ErrorRecord) { if ($PSCmdlet.ParameterSetName -eq "NewException") { if ($Exception) { $Exception = New-Object $ExceptionType $Message, $Exception } else { $Exception = New-Object $ExceptionType $Message } } $errorRecord = New-Object System.Management.Automation.ErrorRecord $Exception, $ErrorId, $Category, $TargetObject } $Cmdlet.ThrowTerminatingError($errorRecord) } } #endregion ThrowError #region Write-DebugMessage function Write-DebugMessage { <# .SYNOPSIS Write a message to the debug stream without creating a breakpoint .DESCRIPTION Write a message to the debug stream without creating a breakpoint This function allows the user to decide how the Debug Message should be formatted. The configuration is inside `$scrpit:Configuration` and supports the following structure (json representation): { "message": { // show a line with the Bread Crumbs of the caller stack "breadcrumbs": true, // how many whitespaces should be used for indenting the // message "indent": true, // show the name of the calling function - this is ignored // if breadcrumbs is active "functionname": true, // show the timestamp (HH:mm:ss format) of the message "timestamp": true } } .EXAMPLE Write-DebugMessage "The value of `$var is: $var" ---------- Description Shows the message if the user added `-Debug` to the command but does not create a breakpoint #> [CmdletBinding()] param( [Parameter( Mandatory, ValueFromPipeline )] [String] $Message, [Switch] $BreakPoint, [Parameter()] [ValidateNotNullOrEmpty()] [System.Management.Automation.PSCmdlet] $Cmdlet = ((Get-Variable -Scope 1 PSCmdlet).Value) ) begin { $indent, $functionName, $timeStamp = "" Import-MqcnAlias -Alias "WriteDebug" -Command "Microsoft.PowerShell.Utility\Write-Debug" $messageSettings = $script:Configuration["Message"] if (-not $BreakPoint) { $oldDebugPreference = $DebugPreference if (-not ($DebugPreference -eq "SilentlyContinue")) { $DebugPreference = 'Continue' } } } process { if ((Get-PSCallstack | Select-Object -Last 1 -Skip 1).Arguments.Contains("Debug")) { $DebugPreference = 'Continue' } if ($messageSettings.Breadcrumbs) { WriteDebug "[$(Get-BreadCrumb)]:" if ($messageSettings.Indent) { $indent = " " * $messageSettings.Indent } else { $indent = " " * 4 } } else { if ($messageSettings.FunctionName) { $functionName = "[$($Cmdlet.MyInvocation.MyCommand.Name)] " } } if ($messageSettings.Timestamp) { $timeStamp = "[$(Get-Date -f "HH:mm:ss")] " } WriteDebug ("{0}{1}{2}{3}" -f $timeStamp, $functionName, $indent, $Message) } end { $DebugPreference = $oldDebugPreference } } #endregion Write-DebugMessage #region Write-Verbose function Write-Verbose { <# .SYNOPSIS Write a verbose message .DESCRIPTION Write a verbose message This function allows the user to decide how the Verbose Message should be formatted. The configuration is inside `$scrpit:Configuration` and supports the following structure (json representation): { "message": { // show a line with the Bread Crumbs of the caller stack "breadcrumbs": true, // how many whitespaces should be used for indenting the // message "indent": true, // show the name of the calling function - this is ignored // if breadcrumbs is active "functionname": true, // show the timestamp (HH:mm:ss format) of the message "timestamp": true } } .EXAMPLE Write-DebugMessage "The value of `$var is: $var" ---------- Description Shows the message if the user added `-Debug` to the command but does not create a breakpoint #> [CmdletBinding()] param( [Parameter( Mandatory, ValueFromPipeline )] [String] $Message, [Parameter()] [ValidateNotNullOrEmpty()] [System.Management.Automation.PSCmdlet] $Cmdlet = ((Get-Variable -Scope 1 PSCmdlet).Value) ) begin { $indent, $functionName, $timeStamp = "" Import-MqcnAlias -Alias "WriteVerbose" -Command "Microsoft.PowerShell.Utility\Write-Verbose" $messageSettings = $script:Configuration["Message"] } process { if ((Get-PSCallstack | Select-Object -Last 1 -Skip 1).Arguments.Contains("Verbose")) { $VerbosePreference = 'Continue' } if ($messageSettings.Breadcrumbs) { WriteVerbose "[$(Get-BreadCrumb)]:" if ($messageSettings.Indent) { $indent = " " * $messageSettings.Indent } else { $indent = " " * 4 } } else { if ($messageSettings.FunctionName) { $functionName = "[$($Cmdlet.MyInvocation.MyCommand.Name)] " } } if ($messageSettings.Timestamp) { $timeStamp = "[$(Get-Date -f "HH:mm:ss")] " } WriteVerbose ("{0}{1}{2}{3}" -f $timeStamp, $functionName, $indent, $Message) } } #endregion Write-Verbose #region WriteError function WriteError { <# .SYNOPSIS Utility to write an errorrecord to the errstd .NOTES Thanks to Jaykul: https://github.com/PoshCode/Configuration/blob/master/Source/Metadata.psm1 #> param ( [Parameter()] [ValidateNotNullOrEmpty()] [System.Management.Automation.PSCmdlet] $Cmdlet = $((Get-Variable -Scope 1 PSCmdlet).Value), [Parameter(Mandatory = $true, ParameterSetName = "ExistingException", Position = 1, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [Parameter(ParameterSetName = "NewException")] [ValidateNotNullOrEmpty()] [System.Exception] $Exception, [Parameter(ParameterSetName = "NewException", Position = 2)] [ValidateNotNullOrEmpty()] [System.String] $ExceptionType = "System.Management.Automation.RuntimeException", [Parameter(Mandatory = $true, ParameterSetName = "NewException", Position = 3)] [ValidateNotNullOrEmpty()] [System.String] $Message, [Parameter(Mandatory = $false)] [System.Object] $TargetObject, [Parameter(Mandatory = $true, Position = 10)] [ValidateNotNullOrEmpty()] [System.String] $ErrorId, [Parameter(Mandatory = $true, Position = 11)] [ValidateNotNull()] [System.Management.Automation.ErrorCategory] $Category, [Parameter(Mandatory = $true, ParameterSetName = "Rethrow", Position = 1)] [System.Management.Automation.ErrorRecord]$ErrorRecord ) process { if (!$ErrorRecord) { if ($PSCmdlet.ParameterSetName -eq "NewException") { if ($Exception) { $Exception = New-Object $ExceptionType $Message, $Exception } else { $Exception = New-Object $ExceptionType $Message } } $errorRecord = New-Object System.Management.Automation.ErrorRecord $Exception, $ErrorId, $Category, $TargetObject } $Cmdlet.WriteError($errorRecord) } } #endregion WriteError #endregion LoadFunctions # Load configuration using # https://github.com/PoshCode/Configuration [Hashtable]$script:Configuration = Import-Configuration -CompanyName "AtlassianPS" -Name "AtlassianPS.Configuration" if (-not $script:Configuration) { $script:Configuration = @{} } if (-not $script:Configuration.ContainsKey("ServerList")) { $script:Configuration.Add("ServerList",[System.Collections.Generic.List[AtlassianPS.ServerData]]::new()) } #endregion ModuleConfig |