MocUpgradePrecheck.Tests.ps1
BeforeAll { Import-Module Pester ipmo .\Moc.psm1 Import-Module $PSScriptRoot\MocUpgradePrecheckTestMocks.psm1 $cluster = "s-cluster" } AfterAll { Remove-Module Moc Remove-Module MocUpgradePrecheckTestMocks } # Important note on mocks # Module name param tells pester to inject the mock into the corresponding # modules scope, so the internal functions of MocNodesHelper will use the mock # instead of the regular version of the function Describe "Verify MocNodesMatchFailoverClusterNodes" { BeforeAll { $activeStatus = @{ "statuses" = @{ "RunningState" = "Active" } } $inactiveStatus = @{ "statuses" = @{ "RunningState" = "Inactive" "Error" = "Precheck Error Message" } } } It "test fails when Get-MocConfig throws with [FAILURE][CRITICAL]" { Mock -ModuleName "Moc" Get-MocConfig { throw "Mock exception" } $result = Test-MocNodesMatchFailoverClusterNodes -Cluster $cluster $result.count | Should -Be 1 $result.Severity | Should -Be "CRITICAL" $result.Status | Should -Be "FAILURE" } It "test fails when Get-MocConfig throws with [FAILURE][CRITICAL]" { Mock -ModuleName "Moc" Get-MocConfig { @{ "cloudLocation" = "MocLocation" } } Mock -ModuleName "Moc" Get-MocNode { throw "Mock exception" } $result = Test-MocNodesMatchFailoverClusterNodes -Cluster $cluster $result.count | Should -Be 1 $result.Severity | Should -Be "CRITICAL" $result.Status | Should -Be "FAILURE" } It "MocNodes test succeeds with [SUCCESS][INFORMATIONAL]" { Mock -ModuleName "Moc" Get-MocNode { @( @{ "name" = "ABC-D120301" "properties" = $activeStatus }, @{ "name" = "abc-d120302" "properties" = $activeStatus } ) } -ParameterFilter {$Location -ne $null} # MOC node can be exact case match, or full lowercase of the failover cluster name Mock -ModuleName "Moc" Get-ClusterNode { @( @{ "Name" = "ABC-D120301" "State" = "Up" }, @{ "Name" = "Abc-D120302" "State" = "Up" } ) } Mock -ModuleName "Moc" Get-MocConfig { @{ "cloudLocation" = "MocLocation" } } $result = Test-MocNodesMatchFailoverClusterNodes -Cluster $cluster $result.count | Should -Be 5 $result[0].Severity | Should -Be "INFORMATIONAL" $result[0].Status | Should -Be "SUCCESS" $result[0].TargetResourceName | Should -Be "s-cluster" $result[1].Severity | Should -Be "INFORMATIONAL" $result[1].Status | Should -Be "SUCCESS" $result[1].TargetResourceName | Should -Be "ABC-D120301" $result[2].Severity | Should -Be "INFORMATIONAL" $result[2].Status | Should -Be "SUCCESS" $result[2].TargetResourceName | Should -Be "Abc-D120302" $result[3].Severity | Should -Be "INFORMATIONAL" $result[3].Status | Should -Be "SUCCESS" $result[3].TargetResourceName | Should -Be "ABC-D120301" $result[4].Severity | Should -Be "INFORMATIONAL" $result[4].Status | Should -Be "SUCCESS" $result[4].TargetResourceName | Should -Be "abc-d120302" } It "MocNodes test succeeds fails when node state is inactive [FAILURE][CRITICAL]" { Mock -ModuleName "Moc" Get-MocNode { # Since there is a single element, add the comma to make sure it gets # returned as an array type, not a single object. Same applies to below ,@( @{ "name" = "ABC-D120301" "properties" = $inactiveStatus } ) } -ParameterFilter {$Location -ne $null} Mock -ModuleName "Moc" Get-ClusterNode { ,@( @{ "Name" = "ABC-D120301" "State" = "Up" } ) } Mock -ModuleName "Moc" Get-MocConfig { @{ "cloudLocation" = "MocLocation" } } $result = Test-MocNodesMatchFailoverClusterNodes -Cluster $cluster $result.count | Should -Be 3 $result[0].Severity | Should -Be "INFORMATIONAL" $result[0].Status | Should -Be "SUCCESS" $result[0].TargetResourceName | Should -Be "s-cluster" $result[1].Severity | Should -Be "INFORMATIONAL" $result[1].Status | Should -Be "SUCCESS" $result[1].TargetResourceName | Should -Be "ABC-D120301" $result[2].Severity | Should -Be "CRITICAL" $result[2].Status | Should -Be "FAILURE" $result[2].TargetResourceName | Should -Be "ABC-D120301" $result[2].Description -match "unexpected running state.*Precheck Error Message" | Should -BeTrue } It "MocNodes test fails due to differences in casing or name with [FAILURE][CRITICAL]" { Mock -ModuleName "Moc" Get-MocNode { @( @{ "name" = "ABC-D120301" "properties" = $activeStatus }, @{ "name" = "ABC-D120302" "properties" = $activeStatus } ) } -ParameterFilter {$Location -ne $null} # The MOC name needs to be either fully lowercase of the Failover cluster name # or an exact match, anything else should fail Mock -ModuleName "Moc" Get-ClusterNode { @( @{ "Name" = "Abc-d120301" "State" = "Up" }, @{ "Name" = "EFG-D120302" "State" = "Up" } ) } Mock -ModuleName "Moc" Get-MocConfig { @{ "cloudLocation" = "MocLocation" } } $result = Test-MocNodesMatchFailoverClusterNodes -Cluster $cluster $result.count | Should -Be 5 $result[0].Severity | Should -Be "INFORMATIONAL" $result[0].Status | Should -Be "SUCCESS" $result[0].TargetResourceName | Should -Be "s-cluster" $result[1].Severity | Should -Be "CRITICAL" $result[1].Status | Should -Be "FAILURE" $result[1].TargetResourceName | Should -Be "abc-d120301" $result[2].Severity | Should -Be "CRITICAL" $result[2].Status | Should -Be "FAILURE" $result[2].TargetResourceName | Should -Be "EFG-D120302" $result[3].Severity | Should -Be "INFORMATIONAL" $result[3].Status | Should -Be "SUCCESS" $result[3].TargetResourceName | Should -Be "Abc-d120301" $result[4].Severity | Should -Be "INFORMATIONAL" $result[4].Status | Should -Be "SUCCESS" $result[4].TargetResourceName | Should -Be "ABC-D120302" } It "MocNodes test fails due to additional MOC nodes [FAILURE][CRITICAL]" { Mock -ModuleName "Moc" Get-MocNode { @( @{ "name" = "ABC-D120301" "properties" = $activeStatus }, @{ "name" = "ABC-D120302" "properties" = $activeStatus }, @{ "name" = "ABC-D120303" "properties" = $activeStatus } ) } -ParameterFilter {$Location -ne $null} Mock -ModuleName "Moc" Get-ClusterNode { @( @{ "Name" = "ABC-D120301" "State" = "Up" }, @{ "Name" = "ABC-D120302" "State" = "Up" } ) } Mock -ModuleName "Moc" Get-MocConfig { @{ "cloudLocation" = "MocLocation" } } $result = Test-MocNodesMatchFailoverClusterNodes -Cluster $cluster $result.count | Should -Be 6 $result[0].Severity | Should -Be "CRITICAL" $result[0].Status | Should -Be "FAILURE" $result[0].TargetResourceName | Should -Be "s-cluster" $result[1].Severity | Should -Be "INFORMATIONAL" $result[1].Status | Should -Be "SUCCESS" $result[1].TargetResourceName | Should -Be "ABC-D120301" $result[2].Severity | Should -Be "INFORMATIONAL" $result[2].Status | Should -Be "SUCCESS" $result[2].TargetResourceName | Should -Be "ABC-D120302" $result[3].Severity | Should -Be "INFORMATIONAL" $result[3].Status | Should -Be "SUCCESS" $result[3].TargetResourceName | Should -Be "ABC-D120301" $result[4].Severity | Should -Be "INFORMATIONAL" $result[4].Status | Should -Be "SUCCESS" $result[4].TargetResourceName | Should -Be "ABC-D120302" $result[5].Severity | Should -Be "INFORMATIONAL" $result[5].Status | Should -Be "SUCCESS" $result[5].TargetResourceName | Should -Be "ABC-D120303" } It "MocNodes test fails due to additional cluster nodes and case change [FAILURE][CRITICAL]" { Mock -ModuleName "Moc" Get-MocNode { @( @{ "name" = "ABC-D120301" "properties" = $activeStatus }, @{ "name" = "ABC-D120302" "properties" = $activeStatus } ) } -ParameterFilter {$Location -ne $null} Mock -ModuleName "Moc" Get-ClusterNode { @( @{ "Name" = "ABC-D120301" "State" = "Up" }, @{ "Name" = "abc-d120302" "State" = "Up" }, @{ "Name" = "abc-d120303" "State" = "Up" } ) } Mock -ModuleName "Moc" Get-MocConfig { @{ "cloudLocation" = "MocLocation" } } $result = Test-MocNodesMatchFailoverClusterNodes -Cluster $cluster $result.count | Should -Be 6 $result[0].Severity | Should -Be "CRITICAL" $result[0].Status | Should -Be "FAILURE" $result[0].TargetResourceName | Should -Be "s-cluster" $result[1].Severity | Should -Be "INFORMATIONAL" $result[1].Status | Should -Be "SUCCESS" $result[1].TargetResourceName | Should -Be "ABC-D120301" $result[2].Severity | Should -Be "CRITICAL" $result[2].Status | Should -Be "FAILURE" $result[2].TargetResourceName | Should -Be "abc-d120302" $result[3].Severity | Should -Be "CRITICAL" $result[3].Status | Should -Be "FAILURE" $result[3].TargetResourceName | Should -Be "abc-d120303" $result[4].Severity | Should -Be "INFORMATIONAL" $result[4].Status | Should -Be "SUCCESS" $result[4].TargetResourceName | Should -Be "ABC-D120301" $result[5].Severity | Should -Be "INFORMATIONAL" $result[5].Status | Should -Be "SUCCESS" $result[5].TargetResourceName | Should -Be "ABC-D120302" } } Describe "Verify Test-HCIClusterAndNodeRegistration" { It "Succeeds when cluster is connected and registered, and all nodes are active [SUCCESS][INFORMATIONAL]" { Mock -ModuleName "Moc" Get-AzureStackHCI { @{ "RegistrationStatus" = "Registered" "ConnectionStatus" = "Connected" } } Mock -ModuleName "Moc" Get-ClusterNode { @( @{ "Name" = "abc-d120301" "State" = "Up" }, @{ "Name" = "abc-d120302" "State" = "Up" } ) } Mock -ModuleName "Moc" Get-AzureStackHCISubscriptionStatus { @( @{ "SubscriptionName" = "Azure Stack HCI" "Status" = "Active" } ) } $result = Test-HCIClusterAndNodeRegistration -Cluster $cluster $result.count | Should -Be 3 $result[0].Severity | Should -Be "INFORMATIONAL" $result[0].Status | Should -Be "SUCCESS" $result[0].TargetResourceName | Should -Be "s-cluster" $result[1].Severity | Should -Be "INFORMATIONAL" $result[1].Status | Should -Be "SUCCESS" $result[1].TargetResourceName | Should -Be "abc-d120301" $result[2].Severity | Should -Be "INFORMATIONAL" $result[2].Status | Should -Be "SUCCESS" $result[2].TargetResourceName | Should -Be "abc-d120302" } It "Succeeds when cluster is connected and registered, and all nodes are active with Preview Subscription Name [SUCCESS][INFORMATIONAL]" { Mock -ModuleName "Moc" Get-AzureStackHCI { @{ "RegistrationStatus" = "Registered" "ConnectionStatus" = "Connected" } } Mock -ModuleName "Moc" Get-ClusterNode { @( @{ "Name" = "abc-d120301" "State" = "Up" }, @{ "Name" = "abc-d120302" "State" = "Up" } ) } Mock -ModuleName "Moc" Get-AzureStackHCISubscriptionStatus { @( @{ "SubscriptionName" = "Azure Stack HCI Preview" "Status" = "Active" } ) } $result = Test-HCIClusterAndNodeRegistration -Cluster $cluster $result.count | Should -Be 3 $result[0].Severity | Should -Be "INFORMATIONAL" $result[0].Status | Should -Be "SUCCESS" $result[0].TargetResourceName | Should -Be "s-cluster" $result[1].Severity | Should -Be "INFORMATIONAL" $result[1].Status | Should -Be "SUCCESS" $result[1].TargetResourceName | Should -Be "abc-d120301" $result[2].Severity | Should -Be "INFORMATIONAL" $result[2].Status | Should -Be "SUCCESS" $result[2].TargetResourceName | Should -Be "abc-d120302" } It "Fails when cluster is connected and registered, but nodes do not have valid subscription name [FAILURE][CRITICAL]" { Mock -ModuleName "Moc" Get-AzureStackHCI { @{ "RegistrationStatus" = "Registered" "ConnectionStatus" = "Connected" } } Mock -ModuleName "Moc" Get-ClusterNode { @( @{ "Name" = "abc-d120301" "State" = "Up" }, @{ "Name" = "abc-d120302" "State" = "Up" } ) } Mock -ModuleName "Moc" Get-AzureStackHCISubscriptionStatus { @( @{ "SubscriptionName" = "Azure Stack Invalid" "Status" = "Active" } ) } $result = Test-HCIClusterAndNodeRegistration -Cluster $cluster $result.count | Should -Be 3 $result[0].Severity | Should -Be "INFORMATIONAL" $result[0].Status | Should -Be "SUCCESS" $result[0].TargetResourceName | Should -Be "s-cluster" $result[1].Severity | Should -Be "CRITICAL" $result[1].Status | Should -Be "FAILURE" $result[1].TargetResourceName | Should -Be "abc-d120301" $result[2].Severity | Should -Be "CRITICAL" $result[2].Status | Should -Be "FAILURE" $result[2].TargetResourceName | Should -Be "abc-d120302" } It "Failed when cluster is not registered, and all nodes are inactive [FAILURE][CRITICAL]" { Mock -ModuleName "Moc" Get-AzureStackHCI { @{ "RegistrationStatus" = "Unregistered" "ConnectionStatus" = "Disconnected" } } Mock -ModuleName "Moc" Get-ClusterNode { @( @{ "Name" = "abc-d120301" "State" = "Up" }, @{ "Name" = "abc-d120302" "State" = "Up" } ) } Mock -ModuleName "Moc" Get-AzureStackHCISubscriptionStatus { @( @{ "SubscriptionName" = "Azure Stack HCI" "Status" = "Inactive" } ) } $result = Test-HCIClusterAndNodeRegistration -Cluster $cluster $result.count | Should -Be 3 $result[0].Severity | Should -Be "CRITICAL" $result[0].Status | Should -Be "FAILURE" $result[0].TargetResourceName | Should -Be "s-cluster" $result[0].Description -match "Registration Status" | Should -BeTrue $result[1].Severity | Should -Be "CRITICAL" $result[1].Status | Should -Be "FAILURE" $result[1].TargetResourceName | Should -Be "abc-d120301" $result[2].Severity | Should -Be "CRITICAL" $result[2].Status | Should -Be "FAILURE" $result[2].TargetResourceName | Should -Be "abc-d120302" } } Describe "Verify Test-MocNodeConnectivity" { It "Should fail when a network connection between cloudagent and nodeagent is unhealthy" { Mock -ModuleName "Moc" Get-ClusterNode { @( @{ "Name" = "abc-d120301" "State" = "Up" }, @{ "Name" = "abc-d120302" "State" = "Up" } ) } Mock -ModuleName "Moc" Get-MocConfig { @{ "clusterRoleName" = "mockName" } } Mock -ModuleName "Moc" Get-FailoverCluster { @{ "domain" = "contoso.com" } } Mock -ModuleName "Moc" Get-FailoverClusterGroup { @{ "ownernode" = @{ "name" = "abc-d120302" } } } Mock -ModuleName "Moc" Invoke-Command { @{ "TcpTestSucceeded" = $false } } Mock -ModuleName "Moc" Get-CloudFqdn { "abc-d120302.contoso.com" } $result = Test-MocNodeConnectivity -Cluster $cluster $result.count | Should -Be 4 $result[0].Severity | Should -Be "CRITICAL" $result[0].Status | Should -Be "FAILURE" $result[0].TargetResourceName | Should -Be "abc-d120301" $result[0].Description | Should -Be "TCP test from CloudAgent Node abc-d120302 to nodeagent abc-d120301.contoso.com failed" $result[1].Severity | Should -Be "CRITICAL" $result[1].Status | Should -Be "FAILURE" $result[1].TargetResourceName | Should -Be "abc-d120302" $result[1].Description | Should -Be "TCP test from CloudAgent Node abc-d120302 to nodeagent abc-d120302.contoso.com failed" $result[2].Severity | Should -Be "CRITICAL" $result[2].Status | Should -Be "FAILURE" $result[2].TargetResourceName | Should -Be "abc-d120301" $result[2].Description | Should -Be "TCP test from cluster node abc-d120301 to CloudAgent fqdn abc-d120302.contoso.com failed" $result[3].Severity | Should -Be "CRITICAL" $result[3].Status | Should -Be "FAILURE" $result[3].TargetResourceName | Should -Be "abc-d120302" $result[3].Description | Should -Be "TCP test from cluster node abc-d120302 to CloudAgent fqdn abc-d120302.contoso.com failed" } It "Should succeed when all agents are connected" { Mock -ModuleName "Moc" Get-ClusterNode { @( @{ "Name" = "abc-d120301" "State" = "Up" }, @{ "Name" = "abc-d120302" "State" = "Up" } ) } Mock -ModuleName "Moc" Get-MocConfig { @{ "clusterRoleName" = "mockName" } } Mock -ModuleName "Moc" Get-FailoverCluster { @{ "domain" = "contoso.com" } } Mock -ModuleName "Moc" Get-FailoverClusterGroup { @{ "ownernode" = @{ "name" = "abc-d120302" } } } Mock -ModuleName "Moc" Invoke-Command { @{ "TcpTestSucceeded" = $true } } Mock -ModuleName "Moc" Get-CloudFqdn { "abc-d120302.contoso.com" } $result = Test-MocNodeConnectivity -Cluster $cluster $result.count | Should -Be 4 $result[0].Severity | Should -Be "INFORMATIONAL" $result[0].Status | Should -Be "SUCCESS" $result[0].TargetResourceName | Should -Be "abc-d120301" $result[0].Description | Should -Be "TCP test from CloudAgent Node abc-d120302 to nodeagent abc-d120301.contoso.com succeeded" $result[1].Severity | Should -Be "INFORMATIONAL" $result[1].Status | Should -Be "SUCCESS" $result[1].TargetResourceName | Should -Be "abc-d120302" $result[1].Description | Should -Be "TCP test from CloudAgent Node abc-d120302 to nodeagent abc-d120302.contoso.com succeeded" $result[2].Severity | Should -Be "INFORMATIONAL" $result[2].Status | Should -Be "SUCCESS" $result[2].TargetResourceName | Should -Be "abc-d120301" $result[2].Description | Should -Be "TCP test from cluster node abc-d120301 to CloudAgent fqdn abc-d120302.contoso.com succeeded" $result[3].Severity | Should -Be "INFORMATIONAL" $result[3].Status | Should -Be "SUCCESS" $result[3].TargetResourceName | Should -Be "abc-d120302" $result[3].Description | Should -Be "TCP test from cluster node abc-d120302 to CloudAgent fqdn abc-d120302.contoso.com succeeded" } It "Should fail when Invoke-Command throws an exception" { Mock -ModuleName "Moc" Get-ClusterNode { @( @{ "Name" = "abc-d120301" "State" = "Up" }, @{ "Name" = "abc-d120302" "State" = "Up" } ) } Mock -ModuleName "Moc" Get-MocConfig { @{ "clusterRoleName" = "mockName" } } Mock -ModuleName "Moc" Get-FailoverCluster { @{ "domain" = "contoso.com" } } Mock -ModuleName "Moc" Get-FailoverClusterGroup { @{ "ownernode" = @{ "name" = "abc-d120302" } } } Mock -ModuleName "Moc" Invoke-Command { throw "Mock exception" } Mock -ModuleName "Moc" Get-CloudFqdn { "abc-d120302.contoso.com" } $result = Test-MocNodeConnectivity -Cluster $cluster $result.count | Should -Be 4 $result[0].Severity | Should -Be "CRITICAL" $result[0].Status | Should -Be "ERROR" $result[0].TargetResourceName | Should -Be "abc-d120301" $result[0].Description | Should -Be "Unable to check CloudAgent Node to Nodeagent connection due to exception: Mock exception" $result[1].Severity | Should -Be "CRITICAL" $result[1].Status | Should -Be "ERROR" $result[1].TargetResourceName | Should -Be "abc-d120302" $result[1].Description | Should -Be "Unable to check CloudAgent Node to Nodeagent connection due to exception: Mock exception" $result[2].Severity | Should -Be "CRITICAL" $result[2].Status | Should -Be "ERROR" $result[2].TargetResourceName | Should -Be "abc-d120301" $result[2].Description | Should -Be "Unable to check Nodeagent Node to Cloudagent connection due to exception: Mock exception" $result[3].Severity | Should -Be "CRITICAL" $result[3].Status | Should -Be "ERROR" $result[3].TargetResourceName | Should -Be "abc-d120302" $result[3].Description | Should -Be "Unable to check Nodeagent Node to Cloudagent connection due to exception: Mock exception" } } Describe "Verify Test-MOCUpdateReadinessInternal" { It "Should return null if not a failover cluster" { Mock -ModuleName "Moc" Get-FailoverCluster { $null } $result = Test-MOCUpdateReadinessInternal $result | Should -BeNullOrEmpty } It "Should skip HCI test in case of non-HCI setup" { Mock -ModuleName "Moc" Get-FailoverCluster { $null } # return something not matching the HCI SKU (406) Mock -ModuleName "Moc" Get-CimInstance { @{ "OperatingSystemSKU" = 8 } } Mock -ModuleName "Moc" Test-MocNodesMatchFailoverClusterNodes {} Mock -ModuleName "Moc" Test-ProxyEnvironmentVariables {} Mock -ModuleName "Moc" Test-MocNodeConnectivity {} Mock -ModuleName "Moc" Test-HCIClusterAndNodeRegistration {} $result = Test-MOCUpdateReadinessInternal -Cluster $cluster Should -Invoke Test-HCIClusterAndNodeRegistration -ModuleName "Moc" -Exactly 0 Should -Invoke Test-ProxyEnvironmentVariables -ModuleName "Moc" -Exactly 1 # If we fix and add back Test-EventLogServiceOnNodes, we should either mock it # or increment the count here, since it calls Get-FailoverCluster Should -Invoke Get-FailoverCluster -ModuleName "Moc" -Exactly 0 } } Describe "Verify Confirm-MocAgentReadiness" { It "Should return null when there is no failover cluster" { Mock -ModuleName "Moc" Get-FailoverCluster { $null } Mock -ModuleName "Moc" Get-ClusterGroup {} $result = Confirm-MocAgentReadiness $result | Should -BeNullOrEmpty # ensure we never get to the point of calling Get-ClusterGroup Should -Invoke Get-ClusterGroup -ModuleName "Moc" -Exactly 0 } It "Should succeed when all agents are already online" { # just return anything non-null Mock -ModuleName "Moc" Get-FailoverCluster { @{ "Name" = $cluster } } Mock -ModuleName "Moc" Get-MocConfig { @{ "clusterRoleName" = "test" } } Mock -ModuleName "Moc" Get-ClusterGroup { @{ "State" = "Online" } } Mock -ModuleName "Moc" Get-ClusterNode { @( @{ "Name" = "abc-d120301" "State" = "Up" }, @{ "Name" = "abc-d120302" "State" = "Up" } ) } Mock -ModuleName "Moc" Invoke-Command { $false } -ParameterFilter { $ComputerName -eq "abc-d120301"} Mock -ModuleName "Moc" Invoke-Command { $false } -ParameterFilter { $ComputerName -eq "abc-d120302"} Mock -ModuleName "Moc" Start-ClusterGroup {} Mock -ModuleName "Moc" Wait-ForActiveNodes {} Confirm-MocAgentReadiness # make sure this is never called, indicating we took no action Should -Invoke Start-ClusterGroup -ModuleName "Moc" -Exactly 0 Should -Invoke Wait-ForActiveNodes -ModuleName "Moc" -Exactly 0 } It "Should exit early but not throw when cloudagent does not become ready" { # just return anything non-null Mock -ModuleName "Moc" Get-FailoverCluster { @{ "Name" = $cluster } } Mock -ModuleName "Moc" Get-MocConfig { @{ "clusterRoleName" = "test" } } Mock -ModuleName "Moc" Get-ClusterGroup { @{ "State" = "Offline" } } Mock -ModuleName "Moc" Get-ClusterNode {} Mock -ModuleName "Moc" Start-ClusterGroup {} Mock -ModuleName "Moc" Wait-ForCloudAgentEndpoint { throw "Test exception" } { Confirm-MocAgentReadiness } | Should -Not -Throw Should -Invoke Start-ClusterGroup -ModuleName "Moc" -Exactly 1 # make sure this is never called, indicating we exited prior to this Should -Invoke Get-ClusterNode -ModuleName "Moc" -Exactly 0 } It "Should wait for cloudagent and nodeagent if they are offline" { # just return anything non-null Mock -ModuleName "Moc" Get-FailoverCluster { @{ "Name" = $cluster } } Mock -ModuleName "Moc" Get-ClusterGroup { @{ "State" = "Offline" } } Mock -ModuleName "Moc" Get-MocConfig { @{ "clusterRoleName" = "test" } } Mock -ModuleName "Moc" Start-ClusterGroup {} Mock -ModuleName "Moc" Wait-ForCloudAgentEndpoint { $null } Mock -ModuleName "Moc" Get-ClusterNode { @( @{ "Name" = "abc-d120301" "State" = "Up" }, @{ "Name" = "abc-d120302" "State" = "Up" } ) } Mock -ModuleName "Moc" Invoke-Command { $false } -ParameterFilter { $ComputerName -eq "abc-d120301"} Mock -ModuleName "Moc" Invoke-Command { $true } -ParameterFilter { $ComputerName -eq "abc-d120302"} Mock -ModuleName "Moc" Wait-ForActiveNodes { $true } { Confirm-MocAgentReadiness } | Should -Not -Throw Should -Invoke Start-ClusterGroup -ModuleName "Moc" -Exactly 1 Should -Invoke Wait-ForCloudAgentEndpoint -ModuleName "Moc" -Exactly 1 Should -Invoke Wait-ForActiveNodes -ModuleName "Moc" -Exactly 1 } It "Should not throw even if we have an unexpected exception" { # just return anything non-null Mock -ModuleName "Moc" Get-FailoverCluster { @{ "Name" = $cluster } } Mock -ModuleName "Moc" Get-MocConfig { @{ "clusterRoleName" = "test" } } Mock -ModuleName "Moc" Get-ClusterGroup { @{ "State" = "Offline" } } Mock -ModuleName "Moc" Start-ClusterGroup {} Mock -ModuleName "Moc" Wait-ForCloudAgentEndpoint { $null } Mock -ModuleName "Moc" Get-ClusterNode { @( @{ "Name" = "abc-d120301" "State" = "Up" }, @{ "Name" = "abc-d120302" "State" = "Up" } ) } Mock -ModuleName "Moc" Invoke-Command { $false } -ParameterFilter { $ComputerName -eq "abc-d120301"} Mock -ModuleName "Moc" Invoke-Command { $true } -ParameterFilter { $ComputerName -eq "abc-d120302"} Mock -ModuleName "Moc" Wait-ForActiveNodes { throw "unexpected failure" } { Confirm-MocAgentReadiness } | Should -Not -Throw Should -Invoke Start-ClusterGroup -ModuleName "Moc" -Exactly 1 Should -Invoke Wait-ForCloudAgentEndpoint -ModuleName "Moc" -Exactly 1 Should -Invoke Wait-ForActiveNodes -ModuleName "Moc" -Exactly 1 } } # SIG # Begin signature block # MIIoPAYJKoZIhvcNAQcCoIIoLTCCKCkCAQExDzANBglghkgBZQMEAgEFADB5Bgor # BgEEAYI3AgEEoGswaTA0BgorBgEEAYI3AgEeMCYCAwEAAAQQH8w7YFlLCE63JNLG # KX7zUQIBAAIBAAIBAAIBAAIBADAxMA0GCWCGSAFlAwQCAQUABCAVfiHSfy4ZDQtu # CWtUSDJIbf83Mj2NvjwJD7FJ67Je6KCCDYUwggYDMIID66ADAgECAhMzAAAEhJji # EuB4ozFdAAAAAASEMA0GCSqGSIb3DQEBCwUAMH4xCzAJBgNVBAYTAlVTMRMwEQYD # VQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01pY3Jvc29mdCBDb2RlIFNpZ25p # bmcgUENBIDIwMTEwHhcNMjUwNjE5MTgyMTM1WhcNMjYwNjE3MTgyMTM1WjB0MQsw # CQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9u # ZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMR4wHAYDVQQDExVNaWNy # b3NvZnQgQ29ycG9yYXRpb24wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB # AQDtekqMKDnzfsyc1T1QpHfFtr+rkir8ldzLPKmMXbRDouVXAsvBfd6E82tPj4Yz # aSluGDQoX3NpMKooKeVFjjNRq37yyT/h1QTLMB8dpmsZ/70UM+U/sYxvt1PWWxLj # MNIXqzB8PjG6i7H2YFgk4YOhfGSekvnzW13dLAtfjD0wiwREPvCNlilRz7XoFde5 # KO01eFiWeteh48qUOqUaAkIznC4XB3sFd1LWUmupXHK05QfJSmnei9qZJBYTt8Zh # ArGDh7nQn+Y1jOA3oBiCUJ4n1CMaWdDhrgdMuu026oWAbfC3prqkUn8LWp28H+2S # LetNG5KQZZwvy3Zcn7+PQGl5AgMBAAGjggGCMIIBfjAfBgNVHSUEGDAWBgorBgEE # AYI3TAgBBggrBgEFBQcDAzAdBgNVHQ4EFgQUBN/0b6Fh6nMdE4FAxYG9kWCpbYUw # VAYDVR0RBE0wS6RJMEcxLTArBgNVBAsTJE1pY3Jvc29mdCBJcmVsYW5kIE9wZXJh # dGlvbnMgTGltaXRlZDEWMBQGA1UEBRMNMjMwMDEyKzUwNTM2MjAfBgNVHSMEGDAW # gBRIbmTlUAXTgqoXNzcitW2oynUClTBUBgNVHR8ETTBLMEmgR6BFhkNodHRwOi8v # d3d3Lm1pY3Jvc29mdC5jb20vcGtpb3BzL2NybC9NaWNDb2RTaWdQQ0EyMDExXzIw # MTEtMDctMDguY3JsMGEGCCsGAQUFBwEBBFUwUzBRBggrBgEFBQcwAoZFaHR0cDov # L3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9jZXJ0cy9NaWNDb2RTaWdQQ0EyMDEx # XzIwMTEtMDctMDguY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQELBQADggIB # AGLQps1XU4RTcoDIDLP6QG3NnRE3p/WSMp61Cs8Z+JUv3xJWGtBzYmCINmHVFv6i # 8pYF/e79FNK6P1oKjduxqHSicBdg8Mj0k8kDFA/0eU26bPBRQUIaiWrhsDOrXWdL # m7Zmu516oQoUWcINs4jBfjDEVV4bmgQYfe+4/MUJwQJ9h6mfE+kcCP4HlP4ChIQB # UHoSymakcTBvZw+Qst7sbdt5KnQKkSEN01CzPG1awClCI6zLKf/vKIwnqHw/+Wvc # Ar7gwKlWNmLwTNi807r9rWsXQep1Q8YMkIuGmZ0a1qCd3GuOkSRznz2/0ojeZVYh # ZyohCQi1Bs+xfRkv/fy0HfV3mNyO22dFUvHzBZgqE5FbGjmUnrSr1x8lCrK+s4A+ # bOGp2IejOphWoZEPGOco/HEznZ5Lk6w6W+E2Jy3PHoFE0Y8TtkSE4/80Y2lBJhLj # 27d8ueJ8IdQhSpL/WzTjjnuYH7Dx5o9pWdIGSaFNYuSqOYxrVW7N4AEQVRDZeqDc # fqPG3O6r5SNsxXbd71DCIQURtUKss53ON+vrlV0rjiKBIdwvMNLQ9zK0jy77owDy # XXoYkQxakN2uFIBO1UNAvCYXjs4rw3SRmBX9qiZ5ENxcn/pLMkiyb68QdwHUXz+1 # fI6ea3/jjpNPz6Dlc/RMcXIWeMMkhup/XEbwu73U+uz/MIIHejCCBWKgAwIBAgIK # YQ6Q0gAAAAAAAzANBgkqhkiG9w0BAQsFADCBiDELMAkGA1UEBhMCVVMxEzARBgNV # BAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jv # c29mdCBDb3Jwb3JhdGlvbjEyMDAGA1UEAxMpTWljcm9zb2Z0IFJvb3QgQ2VydGlm # aWNhdGUgQXV0aG9yaXR5IDIwMTEwHhcNMTEwNzA4MjA1OTA5WhcNMjYwNzA4MjEw # OTA5WjB+MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UE # BxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSgwJgYD # VQQDEx9NaWNyb3NvZnQgQ29kZSBTaWduaW5nIFBDQSAyMDExMIICIjANBgkqhkiG # 9w0BAQEFAAOCAg8AMIICCgKCAgEAq/D6chAcLq3YbqqCEE00uvK2WCGfQhsqa+la # UKq4BjgaBEm6f8MMHt03a8YS2AvwOMKZBrDIOdUBFDFC04kNeWSHfpRgJGyvnkmc # 6Whe0t+bU7IKLMOv2akrrnoJr9eWWcpgGgXpZnboMlImEi/nqwhQz7NEt13YxC4D # dato88tt8zpcoRb0RrrgOGSsbmQ1eKagYw8t00CT+OPeBw3VXHmlSSnnDb6gE3e+ # lD3v++MrWhAfTVYoonpy4BI6t0le2O3tQ5GD2Xuye4Yb2T6xjF3oiU+EGvKhL1nk # kDstrjNYxbc+/jLTswM9sbKvkjh+0p2ALPVOVpEhNSXDOW5kf1O6nA+tGSOEy/S6 # A4aN91/w0FK/jJSHvMAhdCVfGCi2zCcoOCWYOUo2z3yxkq4cI6epZuxhH2rhKEmd # X4jiJV3TIUs+UsS1Vz8kA/DRelsv1SPjcF0PUUZ3s/gA4bysAoJf28AVs70b1FVL # 5zmhD+kjSbwYuER8ReTBw3J64HLnJN+/RpnF78IcV9uDjexNSTCnq47f7Fufr/zd # sGbiwZeBe+3W7UvnSSmnEyimp31ngOaKYnhfsi+E11ecXL93KCjx7W3DKI8sj0A3 # T8HhhUSJxAlMxdSlQy90lfdu+HggWCwTXWCVmj5PM4TasIgX3p5O9JawvEagbJjS # 4NaIjAsCAwEAAaOCAe0wggHpMBAGCSsGAQQBgjcVAQQDAgEAMB0GA1UdDgQWBBRI # bmTlUAXTgqoXNzcitW2oynUClTAZBgkrBgEEAYI3FAIEDB4KAFMAdQBiAEMAQTAL # BgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBRyLToCMZBD # uRQFTuHqp8cx0SOJNDBaBgNVHR8EUzBRME+gTaBLhklodHRwOi8vY3JsLm1pY3Jv # c29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf # MDNfMjIuY3JsMF4GCCsGAQUFBwEBBFIwUDBOBggrBgEFBQcwAoZCaHR0cDovL3d3 # dy5taWNyb3NvZnQuY29tL3BraS9jZXJ0cy9NaWNSb29DZXJBdXQyMDExXzIwMTFf # MDNfMjIuY3J0MIGfBgNVHSAEgZcwgZQwgZEGCSsGAQQBgjcuAzCBgzA/BggrBgEF # BQcCARYzaHR0cDovL3d3dy5taWNyb3NvZnQuY29tL3BraW9wcy9kb2NzL3ByaW1h # cnljcHMuaHRtMEAGCCsGAQUFBwICMDQeMiAdAEwAZQBnAGEAbABfAHAAbwBsAGkA # YwB5AF8AcwB0AGEAdABlAG0AZQBuAHQALiAdMA0GCSqGSIb3DQEBCwUAA4ICAQBn # 8oalmOBUeRou09h0ZyKbC5YR4WOSmUKWfdJ5DJDBZV8uLD74w3LRbYP+vj/oCso7 # v0epo/Np22O/IjWll11lhJB9i0ZQVdgMknzSGksc8zxCi1LQsP1r4z4HLimb5j0b # pdS1HXeUOeLpZMlEPXh6I/MTfaaQdION9MsmAkYqwooQu6SpBQyb7Wj6aC6VoCo/ # KmtYSWMfCWluWpiW5IP0wI/zRive/DvQvTXvbiWu5a8n7dDd8w6vmSiXmE0OPQvy # CInWH8MyGOLwxS3OW560STkKxgrCxq2u5bLZ2xWIUUVYODJxJxp/sfQn+N4sOiBp # mLJZiWhub6e3dMNABQamASooPoI/E01mC8CzTfXhj38cbxV9Rad25UAqZaPDXVJi # hsMdYzaXht/a8/jyFqGaJ+HNpZfQ7l1jQeNbB5yHPgZ3BtEGsXUfFL5hYbXw3MYb # BL7fQccOKO7eZS/sl/ahXJbYANahRr1Z85elCUtIEJmAH9AAKcWxm6U/RXceNcbS # oqKfenoi+kiVH6v7RyOA9Z74v2u3S5fi63V4GuzqN5l5GEv/1rMjaHXmr/r8i+sL # gOppO6/8MO0ETI7f33VtY5E90Z1WTk+/gFcioXgRMiF670EKsT/7qMykXcGhiJtX # cVZOSEXAQsmbdlsKgEhr/Xmfwb1tbWrJUnMTDXpQzTGCGg0wghoJAgEBMIGVMH4x # CzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRt # b25kMR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xKDAmBgNVBAMTH01p # Y3Jvc29mdCBDb2RlIFNpZ25pbmcgUENBIDIwMTECEzMAAASEmOIS4HijMV0AAAAA # BIQwDQYJYIZIAWUDBAIBBQCgga4wGQYJKoZIhvcNAQkDMQwGCisGAQQBgjcCAQQw # HAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUwLwYJKoZIhvcNAQkEMSIEIAo5 # HSLgh1m3Y6szwxBFYFcMcKYpfd/JgKOgAAM3uT1rMEIGCisGAQQBgjcCAQwxNDAy # oBSAEgBNAGkAYwByAG8AcwBvAGYAdKEagBhodHRwOi8vd3d3Lm1pY3Jvc29mdC5j # b20wDQYJKoZIhvcNAQEBBQAEggEArc5trhqnm035gW35KS4PHyzUqVGBm7jDIAX/ # uyZ5BjMh/ADIM0Xr4yrmiPmV/vPxoZQKMa2lwQ/Y/Am/2THhwH1SLCRQM8CCqaWP # +s6ZoJxqP8siu1ln73PjezFYlIsKO3p7edLNktYRxgbN76IoruHSpfn+JUdLUsta # BoDdEqS8pxlTiCOFArGpnzGqabzNeHguXYRSpVBeyHnuvy0wTubkbGLHHPEnb4sc # YE/CGQBM6S0NyoaGRO4phadQNLYS7EzqwZnuU64fbgn63Vv5M1emWiIzNNFgNZUd # d7yPxA9Ur5vPoihs5JlgRQB8Yk8NDxExQrO49CwiZsfSW20fJqGCF5cwgheTBgor # BgEEAYI3AwMBMYIXgzCCF38GCSqGSIb3DQEHAqCCF3AwghdsAgEDMQ8wDQYJYIZI # AWUDBAIBBQAwggFSBgsqhkiG9w0BCRABBKCCAUEEggE9MIIBOQIBAQYKKwYBBAGE # WQoDATAxMA0GCWCGSAFlAwQCAQUABCCEGzxmmmKID0XR7YFEWfP+UcL8GOOlEkN4 # 5DI5VItlbQIGaKOhWNbJGBMyMDI1MDkxODA1MzYxOC4wOTlaMASAAgH0oIHRpIHO # MIHLMQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMH # UmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQL # ExxNaWNyb3NvZnQgQW1lcmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxk # IFRTUyBFU046N0YwMC0wNUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1l # LVN0YW1wIFNlcnZpY2WgghHtMIIHIDCCBQigAwIBAgITMwAAAgbXvFE4mCPsLAAB # AAACBjANBgkqhkiG9w0BAQsFADB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2Fz # aGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENv # cnBvcmF0aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAx # MDAeFw0yNTAxMzAxOTQyNTBaFw0yNjA0MjIxOTQyNTBaMIHLMQswCQYDVQQGEwJV # UzETMBEGA1UECBMKV2FzaGluZ3RvbjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UE # ChMVTWljcm9zb2Z0IENvcnBvcmF0aW9uMSUwIwYDVQQLExxNaWNyb3NvZnQgQW1l # cmljYSBPcGVyYXRpb25zMScwJQYDVQQLEx5uU2hpZWxkIFRTUyBFU046N0YwMC0w # NUUwLUQ5NDcxJTAjBgNVBAMTHE1pY3Jvc29mdCBUaW1lLVN0YW1wIFNlcnZpY2Uw # ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDpRIWbIM3Rlr397cjHaYx8 # 5l7I+ZVWGMCBCM911BpU6+IGWCqksqgqefZFEjKzNVDYC9YcgITAz276NGgvECm4 # ZfNv/FPwcaSDz7xbDbsOoxbwQoHUNRro+x5ubZhT6WJeU97F06+vDjAw/Yt1vWOg # RTqmP/dNr9oqIbE5oCLYdH3wI/noYmsJVc7966n+B7UAGAWU2se3Lz+xdxnNsNX4 # CR6zIMVJTSezP/2STNcxJTu9k2sl7/vzOhxJhCQ38rdaEoqhGHrXrmVkEhSv+S00 # DMJc1OIXxqfbwPjMqEVp7K3kmczCkbum1BOIJ2wuDAbKuJelpteNZj/S58NSQw6k # hfuJAluqHK3igkS/Oux49qTP+rU+PQeNuD+GtrCopFucRmanQvxISGNoxnBq3UeD # Tqphm6aI7GMHtFD6DOjJlllH1gVWXPTyivf+4tN8TmO6yIgB4uP00bH9jn/dyyxS # jxPQ2nGvZtgtqnvq3h3TRjRnkc+e1XB1uatDa1zUcS7r3iodTpyATe2hgkVX3m4D # hRzI6A4SJ6fbJM9isLH8AGKcymisKzYupAeFSTJ10JEFa6MjHQYYohoCF77R0CCw # MNjvE4XfLHu+qKPY8GQfsZdigQ9clUAiydFmVt61hytoxZP7LmXbzjD0VecyzZoL # 4Equ1XszBsulAr5Ld2KwcwIDAQABo4IBSTCCAUUwHQYDVR0OBBYEFO0wsLKdDGpT # 97cx3Iymyo/SBm4SMB8GA1UdIwQYMBaAFJ+nFV0AXmJdg/Tl0mWnG1M1GelyMF8G # A1UdHwRYMFYwVKBSoFCGTmh0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMv # Y3JsL01pY3Jvc29mdCUyMFRpbWUtU3RhbXAlMjBQQ0ElMjAyMDEwKDEpLmNybDBs # BggrBgEFBQcBAQRgMF4wXAYIKwYBBQUHMAKGUGh0dHA6Ly93d3cubWljcm9zb2Z0 # LmNvbS9wa2lvcHMvY2VydHMvTWljcm9zb2Z0JTIwVGltZS1TdGFtcCUyMFBDQSUy # MDIwMTAoMSkuY3J0MAwGA1UdEwEB/wQCMAAwFgYDVR0lAQH/BAwwCgYIKwYBBQUH # AwgwDgYDVR0PAQH/BAQDAgeAMA0GCSqGSIb3DQEBCwUAA4ICAQB23GZOfe9ThTUv # D29i4t6lDpxJhpVRMme+UbyZhBFCZhoGTtjDdphAArU2Q61WYg3YVcl2RdJm5PUb # Z2bA77zk+qtLxC+3dNxVsTcdtxPDSSWgwBHxTj6pCmoDNXolAYsWpvHQFCHDqEfA # iBxX1dmaXbiTP1d0XffvgR6dshUcqaH/mFfjDZAxLU1s6HcVgCvBQJlJ7xEG5jFK # dtqapKWcbUHwTVqXQGbIlHVClNJ3yqW6Z3UJH/CFcYiLV/e68urTmGtiZxGSYb4S # BSPArTrTYeHOlQIj/7loVWmfWX2y4AGV/D+MzyZMyvFw4VyL0Vgq96EzQKyteiVe # BaVEjxQKo3AcPULRF4Uzz98P2tCM5XbFZ3Qoj9PLg3rgFXr0oJEhfh2tqUrhTJd1 # 3+i4/fek9zWicoshlwXgFu002ZWBVzASEFuqED48qyulZ/2jGJBcta+Fdk2loP2K # 3oSj4PQQe1MzzVZO52AXO42MHlhm3SHo3/RhQ+I1A0Ny+9uAehkQH6LrxkrVNvZG # 4f0PAKMbqUcXG7xznKJ0x0HYr5ayWGbHKZRcObU+/34ZpL9NrXOedVDXmSd2ylKS # l/vvi1QwNJqXJl/+gJkQEetqmHAUFQkFtemi8MUXQG2w/RDHXXwWAjE+qIDZLQ/k # 4z2Z216tWaR6RDKHGkweCoDtQtzkHTCCB3EwggVZoAMCAQICEzMAAAAVxedrngKb # SZkAAAAAABUwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVTMRMwEQYDVQQI # EwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25kMR4wHAYDVQQKExVNaWNyb3Nv # ZnQgQ29ycG9yYXRpb24xMjAwBgNVBAMTKU1pY3Jvc29mdCBSb290IENlcnRpZmlj # YXRlIEF1dGhvcml0eSAyMDEwMB4XDTIxMDkzMDE4MjIyNVoXDTMwMDkzMDE4MzIy # NVowfDELMAkGA1UEBhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcT # B1JlZG1vbmQxHjAcBgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UE # AxMdTWljcm9zb2Z0IFRpbWUtU3RhbXAgUENBIDIwMTAwggIiMA0GCSqGSIb3DQEB # AQUAA4ICDwAwggIKAoICAQDk4aZM57RyIQt5osvXJHm9DtWC0/3unAcH0qlsTnXI # yjVX9gF/bErg4r25PhdgM/9cT8dm95VTcVrifkpa/rg2Z4VGIwy1jRPPdzLAEBjo # YH1qUoNEt6aORmsHFPPFdvWGUNzBRMhxXFExN6AKOG6N7dcP2CZTfDlhAnrEqv1y # aa8dq6z2Nr41JmTamDu6GnszrYBbfowQHJ1S/rboYiXcag/PXfT+jlPP1uyFVk3v # 3byNpOORj7I5LFGc6XBpDco2LXCOMcg1KL3jtIckw+DJj361VI/c+gVVmG1oO5pG # ve2krnopN6zL64NF50ZuyjLVwIYwXE8s4mKyzbnijYjklqwBSru+cakXW2dg3viS # kR4dPf0gz3N9QZpGdc3EXzTdEonW/aUgfX782Z5F37ZyL9t9X4C626p+Nuw2TPYr # bqgSUei/BQOj0XOmTTd0lBw0gg/wEPK3Rxjtp+iZfD9M269ewvPV2HM9Q07BMzlM # jgK8QmguEOqEUUbi0b1qGFphAXPKZ6Je1yh2AuIzGHLXpyDwwvoSCtdjbwzJNmSL # W6CmgyFdXzB0kZSU2LlQ+QuJYfM2BjUYhEfb3BvR/bLUHMVr9lxSUV0S2yW6r1AF # emzFER1y7435UsSFF5PAPBXbGjfHCBUYP3irRbb1Hode2o+eFnJpxq57t7c+auIu # rQIDAQABo4IB3TCCAdkwEgYJKwYBBAGCNxUBBAUCAwEAATAjBgkrBgEEAYI3FQIE # FgQUKqdS/mTEmr6CkTxGNSnPEP8vBO4wHQYDVR0OBBYEFJ+nFV0AXmJdg/Tl0mWn # G1M1GelyMFwGA1UdIARVMFMwUQYMKwYBBAGCN0yDfQEBMEEwPwYIKwYBBQUHAgEW # M2h0dHA6Ly93d3cubWljcm9zb2Z0LmNvbS9wa2lvcHMvRG9jcy9SZXBvc2l0b3J5 # Lmh0bTATBgNVHSUEDDAKBggrBgEFBQcDCDAZBgkrBgEEAYI3FAIEDB4KAFMAdQBi # AEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBTV # 9lbLj+iiXGJo0T2UkFvXzpoYxDBWBgNVHR8ETzBNMEugSaBHhkVodHRwOi8vY3Js # Lm1pY3Jvc29mdC5jb20vcGtpL2NybC9wcm9kdWN0cy9NaWNSb29DZXJBdXRfMjAx # MC0wNi0yMy5jcmwwWgYIKwYBBQUHAQEETjBMMEoGCCsGAQUFBzAChj5odHRwOi8v # d3d3Lm1pY3Jvc29mdC5jb20vcGtpL2NlcnRzL01pY1Jvb0NlckF1dF8yMDEwLTA2 # LTIzLmNydDANBgkqhkiG9w0BAQsFAAOCAgEAnVV9/Cqt4SwfZwExJFvhnnJL/Klv # 6lwUtj5OR2R4sQaTlz0xM7U518JxNj/aZGx80HU5bbsPMeTCj/ts0aGUGCLu6WZn # OlNN3Zi6th542DYunKmCVgADsAW+iehp4LoJ7nvfam++Kctu2D9IdQHZGN5tggz1 # bSNU5HhTdSRXud2f8449xvNo32X2pFaq95W2KFUn0CS9QKC/GbYSEhFdPSfgQJY4 # rPf5KYnDvBewVIVCs/wMnosZiefwC2qBwoEZQhlSdYo2wh3DYXMuLGt7bj8sCXgU # 6ZGyqVvfSaN0DLzskYDSPeZKPmY7T7uG+jIa2Zb0j/aRAfbOxnT99kxybxCrdTDF # NLB62FD+CljdQDzHVG2dY3RILLFORy3BFARxv2T5JL5zbcqOCb2zAVdJVGTZc9d/ # HltEAY5aGZFrDZ+kKNxnGSgkujhLmm77IVRrakURR6nxt67I6IleT53S0Ex2tVdU # CbFpAUR+fKFhbHP+CrvsQWY9af3LwUFJfn6Tvsv4O+S3Fb+0zj6lMVGEvL8CwYKi # excdFYmNcP7ntdAoGokLjzbaukz5m/8K6TT4JDVnK+ANuOaMmdbhIurwJ0I9JZTm # dHRbatGePu1+oDEzfbzL6Xu/OHBE0ZDxyKs6ijoIYn/ZcGNTTY3ugm2lBRDBcQZq # ELQdVTNYs6FwZvKhggNQMIICOAIBATCB+aGB0aSBzjCByzELMAkGA1UEBhMCVVMx # EzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAcBgNVBAoT # FU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjElMCMGA1UECxMcTWljcm9zb2Z0IEFtZXJp # Y2EgT3BlcmF0aW9uczEnMCUGA1UECxMeblNoaWVsZCBUU1MgRVNOOjdGMDAtMDVF # MC1EOTQ3MSUwIwYDVQQDExxNaWNyb3NvZnQgVGltZS1TdGFtcCBTZXJ2aWNloiMK # AQEwBwYFKw4DAhoDFQAEa0f118XHM/VNdqKBs4QXxNnN96CBgzCBgKR+MHwxCzAJ # BgNVBAYTAlVTMRMwEQYDVQQIEwpXYXNoaW5ndG9uMRAwDgYDVQQHEwdSZWRtb25k # MR4wHAYDVQQKExVNaWNyb3NvZnQgQ29ycG9yYXRpb24xJjAkBgNVBAMTHU1pY3Jv # c29mdCBUaW1lLVN0YW1wIFBDQSAyMDEwMA0GCSqGSIb3DQEBCwUAAgUA7HWprTAi # GA8yMDI1MDkxNzIxNDIwNVoYDzIwMjUwOTE4MjE0MjA1WjB3MD0GCisGAQQBhFkK # BAExLzAtMAoCBQDsdamtAgEAMAoCAQACAhGMAgH/MAcCAQACAhK3MAoCBQDsdvst # AgEAMDYGCisGAQQBhFkKBAIxKDAmMAwGCisGAQQBhFkKAwKgCjAIAgEAAgMHoSCh # CjAIAgEAAgMBhqAwDQYJKoZIhvcNAQELBQADggEBADB8oBFeMgRkxIRTt4KrF7gR # 3WygAModHuXoVVIX5IRzMrNhB/6T0WoVQhVL0j+bxqLLjMth44j5e6ipgkRfs518 # 9g1VZYeO56ExcjWF1FaQMi54BM0JTNFytrTgvB/SLCz85eVgby4KH5EVw47OJR7M # bS0x5r6Y/bUb1RXLkVA2Z3BivCScHsG8y1MuhJxMVincxAcyI42WErsXmv9B+SKL # hcH7ACeL3sXQYXU15ogESXrdJ9P2SyscCsAxRKSBrhdTqDirNfoqAWgJWJHLwvhr # /zJ0NKOqCUWGv+4myIcwxKvG+X9NLj41IESajU7t5KSH2scg8xHff/IU7kSpxWcx # ggQNMIIECQIBATCBkzB8MQswCQYDVQQGEwJVUzETMBEGA1UECBMKV2FzaGluZ3Rv # bjEQMA4GA1UEBxMHUmVkbW9uZDEeMBwGA1UEChMVTWljcm9zb2Z0IENvcnBvcmF0 # aW9uMSYwJAYDVQQDEx1NaWNyb3NvZnQgVGltZS1TdGFtcCBQQ0EgMjAxMAITMwAA # AgbXvFE4mCPsLAABAAACBjANBglghkgBZQMEAgEFAKCCAUowGgYJKoZIhvcNAQkD # MQ0GCyqGSIb3DQEJEAEEMC8GCSqGSIb3DQEJBDEiBCCbrGP+RYRcEo7FsQkvRC9s # NmyZ7ISsT06d8oa7Q5BQkTCB+gYLKoZIhvcNAQkQAi8xgeowgecwgeQwgb0EIODo # 9ZSIkZ6dVtKT+E/uZx2WAy7KiXM5R1JIOhNJf0vSMIGYMIGApH4wfDELMAkGA1UE # BhMCVVMxEzARBgNVBAgTCldhc2hpbmd0b24xEDAOBgNVBAcTB1JlZG1vbmQxHjAc # BgNVBAoTFU1pY3Jvc29mdCBDb3Jwb3JhdGlvbjEmMCQGA1UEAxMdTWljcm9zb2Z0 # IFRpbWUtU3RhbXAgUENBIDIwMTACEzMAAAIG17xROJgj7CwAAQAAAgYwIgQg6sq3 # k/M4Hp2UBBNbWdKwIOs9yeeEGTqRI3GpKcaJ4nQwDQYJKoZIhvcNAQELBQAEggIA # Ccy+MhKU9QqLW8k1XGIkasr9EQMQmU4fDjI2/GV5xIySiVcaFlPWNdmxzHXTsq5m # G8nb601hUBMlzfJnnrY6EcS4/NLvMirekhDO4HBi3ensVTIrUEMFRs53kBtaCK7P # 1FnGHQAh9LaZzgQCTX1ESQDcxrx/QpNiFXvNS7+3OCJLxtlR0gVeat9HHRvCpMW6 # H1Y4hCuG+ZxAVpCnviLFEgKGvXiXwcA2AB7+T6y/jADV/3OuMpCaOyDX6fSlNWYB # ECmKJ7nvzey1HgG6BFd2S+7VOD3B0UOxvVnrkJ+xd7Sh6kBi8V4QVcG8M0b3e4Iw # uuCBx9Ql6EMdiOgUnmuov60bvjLPOt7Vb4PIAWHYosmlQdqJyLwmNNYYIEvYtrt9 # IKEcLkwEcQ1cgs1jZLqjWDCMQWrqj650lnKOK0sbcfU2CsICs2qYhNwrv58YHiTp # pyGU4baoQGDzMewQjj2shAm7Ld8zmWH9lu2voYv/TTzB5MtI34EqfRvIOvOg+fBc # ea5OroJinxKCGODSpq39ZYbcZDdDthbt/iQS/82ZnUcPsASepRTxzrBWFMtQuwa3 # a/EEEQ9lCdrCNCXzcuwnLPD5Zwas3hsLJJhmYBSLIimI/3Bkl+0RvZA+rPUmlTzx # YDZSOOCRTaRXc+AU/QGE7htop3dV0r0ASKEP/9OL8Rg= # SIG # End signature block |