From 32f6a6eebc21e134e16e8fa8fb271f7cc4a70930 Mon Sep 17 00:00:00 2001 From: Wes Carroll Date: Thu, 3 Oct 2019 14:32:05 -0400 Subject: [PATCH 1/5] Update function to use new token parameter --- ZertoApiWrapper/Public/Add-ZertoPeerSite.ps1 | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/ZertoApiWrapper/Public/Add-ZertoPeerSite.ps1 b/ZertoApiWrapper/Public/Add-ZertoPeerSite.ps1 index ecf104e..9cbd5db 100644 --- a/ZertoApiWrapper/Public/Add-ZertoPeerSite.ps1 +++ b/ZertoApiWrapper/Public/Add-ZertoPeerSite.ps1 @@ -6,21 +6,30 @@ function Add-ZertoPeerSite { Mandatory = $true, HelpMessage = "Target Hostname or IP address to pair the localsite to." )] - [ValidateScript( {$_ -match [IPAddress]$_ } )] + [ValidateScript( { $_ -match [IPAddress]$_ } )] [string]$targetHost, [Parameter( HelpMessage = "Target communication port. Default is 9081" )] [ValidateRange(1024, 65535)] - [int]$targetPort = 9081 + [int]$targetPort = 9081, + [Parameter( + HelpMessage = "The generated token from the destination site. Note: This is only supported when both sites support pairing authentication. This was implemented to support ZVR 7.5 and later." + )] + [ValidateNotNullOrEmpty()] + [string]$token ) begin { - $baseUri = "peersites" - $body = @{"HostName" = $targetHost; "Port" = $targetPort} } process { + $baseUri = "peersites" + if ($PSBoundParameters.Keys.Contains("token")) { + $body = @{ "HostName" = $targetHost; "Port" = $targetPort; "Token" = $token } + } else { + $body = @{ "HostName" = $targetHost; "Port" = $targetPort } + } if ($PSCmdlet.ShouldProcess("Pairing with Site $targetHost")) { Invoke-ZertoRestRequest -uri $baseUri -body $($body | ConvertTo-Json) -method "POST" } From 0657607f3a7dd0de4ade430743cb1bbb6a97955d Mon Sep 17 00:00:00 2001 From: Wes Carroll Date: Thu, 3 Oct 2019 14:32:36 -0400 Subject: [PATCH 2/5] Update Tests to New format and add token parameter tests --- Tests/Public/Add-ZertoPeerSite.Tests.ps1 | 72 ++++++++++++++++-------- 1 file changed, 50 insertions(+), 22 deletions(-) diff --git a/Tests/Public/Add-ZertoPeerSite.Tests.ps1 b/Tests/Public/Add-ZertoPeerSite.Tests.ps1 index 35927f8..bdf4f52 100644 --- a/Tests/Public/Add-ZertoPeerSite.Tests.ps1 +++ b/Tests/Public/Add-ZertoPeerSite.Tests.ps1 @@ -9,34 +9,55 @@ Describe $global:function -Tag 'Unit', 'Source', 'Built' { Context "$global:function::Parameter Unit Tests" { - It "Has a mandatory string parameter for the target host" { - Get-Command $global:function | Should -HaveParameter TargetHost -Mandatory -Type String + It "$global:function should have exactly 16 parameters defined" { + (Get-Command $global:function).Parameters.Count | Should -Be 16 } - It "Will not take a non-ip address as a 'TargetHost'" { - { Add-ZertoPeerSite -targetHost 'MyZVMHost' -targetPort '9081' } | Should -Throw - { Add-ZertoPeerSite -targetHost '192.168.1.266' -targetPort '9081' } | Should -Throw - { Add-ZertoPeerSite -targetHost '192.168.1' -targetPort '9081' } | Should -Throw - { Add-ZertoPeerSite -targetHost $null -targetPort '9081' } | Should -Throw + $ParameterTestCases = @( + @{ParameterName = 'targetHost'; Type = 'String'; Mandatory = $true; Validation = 'Script' } + @{ParameterName = 'targetPort'; Type = 'Int32'; Mandatory = $false; Validation = 'Range' } + @{ParameterName = 'token'; Type = 'String'; Mandatory = $false; Validation = 'NotNullOrEmpty' } + ) + + It " parameter is of type" -TestCases $ParameterTestCases { + param($ParameterName, $Type, $Mandatory, $Validation) + Get-Command $global:function | Should -HaveParameter $ParameterName -Mandatory:$Mandatory -Type $Type } - It "Has a non-mandatory string parameter for the target port with default value of 9081" { - Get-Command Add-ZertoPeerSite | Should -HaveParameter TargetPort -Not -Mandatory - Get-Command Add-ZertoPeerSite | Should -HaveParameter TargetPort -Type Int32 - Get-Command Add-ZertoPeerSite | Should -HaveParameter TargetPort -DefaultValue 9081 + It " parameter has correct validation setting" -TestCases $ParameterTestCases { + param($ParameterName, $Validation) + Switch ($Validation) { + 'Script' { + $attrs = (Get-Command $global:function).Parameters[$ParameterName].Attributes + $attrs.Where{ $_ -is [ValidateScript] }.Count | Should -Be 1 + } + + 'Range' { + $attrs = (Get-Command $global:function).Parameters[$ParameterName].Attributes + $attrs.Where{ $_ -is [ValidateRange] }.Count | Should -Be 1 + } + + 'NotNullOrEmpty' { + $attrs = (Get-Command $global:function).Parameters[$ParameterName].Attributes + $attrs.Where{ $_ -is [ValidateNotNullOrEmpty] }.Count | Should -Be 1 + } + + default { + $true | Should be $false -Because "No Validation Selected. Review test cases" + } + } } - It "Will not take a non-int as a port" { - { Add-ZertoPeerSite -targetHost '192.168.1.100' -targetPort 'string' } | Should -Throw - { Add-ZertoPeerSite -targetHost '192.168.1.100' -targetPort $true } | Should -Throw - { Add-ZertoPeerSite -targetHost '192.168.1.100' -targetPort $null } | Should -Throw + It "targetPort Parameter should have a default value of 9081" { + Get-Command $global:function | Should -HaveParameter targetPort -DefaultValue 9081 } - It "Will fail if the specified port is outside of the range 1024 - 65535" { - { Add-ZertoPeerSite -targetHost '192.168.1.100' -targetPort 1023 } | Should -Throw - { Add-ZertoPeerSite -targetHost '192.168.1.100' -targetPort 65536 } | Should -Throw - { Add-ZertoPeerSite -targetHost '192.168.1.100' -targetPort 0 } | Should -Throw - { Add-ZertoPeerSite -targetHost '192.168.1.100' -targetPort -1 } | Should -Throw + It "targetPort Parameter should have a Min value of 1024" { + (Get-Command $global:function).Parameters['targetPort'].Attributes.Where{ $_ -is [ValidateRange] }.MinRange | Should Be 1024 + } + + It "targetPort Parameter should have a Max value of 65535" { + (Get-Command $global:function).Parameters['targetPort'].Attributes.Where{ $_ -is [ValidateRange] }.MaxRange | Should Be 65535 } It "Supports 'SupportsShouldProcess'" { @@ -52,19 +73,26 @@ Describe $global:function -Tag 'Unit', 'Source', 'Built' { return (Get-Content "$global:here\Mocks\TaskId.txt") } - It "Returns a string value" { + It "Returns a string value when no Token Passed" { $results = Add-ZertoPeerSite -targetHost '192.168.1.100' -targetPort '9081' $results | Should -Not -BeNullOrEmpty $results | Should -BeOfType "String" $results | Should -BeExactly "7e79035e-fb8c-47fe-815c-12ddd41708e6.3e4cdd0d-1064-4022-921f-6265ad6d335a" } + It "Returns a string value when a Token is passed" { + $results = Add-ZertoPeerSite -targetHost '192.168.1.100' -targetPort '9081' -token "NotARealTokenString" + $results | Should -Not -BeNullOrEmpty + $results | Should -BeOfType "String" + $results | Should -BeExactly "7e79035e-fb8c-47fe-815c-12ddd41708e6.3e4cdd0d-1064-4022-921f-6265ad6d335a" + } + It "Does not return a taskId if '-whatif' is used" { $results = Add-ZertoPeerSite -targetHost '192.168.1.100' -targetPort '9081' -WhatIf $results | Should -BeNullOrEmpty } - Assert-MockCalled -ModuleName ZertoApiWrapper -CommandName Invoke-ZertoRestRequest -Exactly 1 + Assert-MockCalled -ModuleName ZertoApiWrapper -CommandName Invoke-ZertoRestRequest -Exactly 2 } } Remove-Variable -Name here -Scope Global From 28fb42d56a493428a03fc3a356433e27c84e1f02 Mon Sep 17 00:00:00 2001 From: Wes Carroll Date: Thu, 3 Oct 2019 14:33:01 -0400 Subject: [PATCH 3/5] Update documentation for token parameter and example. --- docs/Add-ZertoPeerSite.md | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/docs/Add-ZertoPeerSite.md b/docs/Add-ZertoPeerSite.md index 2589547..7fafff4 100644 --- a/docs/Add-ZertoPeerSite.md +++ b/docs/Add-ZertoPeerSite.md @@ -13,7 +13,8 @@ Pairs the current Zerto Virtual Manager to the target Zerto Virtual Manager ## SYNTAX ``` -Add-ZertoPeerSite [-targetHost] [[-targetPort] ] [-WhatIf] [-Confirm] [] +Add-ZertoPeerSite [-targetHost] [[-targetPort] ] [-token ] [-WhatIf] [-Confirm] + [] ``` ## DESCRIPTION @@ -23,10 +24,17 @@ Pairs the current Zerto Virtual Manager to the target Zerto Virtual Manager by l ### Example 1 ```powershell -PS C:\> Add-ZertoPeerSite -targetHost "192.168.2.100" -targetPort "9081" +PS C:\> Add-ZertoPeerSite -targetHost "192.168.2.100" ``` -Pairs the current Zerto Virtual Manager to the Zerto Virtual Manager at IP address 192.168.2.100. +Pairs the current Zerto Virtual Manager to the Zerto Virtual Manager at IP address 192.168.2.100. Use this method when pairing Zerto Virtual Managers that are prior to version 7.5 + +### Example 2 +```powershell +PS C:\> Add-ZertoPeerSite -targetHost "192.168.2.100" -token "GeneratedFromTargetZVM" +``` + +Pairs the current Zerto Virtual Manager to the Zerto Virtual Manager at IP address 192.168.2.100. Use this method when pairing Zerto Virtual Managers that are version 7.5 or later. ## PARAMETERS @@ -61,6 +69,21 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -token +The generated token from the destination site. Note: This is only supported when both sites support pairing authentication. This was implemented to support ZVR 7.5 and later. + +```yaml +Type: String +Parameter Sets: (All) +Aliases: + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### -Confirm Prompts you for confirmation before running the cmdlet. From d78fc28b1ce219ab8a5cf6a40519b9333f8d970a Mon Sep 17 00:00:00 2001 From: Wes Carroll Date: Thu, 3 Oct 2019 14:33:17 -0400 Subject: [PATCH 4/5] Add ShouldProcess support to help file. --- docs/Import-ZertoVmNicSetting.md | 33 +++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/docs/Import-ZertoVmNicSetting.md b/docs/Import-ZertoVmNicSetting.md index f2a8d62..f16815a 100644 --- a/docs/Import-ZertoVmNicSetting.md +++ b/docs/Import-ZertoVmNicSetting.md @@ -13,7 +13,7 @@ Using a CSV file, will import updated Live and Test network settings for protect ## SYNTAX ``` -Import-ZertoVmNicSetting [-InputFile] [] +Import-ZertoVmNicSetting [-InputFile] [-WhatIf] [-Confirm] [] ``` ## DESCRIPTION @@ -47,6 +47,36 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -Confirm +Prompts you for confirmation before running the cmdlet. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: cf + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### -WhatIf +Shows what would happen if the cmdlet runs. The cmdlet is not run. + +```yaml +Type: SwitchParameter +Parameter Sets: (All) +Aliases: wi + +Required: False +Position: Named +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + ### CommonParameters This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). @@ -57,4 +87,5 @@ This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable ## NOTES ## RELATED LINKS + [Zerto Virtual Manager REST API VpgSettings end point documentation](http://s3.amazonaws.com/zertodownload_docs/Latest/Zerto%20Virtual%20Replication%20Zerto%20Virtual%20Manager%20%28ZVM%29%20-%20vSphere%20Online%20Help/index.html#page/RestfulAPIs%2FStatusAPIs.5.110.html%23) From 842c7ceeec0a1d74ac1b55250dacc8d964646f78 Mon Sep 17 00:00:00 2001 From: Wes Carroll Date: Thu, 3 Oct 2019 16:54:56 -0400 Subject: [PATCH 5/5] Added release notes for this update. --- RELEASENOTES.md | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/RELEASENOTES.md b/RELEASENOTES.md index a08b308..a1cfdee 100644 --- a/RELEASENOTES.md +++ b/RELEASENOTES.md @@ -2,17 +2,9 @@ ### Zerto Virtual Manager -* Added two functions to aid in bulk updating of NIC information for protected VMs. ([Issue 38](https://github.com/ZertoPublic/ZertoApiWrapper/issues/38)) - * [Export-ZertoVmNicSetting](https://github.com/ZertoPublic/ZertoApiWrapper/blob/Master/docs/Export-ZertoVmNicSettings.md) - * [Import-ZertoVmNicSetting](https://github.com/ZertoPublic/ZertoApiWrapper/blob/Master/docs/Import-ZertoVmNicSettings.md) -* Fixed an [issue](https://github.com/ZertoPublic/ZertoApiWrapper/issues/43) where a VPG being created with a single VM member would not be parsed by the API correctly using PowerShell 5.1 +* [Zerto version 7.5 has been released.](https://s3.amazonaws.com/zertodownload_docs/Latest/Zerto%20Virtual%20Replication%20Release%20Notes.pdf) As part of this release Zerto has added API functionality that requires the following updates. + * A token is now required to pair two sites together. The need is discussed in [Issue 46](https://github.com/ZertoPublic/ZertoApiWrapper/issues/46). To implement this change a `-token` parameter has been added to the `Add-ZertoPeerSite` function. ### Zerto Analytics -* Fixed an [issue](https://github.com/ZertoPublic/ZertoApiWrapper/issues/36) where the Zerto Analytics Rest Request function was not checking for the token before attempting a connection. -* Fixed an [issue](https://github.com/ZertoPublic/ZertoApiWrapper/issues/40) where the `Get-ZAVpg` method would return a 404 error when a `-vpgIdentifier` parameter was specified. - ### General Updates - -* Updated the way that tests are invoked and parsed to ensure that both source and built module files are tested. This will ensure that what is being shipped passes all tests along with testing of the source files. -* Added additional parameter validation tests to several of the functions. On-going effort to complete stand alone unit testing of each function.