Support/Package/Lifecycle/Eigenverft.Manifested.Package.Package.DependencyPlan.ps1
|
<#
Eigenverft.Manifested.Package.Package.DependencyPlan #> function New-PackageDependencyPlanViolation { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$Reason, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$Message, [AllowNull()] [string]$RootDefinitionId = $null, [AllowNull()] [string]$ParentNodeKey = $null, [AllowNull()] [string]$NodeKey = $null, [AllowNull()] [string]$PublisherId = $null, [AllowNull()] [string]$DefinitionId = $null, [AllowNull()] [string]$VersionRange = $null ) return [pscustomobject]@{ Reason = $Reason Message = $Message RootDefinitionId = $RootDefinitionId ParentNodeKey = $ParentNodeKey NodeKey = $NodeKey PublisherId = $PublisherId DefinitionId = $DefinitionId VersionRange = $VersionRange } } function Add-PackageDependencyPlanViolation { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$Plan, [Parameter(Mandatory = $true)] [psobject]$Violation ) $Plan.Violations.Add($Violation) | Out-Null $Plan.Accepted = $false $Plan.Status = 'Failed' return $Violation } function Join-PackageDependencyVersionRanges { [CmdletBinding()] param( [AllowNull()] [object[]]$VersionRanges ) $ranges = @( foreach ($range in @($VersionRanges)) { if (-not [string]::IsNullOrWhiteSpace([string]$range)) { ([string]$range).Trim() } } ) | Select-Object -Unique if ($ranges.Count -eq 0) { return $null } return ($ranges -join ' ') } function ConvertTo-PackageDependencyPlanArray { [CmdletBinding()] param( [AllowNull()] [object]$Value ) if ($null -eq $Value) { return @() } if ($Value.PSObject.Methods['ToArray']) { return @($Value.ToArray()) } return @($Value) } function Get-PackageDependencyPlanNode { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$Plan, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$NodeKey ) if ($Plan.NodeMap.ContainsKey($NodeKey)) { return $Plan.NodeMap[$NodeKey] } return $null } function Get-PackageDependencyPlanRootNodeKey { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$Plan, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$DefinitionId ) foreach ($root in @(ConvertTo-PackageDependencyPlanArray -Value $Plan.Roots)) { if ([string]::Equals([string]$root.RequestedDefinitionId, $DefinitionId, [System.StringComparison]::OrdinalIgnoreCase)) { return [string]$root.NodeKey } } return $null } function Get-PackageDependencyPlanChildEdges { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$Plan, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$NodeKey ) if ($Plan.ChildrenByParentKey.ContainsKey($NodeKey)) { return @(ConvertTo-PackageDependencyPlanArray -Value $Plan.ChildrenByParentKey[$NodeKey]) } return @() } function Select-PackageDependencyPlanVerdict { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$Plan ) $roots = @(ConvertTo-PackageDependencyPlanArray -Value $Plan.Roots) $nodes = @(ConvertTo-PackageDependencyPlanArray -Value $Plan.Nodes) $edges = @(ConvertTo-PackageDependencyPlanArray -Value $Plan.Edges) $violations = @(ConvertTo-PackageDependencyPlanArray -Value $Plan.Violations) return [pscustomobject]@{ Status = [string]$Plan.Status Accepted = [bool]$Plan.Accepted RootCount = $roots.Count NodeCount = $nodes.Count EdgeCount = $edges.Count ViolationCount = $violations.Count Violations = @($violations) } } function Add-PackageDependencyPlanEdge { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$Plan, [Parameter(Mandatory = $true)] [psobject]$ParentNode, [Parameter(Mandatory = $true)] [psobject]$ChildNode, [AllowNull()] [string]$VersionRange = $null ) $edgeKey = '{0}|{1}|{2}' -f [string]$ParentNode.NodeKey, [string]$ChildNode.NodeKey, $(if ([string]::IsNullOrWhiteSpace($VersionRange)) { '<none>' } else { [string]$VersionRange }) if ($Plan.EdgeMap.ContainsKey($edgeKey)) { return $Plan.EdgeMap[$edgeKey] } $edge = [pscustomobject]@{ EdgeKey = $edgeKey ParentNodeKey = [string]$ParentNode.NodeKey ParentPublisherId = [string]$ParentNode.PublisherId ParentDefinitionId = [string]$ParentNode.DefinitionId ChildNodeKey = [string]$ChildNode.NodeKey PublisherId = [string]$ChildNode.PublisherId DefinitionId = [string]$ChildNode.DefinitionId VersionRange = if ([string]::IsNullOrWhiteSpace($VersionRange)) { $null } else { [string]$VersionRange } } $Plan.Edges.Add($edge) | Out-Null $Plan.EdgeMap[$edgeKey] = $edge if (-not $Plan.ChildrenByParentKey.ContainsKey([string]$ParentNode.NodeKey)) { $Plan.ChildrenByParentKey[[string]$ParentNode.NodeKey] = New-Object 'System.Collections.Generic.List[object]' } $Plan.ChildrenByParentKey[[string]$ParentNode.NodeKey].Add($edge) | Out-Null return $edge } function Resolve-PackageDependencyPlanNodeSelection { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$Context, [Parameter(Mandatory = $true)] [psobject]$Node ) $versionRange = Join-PackageDependencyVersionRanges -VersionRanges @($Node.IncomingVersionRanges) if (-not [string]::IsNullOrWhiteSpace($versionRange)) { try { $null = Resolve-PackageVersionRangeTerms -VersionRange $versionRange } catch { Add-PackageDependencyPlanViolation -Plan $Context.Plan -Violation (New-PackageDependencyPlanViolation -Reason 'DependencyVersionRangeInvalid' -Message $_.Exception.Message -RootDefinitionId $Context.RootDefinitionId -NodeKey ([string]$Node.NodeKey) -PublisherId ([string]$Node.PublisherId) -DefinitionId ([string]$Node.DefinitionId) -VersionRange $versionRange) | Out-Null return } } $packageVersionOverride = $null if ([bool]$Node.IsRoot -and [bool]$Context.PackageVersionOverrideSpecified) { $packageVersionOverride = [string]$Context.PackageVersion } try { $selectedPackage = Resolve-PackageEffectivePackage_1_9 -PackageConfig $Node.PackageConfig -PackageVersionOverride $packageVersionOverride -PackageVersionRange $versionRange } catch { $reason = if (-not [string]::IsNullOrWhiteSpace($versionRange) -and $_.Exception.Message -like '*versionRange*') { 'DependencyVersionRangeUnsatisfied' } else { 'DependencyPlanInvalid' } Add-PackageDependencyPlanViolation -Plan $Context.Plan -Violation (New-PackageDependencyPlanViolation -Reason $reason -Message $_.Exception.Message -RootDefinitionId $Context.RootDefinitionId -NodeKey ([string]$Node.NodeKey) -PublisherId ([string]$Node.PublisherId) -DefinitionId ([string]$Node.DefinitionId) -VersionRange $versionRange) | Out-Null return } $Node.Package = $selectedPackage $Node.PackageId = [string]$selectedPackage.id $Node.PackageVersion = [string]$selectedPackage.version $Node.VersionRange = $versionRange $Node.ReleaseTrack = [string]$selectedPackage.releaseTrack $Node.ArtifactDistributionVariant = [string]$selectedPackage.artifactDistributionVariant } function Resolve-PackageDependencyPolicyPublisherId { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$PolicyReference ) if ($PolicyReference.PSObject.Properties['publisherId'] -and -not [string]::IsNullOrWhiteSpace([string]$PolicyReference.publisherId)) { return [string]$PolicyReference.publisherId } return $null } function Find-PackageDependencyPlanMatchingNodes { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$Plan, [Parameter(Mandatory = $true)] [psobject]$PolicyReference ) $publisherId = Resolve-PackageDependencyPolicyPublisherId -PolicyReference $PolicyReference $definitionId = if ($PolicyReference.PSObject.Properties['definitionId']) { [string]$PolicyReference.definitionId } else { $null } $versionRange = if ($PolicyReference.PSObject.Properties['versionRange']) { [string]$PolicyReference.versionRange } else { $null } return @( foreach ($node in @(ConvertTo-PackageDependencyPlanArray -Value $Plan.Nodes)) { if ([string]::IsNullOrWhiteSpace($definitionId) -or -not [string]::Equals([string]$node.DefinitionId, $definitionId, [System.StringComparison]::OrdinalIgnoreCase)) { continue } if (-not [string]::IsNullOrWhiteSpace($publisherId) -and -not [string]::Equals([string]$node.PublisherId, $publisherId, [System.StringComparison]::OrdinalIgnoreCase)) { continue } if (-not [string]::IsNullOrWhiteSpace($versionRange) -and -not (Test-PackageVersionRange -VersionText ([string]$node.PackageVersion) -VersionRange $versionRange)) { continue } $node } ) } function Test-PackageDependencyInventoryContainsReference { [CmdletBinding()] [OutputType([bool])] param( [Parameter(Mandatory = $true)] [psobject]$PackageConfig, [Parameter(Mandatory = $true)] [psobject]$PolicyReference ) $definitionId = if ($PolicyReference.PSObject.Properties['definitionId']) { [string]$PolicyReference.definitionId } else { $null } if ([string]::IsNullOrWhiteSpace($definitionId)) { return $false } $publisherId = Resolve-PackageDependencyPolicyPublisherId -PolicyReference $PolicyReference $versionRange = if ($PolicyReference.PSObject.Properties['versionRange']) { [string]$PolicyReference.versionRange } else { $null } $inventory = Get-PackageInventory -PackageConfig $PackageConfig foreach ($record in @($inventory.Records)) { if (-not [string]::Equals([string]$record.definitionId, $definitionId, [System.StringComparison]::OrdinalIgnoreCase)) { continue } if (-not [string]::IsNullOrWhiteSpace($publisherId) -and $record.PSObject.Properties['definitionPublisherId'] -and -not [string]::Equals([string]$record.definitionPublisherId, $publisherId, [System.StringComparison]::OrdinalIgnoreCase)) { continue } if (-not [string]::IsNullOrWhiteSpace($versionRange) -and -not (Test-PackageVersionRange -VersionText ([string]$record.currentVersion) -VersionRange $versionRange)) { continue } return $true } return $false } function Test-PackageDependencyPlanPolicyReference { [CmdletBinding()] [OutputType([bool])] param( [Parameter(Mandatory = $true)] [psobject]$Plan, [Parameter(Mandatory = $true)] [psobject]$Node, [Parameter(Mandatory = $true)] [psobject]$PolicyReference, [Parameter(Mandatory = $true)] [ValidateSet('conflictsWith', 'requiresAbsent')] [string]$Kind ) if (-not $PolicyReference.PSObject.Properties['definitionId'] -or [string]::IsNullOrWhiteSpace([string]$PolicyReference.definitionId)) { Add-PackageDependencyPlanViolation -Plan $Plan -Violation (New-PackageDependencyPlanViolation -Reason 'DependencyPlanInvalid' -Message "Package definition '$($Node.DefinitionId)' dependency.policy.$Kind entry is missing definitionId." -NodeKey ([string]$Node.NodeKey) -PublisherId ([string]$Node.PublisherId) -DefinitionId ([string]$Node.DefinitionId)) | Out-Null return $false } if ($PolicyReference.PSObject.Properties['publisherId'] -and [string]::IsNullOrWhiteSpace([string]$PolicyReference.publisherId)) { Add-PackageDependencyPlanViolation -Plan $Plan -Violation (New-PackageDependencyPlanViolation -Reason 'DependencyPlanInvalid' -Message "Package definition '$($Node.DefinitionId)' dependency.policy.$Kind entry has empty publisherId." -NodeKey ([string]$Node.NodeKey) -PublisherId ([string]$Node.PublisherId) -DefinitionId ([string]$Node.DefinitionId)) | Out-Null return $false } if ($PolicyReference.PSObject.Properties['publisherId']) { Assert-PackagePublisherId -PublisherId ([string]$PolicyReference.publisherId) } if ($PolicyReference.PSObject.Properties['versionRange'] -and -not [string]::IsNullOrWhiteSpace([string]$PolicyReference.versionRange)) { try { $null = Resolve-PackageVersionRangeTerms -VersionRange ([string]$PolicyReference.versionRange) } catch { Add-PackageDependencyPlanViolation -Plan $Plan -Violation (New-PackageDependencyPlanViolation -Reason 'DependencyVersionRangeInvalid' -Message $_.Exception.Message -NodeKey ([string]$Node.NodeKey) -PublisherId ([string]$Node.PublisherId) -DefinitionId ([string]$Node.DefinitionId) -VersionRange ([string]$PolicyReference.versionRange)) | Out-Null return $false } } return $true } function Test-PackageDependencyPlanPeerPolicy { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$Plan ) foreach ($node in @(ConvertTo-PackageDependencyPlanArray -Value $Plan.Nodes)) { $definition = $node.PackageConfig.Definition $dependencyModel = Get-PackageDefinitionDependencyModel_1_9 -Definition $definition -DefinitionId ([string]$node.DefinitionId) foreach ($conflict in @($dependencyModel.ConflictsWith)) { if (-not (Test-PackageDependencyPlanPolicyReference -Plan $Plan -Node $node -PolicyReference $conflict -Kind 'conflictsWith')) { continue } foreach ($match in @(Find-PackageDependencyPlanMatchingNodes -Plan $Plan -PolicyReference $conflict)) { Add-PackageDependencyPlanViolation -Plan $Plan -Violation (New-PackageDependencyPlanViolation -Reason 'DependencyConflict' -Message ("Package definition '{0}' conflicts with planned package '{1}'." -f [string]$node.DefinitionId, [string]$match.DefinitionId) -NodeKey ([string]$node.NodeKey) -PublisherId ([string]$match.PublisherId) -DefinitionId ([string]$match.DefinitionId) -VersionRange $(if ($conflict.PSObject.Properties['versionRange']) { [string]$conflict.versionRange } else { $null })) | Out-Null } } foreach ($requiresAbsent in @($dependencyModel.RequiresAbsent)) { if (-not (Test-PackageDependencyPlanPolicyReference -Plan $Plan -Node $node -PolicyReference $requiresAbsent -Kind 'requiresAbsent')) { continue } $plannedMatches = @(Find-PackageDependencyPlanMatchingNodes -Plan $Plan -PolicyReference $requiresAbsent) if ($plannedMatches.Count -gt 0) { foreach ($match in @($plannedMatches)) { Add-PackageDependencyPlanViolation -Plan $Plan -Violation (New-PackageDependencyPlanViolation -Reason 'DependencyRequiresAbsent' -Message ("Package definition '{0}' requires package '{1}' to be absent, but it is in the approved plan." -f [string]$node.DefinitionId, [string]$match.DefinitionId) -NodeKey ([string]$node.NodeKey) -PublisherId ([string]$match.PublisherId) -DefinitionId ([string]$match.DefinitionId) -VersionRange $(if ($requiresAbsent.PSObject.Properties['versionRange']) { [string]$requiresAbsent.versionRange } else { $null })) | Out-Null } } if (Test-PackageDependencyInventoryContainsReference -PackageConfig $node.PackageConfig -PolicyReference $requiresAbsent) { Add-PackageDependencyPlanViolation -Plan $Plan -Violation (New-PackageDependencyPlanViolation -Reason 'DependencyRequiresAbsent' -Message ("Package definition '{0}' requires package '{1}' to be absent, but it is assigned locally." -f [string]$node.DefinitionId, [string]$requiresAbsent.definitionId) -NodeKey ([string]$node.NodeKey) -PublisherId $(Resolve-PackageDependencyPolicyPublisherId -PolicyReference $requiresAbsent) -DefinitionId ([string]$requiresAbsent.definitionId) -VersionRange $(if ($requiresAbsent.PSObject.Properties['versionRange']) { [string]$requiresAbsent.versionRange } else { $null })) | Out-Null } } } } function Resolve-PackageDependencyPlanNode { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$Context, [AllowNull()] [string]$PublisherId = $null, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string]$DefinitionId, [AllowNull()] [string]$ParentNodeKey = $null, [AllowNull()] [string]$VersionRange = $null, [object[]]$Stack = @(), [switch]$IsRoot ) try { $config = Get-PackageConfig -PublisherId $PublisherId -DefinitionId $DefinitionId -DesiredState 'Assigned' -AcceptUnknownSigningKey:([bool]$Context.AcceptUnknownSigningKey) } catch { Add-PackageDependencyPlanViolation -Plan $Context.Plan -Violation (New-PackageDependencyPlanViolation -Reason 'DependencyDefinitionNotFound' -Message $_.Exception.Message -RootDefinitionId $Context.RootDefinitionId -ParentNodeKey $ParentNodeKey -PublisherId $PublisherId -DefinitionId $DefinitionId -VersionRange $VersionRange) | Out-Null return $null } $resolvedPublisherId = [string]$config.DefinitionPublisherId $resolvedDefinitionId = [string]$config.DefinitionId $nodeKey = Get-PackageDependencyReferenceKey -PublisherId $resolvedPublisherId -DefinitionId $resolvedDefinitionId if (@($Stack) -contains $nodeKey) { Add-PackageDependencyPlanViolation -Plan $Context.Plan -Violation (New-PackageDependencyPlanViolation -Reason 'DependencyCycle' -Message ("Package dependency cycle detected: {0} -> {1}." -f ((@($Stack) -join ' -> ')), $nodeKey) -RootDefinitionId $Context.RootDefinitionId -ParentNodeKey $ParentNodeKey -NodeKey $nodeKey -PublisherId $resolvedPublisherId -DefinitionId $resolvedDefinitionId -VersionRange $VersionRange) | Out-Null return $null } $node = $null if ($Context.Plan.NodeMap.ContainsKey($nodeKey)) { $node = $Context.Plan.NodeMap[$nodeKey] if (-not [string]::IsNullOrWhiteSpace($VersionRange) -and -not $node.IncomingVersionRanges.Contains([string]$VersionRange)) { $node.IncomingVersionRanges.Add([string]$VersionRange) | Out-Null Resolve-PackageDependencyPlanNodeSelection -Context $Context -Node $node } return $node } $incomingRanges = New-Object 'System.Collections.Generic.List[string]' if (-not [string]::IsNullOrWhiteSpace($VersionRange)) { $incomingRanges.Add([string]$VersionRange) | Out-Null } $node = [pscustomobject]@{ NodeKey = $nodeKey PublisherId = $resolvedPublisherId DefinitionId = $resolvedDefinitionId DefinitionRevision = $config.DefinitionRevision DefinitionEndpointName = $config.DefinitionEndpointName IsRoot = [bool]$IsRoot PackageConfig = $config IncomingVersionRanges = $incomingRanges VersionRange = $null Package = $null PackageId = $null PackageVersion = $null ReleaseTrack = $null ArtifactDistributionVariant = $null } $Context.Plan.NodeMap[$nodeKey] = $node $Context.Plan.Nodes.Add($node) | Out-Null Resolve-PackageDependencyPlanNodeSelection -Context $Context -Node $node $definition = $config.Definition $dependencyModel = Get-PackageDefinitionDependencyModel_1_9 -Definition $definition -DefinitionId $resolvedDefinitionId $nextStack = @($Stack) + $nodeKey foreach ($dependency in @($dependencyModel.Requires)) { if ($null -eq $dependency) { continue } if (-not $dependency.PSObject.Properties['definitionId'] -or [string]::IsNullOrWhiteSpace([string]$dependency.definitionId)) { Add-PackageDependencyPlanViolation -Plan $Context.Plan -Violation (New-PackageDependencyPlanViolation -Reason 'DependencyPlanInvalid' -Message "Package definition '$resolvedDefinitionId' has dependency without definitionId." -RootDefinitionId $Context.RootDefinitionId -ParentNodeKey $nodeKey -NodeKey $nodeKey -PublisherId $resolvedPublisherId -DefinitionId $resolvedDefinitionId) | Out-Null continue } try { $dependencyPublisherId = Resolve-PackageDependencyPublisherId -PackageResult ([pscustomobject]@{ DefinitionPublisherId = $resolvedPublisherId; PackageConfig = $config }) -Dependency $dependency } catch { Add-PackageDependencyPlanViolation -Plan $Context.Plan -Violation (New-PackageDependencyPlanViolation -Reason 'DependencyPlanInvalid' -Message $_.Exception.Message -RootDefinitionId $Context.RootDefinitionId -ParentNodeKey $nodeKey -NodeKey $nodeKey -PublisherId $resolvedPublisherId -DefinitionId $resolvedDefinitionId) | Out-Null continue } $dependencyVersionRange = if ($dependency.PSObject.Properties['versionRange'] -and -not [string]::IsNullOrWhiteSpace([string]$dependency.versionRange)) { [string]$dependency.versionRange } else { $null } $child = Resolve-PackageDependencyPlanNode -Context $Context -PublisherId $dependencyPublisherId -DefinitionId ([string]$dependency.definitionId) -ParentNodeKey $nodeKey -VersionRange $dependencyVersionRange -Stack $nextStack if ($child) { Add-PackageDependencyPlanEdge -Plan $Context.Plan -ParentNode $node -ChildNode $child -VersionRange $dependencyVersionRange | Out-Null } } return $node } function New-PackageDependencyPlan { [CmdletBinding()] param( [AllowNull()] [string]$PublisherId = $null, [Parameter(Mandatory = $true)] [ValidateNotNullOrEmpty()] [string[]]$DefinitionId, [ValidateSet('Assigned', 'Removed')] [string]$DesiredState = 'Assigned', [AllowNull()] [string]$PackageVersion = $null, [bool]$PackageVersionOverrideSpecified = $false, [switch]$AcceptUnknownSigningKey ) $nodeMap = New-Object 'System.Collections.Generic.Dictionary[string,object]' ([System.StringComparer]::OrdinalIgnoreCase) $edgeMap = New-Object 'System.Collections.Generic.Dictionary[string,object]' ([System.StringComparer]::OrdinalIgnoreCase) $childrenByParentKey = New-Object 'System.Collections.Generic.Dictionary[string,object]' ([System.StringComparer]::OrdinalIgnoreCase) $plan = [pscustomobject]@{ Kind = 'PackageDependencyPlan' CreatedAtUtc = [DateTime]::UtcNow.ToString('o') DesiredState = $DesiredState Status = 'Pending' Accepted = $false Roots = New-Object 'System.Collections.Generic.List[object]' Nodes = New-Object 'System.Collections.Generic.List[object]' Edges = New-Object 'System.Collections.Generic.List[object]' Violations = New-Object 'System.Collections.Generic.List[object]' NodeMap = $nodeMap EdgeMap = $edgeMap ChildrenByParentKey = $childrenByParentKey } $context = [pscustomobject]@{ Plan = $plan AcceptUnknownSigningKey = [bool]$AcceptUnknownSigningKey PackageVersion = $PackageVersion PackageVersionOverrideSpecified = [bool]$PackageVersionOverrideSpecified RootDefinitionId = $null } foreach ($rootDefinitionId in @($DefinitionId)) { $context.RootDefinitionId = [string]$rootDefinitionId $rootNode = Resolve-PackageDependencyPlanNode -Context $context -PublisherId $PublisherId -DefinitionId ([string]$rootDefinitionId) -Stack @() -IsRoot $plan.Roots.Add([pscustomobject]@{ RequestedPublisherId = $PublisherId RequestedDefinitionId = [string]$rootDefinitionId NodeKey = if ($rootNode) { [string]$rootNode.NodeKey } else { $null } PublisherId = if ($rootNode) { [string]$rootNode.PublisherId } else { $PublisherId } DefinitionId = if ($rootNode) { [string]$rootNode.DefinitionId } else { [string]$rootDefinitionId } PackageConfig = if ($rootNode) { $rootNode.PackageConfig } else { $null } }) | Out-Null } Test-PackageDependencyPlanPeerPolicy -Plan $plan if ($plan.Violations.Count -eq 0) { $plan.Status = 'Approved' $plan.Accepted = $true } else { $plan.Status = 'Failed' $plan.Accepted = $false } return $plan } function Confirm-PackageDependencyPlanSelection { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$PackageResult ) if (-not $PackageResult.PSObject.Properties['DependencyPlan'] -or -not $PackageResult.DependencyPlan -or -not $PackageResult.PSObject.Properties['DependencyPlanNodeKey'] -or [string]::IsNullOrWhiteSpace([string]$PackageResult.DependencyPlanNodeKey)) { return $PackageResult } $node = Get-PackageDependencyPlanNode -Plan $PackageResult.DependencyPlan -NodeKey ([string]$PackageResult.DependencyPlanNodeKey) if (-not $node) { throw "Dependency plan node '$($PackageResult.DependencyPlanNodeKey)' was not found." } if (-not [string]::Equals([string]$PackageResult.DefinitionId, [string]$node.DefinitionId, [System.StringComparison]::OrdinalIgnoreCase)) { throw "Dependency plan node '$($node.NodeKey)' expected definition '$($node.DefinitionId)' but execution selected '$($PackageResult.DefinitionId)'." } if (-not [string]::Equals([string]$PackageResult.PackageVersion, [string]$node.PackageVersion, [System.StringComparison]::OrdinalIgnoreCase)) { throw "Dependency plan node '$($node.NodeKey)' expected version '$($node.PackageVersion)' but execution selected '$($PackageResult.PackageVersion)'." } $PackageResult.DependencyPlanVerdict = Select-PackageDependencyPlanVerdict -Plan $PackageResult.DependencyPlan return $PackageResult } function Set-PackageResultDependencyPlanContext { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$PackageResult, [AllowNull()] [psobject]$DependencyPlan = $null, [AllowNull()] [string]$DependencyPlanNodeKey = $null ) if (-not $DependencyPlan -or [string]::IsNullOrWhiteSpace($DependencyPlanNodeKey)) { return $PackageResult } $node = Get-PackageDependencyPlanNode -Plan $DependencyPlan -NodeKey $DependencyPlanNodeKey if (-not $node) { throw "Dependency plan node '$DependencyPlanNodeKey' was not found." } $PackageResult | Add-Member -MemberType NoteProperty -Name DependencyPlan -Value $DependencyPlan -Force $PackageResult | Add-Member -MemberType NoteProperty -Name DependencyPlanNodeKey -Value ([string]$DependencyPlanNodeKey) -Force $PackageResult | Add-Member -MemberType NoteProperty -Name DependencyPlanVerdict -Value (Select-PackageDependencyPlanVerdict -Plan $DependencyPlan) -Force if (-not [string]::IsNullOrWhiteSpace([string]$node.VersionRange)) { $PackageResult | Add-Member -MemberType NoteProperty -Name PackageVersionRange -Value ([string]$node.VersionRange) -Force } return $PackageResult } function New-PackageDependencyPlanFailureResult { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$Plan, [Parameter(Mandatory = $true)] [psobject]$Root, [ValidateSet('Assigned', 'Removed')] [string]$DesiredState = 'Assigned', [switch]$Offline, [switch]$MaterializeOnly, [AllowNull()] [string]$PackageVersion = $null ) $commandMode = if ($MaterializeOnly.IsPresent) { 'MaterializeOnly' } else { $DesiredState } $config = $Root.PackageConfig if ($config) { $result = New-PackageResult -DesiredState $DesiredState -CommandMode $commandMode -Offline:$Offline -MaterializeOnly:$MaterializeOnly -PackageConfig $config -PackageVersionSelector $PackageVersion } else { $result = [pscustomobject]@{ OperationId = [guid]::NewGuid().ToString('n') OperationStartedAtUtc = [DateTime]::UtcNow.ToString('o') DesiredState = $DesiredState CommandMode = $commandMode Offline = [bool]$Offline MaterializeOnly = [bool]$MaterializeOnly PublisherId = $Root.RequestedPublisherId DefinitionId = $Root.RequestedDefinitionId DefinitionPublisherId = $Root.PublisherId Status = 'Pending' FailureReason = $null ErrorMessage = $null CurrentStep = 'Pending' } } $planViolations = @(ConvertTo-PackageDependencyPlanArray -Value $Plan.Violations) $firstViolation = @($planViolations | Where-Object { [string]::IsNullOrWhiteSpace([string]$_.RootDefinitionId) -or [string]::Equals([string]$_.RootDefinitionId, [string]$Root.RequestedDefinitionId, [System.StringComparison]::OrdinalIgnoreCase) } | Select-Object -First 1) if (-not $firstViolation) { $firstViolation = @($planViolations | Select-Object -First 1) } $result.Status = 'Failed' $result.FailureReason = 'PackageDependencyPlanFailed' $result.ErrorMessage = if ($firstViolation) { [string]$firstViolation.Message } else { 'Package dependency plan failed.' } $result.CurrentStep = 'PlanDependencies' $result | Add-Member -MemberType NoteProperty -Name DependencyPlanVerdict -Value (Select-PackageDependencyPlanVerdict -Plan $Plan) -Force return $result } function New-PackageDependencyPlanFailureResults { [CmdletBinding()] param( [Parameter(Mandatory = $true)] [psobject]$Plan, [ValidateSet('Assigned', 'Removed')] [string]$DesiredState = 'Assigned', [switch]$Offline, [switch]$MaterializeOnly, [AllowNull()] [string]$PackageVersion = $null ) return @( foreach ($root in @(ConvertTo-PackageDependencyPlanArray -Value $Plan.Roots)) { New-PackageDependencyPlanFailureResult -Plan $Plan -Root $root -DesiredState $DesiredState -Offline:$Offline -MaterializeOnly:$MaterializeOnly -PackageVersion $PackageVersion } ) } |