diff --git a/CHANGELOG.md b/CHANGELOG.md index 4b7e3776d..d919d60a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,16 +18,30 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ### Changed +* Changed Get/Set Rubrik-Blackout to use correctly API version for Rubrik CDM 5.1 and later [Issue 679](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/679) +* Changed `Remove-RubrikUnmanagedObject` to use correct REST endpoint for Rubrik CDM 5.2 and later [Issue 671](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/671) + ### Added +* Added `Get-RubrikBlackout` cmdlet as requested in [Issue 688](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/688) +* Added additional example to `New-RubrikVolumeGroupMount` [Issue 660](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/660) +* Added additional example to `Invoke-RubrikRESTCall` [Issue 655](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/655) +* Added new cmdlet `Set-RubrikReport` to allow for changing settings on Rubrik Reports, and added associated unit tests [Issue 654](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/654) +* Added `DetailedObject` parameter & updated documentation for: `Get-RubrikDatabaseMount`, `Get-RubrikHyperVVM`, `Get-RubrikMount`, `Get-RubrikNutanixVM`, `Get-RubrikReport`, `Get-RubrikSLA`, `Get-RubrikUser`, `Get-RubrikVCenter`, `Get-RubrikVMwareDatastore`, `Get-RubrikVMwareHost` [Issue 651](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/651) +* Added additional example to `Get-RubrikVolumeGroup` [Issue 647](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/647) * New switch added to `Get-RubrikEvent` `-IncludeEventSeries` which determines if EventSeries events are included in the results [Issue 626](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/626) ### Fixed +* The `DynamicDNS` parameter of `New-RubrikLDAP` is no longer a mandatory parameter [Issue 662](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/662) +* Fixed `Test-RubrikSLA` internal function behaviour to no longer enforce `local` cluster ID when not supplied [Issue 659](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/659) +* WhatIf/Verbose messages for `Remove-RubrikSLA` will display SLA name and ID for additional clarification [Issue 653](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/653) +* Invoke-RubrikRestCall no longer takes Body object for Get Method [Issue 652](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/652) * Created entries for 5.2 endpoints in `Get-RubrikAPIData` private function for `Get-RubrikEvent` & `Get-RubrikEventSeries` which caused these cmdlets to no longer work on Rubrik CDM 5.2 [Issue 626](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/626) ### Deprecated +* The `Remove-RubrikOrgAuthorization` & `Set-RubrikOrgAuthorization` cmdlets no longer work in 5.2 because of API changes [Issue 681](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/681) * Functionality in `Get-RubrikEventSeries` is limited to only queries by specific EventSeries id on Rubrik CDM Clusters running versions higher than 5.2. Original functionality is still available for backwards compatibility with older versions of Rubrik CDM [Issue 626](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/626) ## [5.0.3](https://github.com/rubrikinc/rubrik-sdk-for-powershell/tree/5.0.3) - 2020-08-12 diff --git a/Rubrik/ObjectDefinitions/Rubrik.VMwareVmMount.ps1xml b/Rubrik/ObjectDefinitions/Rubrik.VMwareVmMount.ps1xml new file mode 100644 index 000000000..e0aa137e6 --- /dev/null +++ b/Rubrik/ObjectDefinitions/Rubrik.VMwareVmMount.ps1xml @@ -0,0 +1,49 @@ + + + + + Default + + Rubrik.VMwareVmMount + + + + + + + + + + + + + + + + + + + + + + (Get-RubrikVM -id $_.mountedVmId).name + + + + + (Get-RubrikVM -id $_.vmId).name + + + + snapshotDate + + + mountTimestamp + + + + + + + + \ No newline at end of file diff --git a/Rubrik/Private/Get-RubrikAPIData.ps1 b/Rubrik/Private/Get-RubrikAPIData.ps1 index a37730468..a4ef45529 100644 --- a/Rubrik/Private/Get-RubrikAPIData.ps1 +++ b/Rubrik/Private/Get-RubrikAPIData.ps1 @@ -236,6 +236,28 @@ function Get-RubrikAPIData { ObjectTName = 'Rubrik.AvailabilityGroup' } } + 'Get-RubrikBlackout' = @{ + '1.0' = @{ + Description = 'Whether global blackout window is active.' + URI = '/api/internal/blackout_window' + Method = 'Get' + Body = '' + Query = '' + Result = '' + Filter = '' + Success = '200' + } + '5.1' = @{ + Description = 'Whether global blackout window is active.' + URI = '/api/v1/blackout_window' + Method = 'Get' + Body = '' + Query = '' + Result = '' + Filter = '' + Success = '200' + } + } 'Get-RubrikClusterInfo' = @{ '4.2' = @{ Description = 'Retrieves advanced settings of the Rubrik cluster' @@ -814,6 +836,7 @@ function Get-RubrikAPIData { vmId = 'vmId' } Success = '200' + ObjectTName = 'Rubrik.VMwareVmMount' } } 'Get-RubrikNASShare' = @{ @@ -2661,6 +2684,22 @@ function Get-RubrikAPIData { Filter = '' Success = '204' } + '5.2' = @{ + Description = 'Bulk delete all unmanaged snapshots for the objects specified by objectId/objectType pairings.' + URI = '/api/v1/data_source/snapshot/bulk_delete' + Method = 'Post' + Body = @{ + objectDefinitions = @( + @{ + objectId = 'objectId' + } + ) + } + Query = '' + Result = '' + Filter = '' + Success = '204' + } } 'Remove-RubrikVCenter' = @{ '1.0' = @{ @@ -2773,6 +2812,18 @@ function Get-RubrikAPIData { Filter = '' Success = '200' } + '5.1' = @{ + Description = 'Whether to start or stop the global blackout window.' + URI = '/api/v1/blackout_window' + Method = 'Patch' + Body = @{ + isGlobalBlackoutActive = 'isGlobalBlackoutActive' + } + Query = '' + Result = '' + Filter = '' + Success = '200' + } } 'Set-RubrikDatabase' = @{ '1.0' = @{ diff --git a/Rubrik/Private/Submit-Request.ps1 b/Rubrik/Private/Submit-Request.ps1 index 2360c44f5..cb202ee9a 100644 --- a/Rubrik/Private/Submit-Request.ps1 +++ b/Rubrik/Private/Submit-Request.ps1 @@ -30,6 +30,11 @@ function Submit-Request { $body ) + # Block to improve readiability of error messages created for issue #653 + switch ($resources.Description) { + 'Delete an SLA Domain from a Rubrik cluster' {$id = "$name $id"} + } + if ($PSCmdlet.ShouldProcess($id, $resources.Description)) { try { Write-Verbose -Message 'Submitting the request' diff --git a/Rubrik/Private/Test-RubrikSLA.ps1 b/Rubrik/Private/Test-RubrikSLA.ps1 index efa982aa7..2c72e1035 100644 --- a/Rubrik/Private/Test-RubrikSLA.ps1 +++ b/Rubrik/Private/Test-RubrikSLA.ps1 @@ -22,16 +22,16 @@ The ID of the cluster to search #> - # Determine the state of $PrimaryClusterID - Write-Verbose -Message "Primary cluster ID currently set to: $PrimaryClusterID" - if (!$PrimaryClusterID) { - $PrimaryClusterID = 'local' - Write-Verbose -Message "Null value found. Setting primary cluster ID to $PrimaryClusterID" - } - Write-Verbose -Message 'Determining the SLA Domain id' if ($SLA) { - $slaid = (Get-RubrikSLA -SLA $SLA -PrimaryClusterID $PrimaryClusterID).id + $slaid = & { + $local:PSDefaultParameterValues = @{Disabled=$true} + if (-not [string]::IsNullOrWhiteSpace($PrimaryClusterID)) { + (Get-RubrikSLA -SLA $SLA -PrimaryClusterID $PrimaryClusterID).id + } else { + (Get-RubrikSLA -SLA $SLA).id + } + } if ($slaid -eq $null) { throw "No SLA Domains were found that match $SLA for $PrimaryClusterID" } diff --git a/Rubrik/Public/Get-RubrikBlackout.ps1 b/Rubrik/Public/Get-RubrikBlackout.ps1 new file mode 100644 index 000000000..b13d3345c --- /dev/null +++ b/Rubrik/Public/Get-RubrikBlackout.ps1 @@ -0,0 +1,65 @@ +#Requires -Version 3 +function Get-RubrikBlackout +{ + <# + .SYNOPSIS + The Get-RubrikBlackout cmdlet will retrieve cluster blackout windows information + + .DESCRIPTION + The Get-RubrikBlackout cmdlet will retrieve cluster blackout windows information + + .NOTES + Written by Jaap Brasser for community usage + Twitter: @jaap_brasser + GitHub: jaapbrasser + + .LINK + https://rubrik.gitbook.io/rubrik-sdk-for-powershell/command-documentation/reference/get-rubrikblackout + + .EXAMPLE + Get-RubrikBlackout + + This will return whether or not Global Blackout is active on the currently connected cluster + #> + + [CmdletBinding()] + Param( + # Rubrik server IP or FQDN + [String]$Server = $global:RubrikConnection.server, + # API version + [String]$api = $global:RubrikConnection.api + ) + + Begin { + + # The Begin section is used to perform one-time loads of data necessary to carry out the function's purpose + # If a command needs to be run with each iteration or pipeline input, place it in the Process section + + # Check to ensure that a session to the Rubrik cluster exists and load the needed header data for authentication + Test-RubrikConnection + + # API data references the name of the function + # For convenience, that name is saved here to $function + $function = $MyInvocation.MyCommand.Name + + # Retrieve all of the URI, method, body, query, result, filter, and success details for the API endpoint + Write-Verbose -Message "Gather API Data for $function" + $resources = Get-RubrikAPIData -endpoint $function + Write-Verbose -Message "Load API data for $($resources.Function)" + Write-Verbose -Message "Description: $($resources.Description)" + + } + + Process { + + $uri = New-URIString -server $Server -endpoint ($resources.URI) -id $id + $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri + $body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) + $result = Submit-Request -uri $uri -header $Header -method $($resources.Method) -body $body + $result = Test-ReturnFormat -api $api -result $result -location $resources.Result + $result = Test-FilterObject -filter ($resources.Filter) -result $result + + return $result + + } # End of process +} # End of function \ No newline at end of file diff --git a/Rubrik/Public/Get-RubrikDatabaseMount.ps1 b/Rubrik/Public/Get-RubrikDatabaseMount.ps1 index c255cd083..a3e2a93bd 100644 --- a/Rubrik/Public/Get-RubrikDatabaseMount.ps1 +++ b/Rubrik/Public/Get-RubrikDatabaseMount.ps1 @@ -19,22 +19,32 @@ function Get-RubrikDatabaseMount .EXAMPLE Get-RubrikDatabaseMount + This will return details on all mounted databases. + .EXAMPLE + Get-RubrikDatabaseMount -DetailedObject + + This will return mounted databases with the full detailed objects. + .EXAMPLE Get-RubrikDatabaseMount -id '11111111-2222-3333-4444-555555555555' + This will return details on mount id "11111111-2222-3333-4444-555555555555". .EXAMPLE Get-RubrikDatabaseMount -source_database_id (Get-RubrikDatabase -HostName FOO -Instance MSSQLSERVER -Database BAR).id + This will return details for any mounts found using the id value from a database named BAR on the FOO default instance. .EXAMPLE Get-RubrikDatabaseMount -source_database_name BAR + This returns any mounts where the source database is named BAR. .EXAMPLE Get-RubrikDatabaseMount -mounted_database_name BAR_LM + This returns any mounts with the name BAR_LM #> @@ -56,6 +66,8 @@ function Get-RubrikDatabaseMount [Alias('mounted_database_name')] [Parameter(Position = 0)] [String]$MountedDatabaseName, + # DetailedObject will retrieved the detailed DatabaseMount object, the default behavior of the API is to only retrieve a subset of the full DatabaseMount object unless we query directly by ID. Using this parameter does affect performance as more data will be retrieved and more API-queries will be performed. + [Switch]$DetailedObject, # Rubrik server IP or FQDN [String]$Server = $global:RubrikConnection.server, # API version @@ -91,8 +103,18 @@ function Get-RubrikDatabaseMount $result = Submit-Request -uri $uri -header $Header -method $($resources.Method) -body $body $result = Test-ReturnFormat -api $api -result $result -location $resources.Result $result = Test-FilterObject -filter ($resources.Filter) -result $result - $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result - return $result + if (($DetailedObject) -and (-not $PSBoundParameters.containskey('id'))) { + for ($i = 0; $i -lt @($result).Count; $i++) { + $Percentage = [int]($i/@($result).count*100) + Write-Progress -Activity "DetailedObject queries in Progress, $($i+1) out of $(@($result).count)" -Status "$Percentage% Complete:" -PercentComplete $Percentage + if ($result) { + Get-RubrikDatabaseMount -id $result[$i].id + } + } + } else { + $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result + return $result + } } # End of process } # End of function \ No newline at end of file diff --git a/Rubrik/Public/Get-RubrikHyperVVM.ps1 b/Rubrik/Public/Get-RubrikHyperVVM.ps1 index 835663659..d40eaff14 100644 --- a/Rubrik/Public/Get-RubrikHyperVVM.ps1 +++ b/Rubrik/Public/Get-RubrikHyperVVM.ps1 @@ -18,14 +18,22 @@ function Get-RubrikHyperVVM .EXAMPLE Get-RubrikHyperVVM -Name 'Server1' + This will return details on all Hyper-V virtual machines named "Server1". .EXAMPLE Get-RubrikHyperVVM -Name 'Server1' -SLA Gold + This will return details on all Hyper-V virtual machines named "Server1" that are protected by the Gold SLA Domain. + .EXAMPLE + Get-RubrikHyperVVM -Name 'Server1' -DetailedObject + + This will return all Hyper-V virtual machines named "Server1" and returns the Detailed Objects of these VMs + .EXAMPLE Get-RubrikHyperVVM -Relic + This will return all removed Hyper-V virtual machines that were formerly protected by Rubrik. #> @@ -65,6 +73,8 @@ function Get-RubrikHyperVVM [Parameter(ParameterSetName='Query')] [Alias('effective_sla_domain_id')] [String]$SLAID, + # DetailedObject will retrieved the detailed Hyper-V VM object, the default behavior of the API is to only retrieve a subset of the full Hyper-V VM object unless we query directly by ID. Using this parameter does affect performance as more data will be retrieved and more API-queries will be performed. + [Switch]$DetailedObject, # Rubrik server IP or FQDN [Parameter(ParameterSetName='Query')] [Parameter(ParameterSetName='ID')] @@ -110,10 +120,18 @@ function Get-RubrikHyperVVM $result = Submit-Request -uri $uri -header $Header -method $($resources.Method) -body $body $result = Test-ReturnFormat -api $api -result $result -location $resources.Result $result = Test-FilterObject -filter ($resources.Filter) -result $result - $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result - - - return $result + if (($DetailedObject) -and (-not $PSBoundParameters.containskey('id'))) { + for ($i = 0; $i -lt @($result).Count; $i++) { + $Percentage = [int]($i/@($result).count*100) + Write-Progress -Activity "DetailedObject queries in Progress, $($i+1) out of $(@($result).count)" -Status "$Percentage% Complete:" -PercentComplete $Percentage + if ($result) { + Get-RubrikHyperVVM -id $result[$i].id + } + } + } else { + $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result + return $result + } } # End of process } # End of function \ No newline at end of file diff --git a/Rubrik/Public/Get-RubrikMount.ps1 b/Rubrik/Public/Get-RubrikMount.ps1 index 896ee76d4..b6b105f87 100644 --- a/Rubrik/Public/Get-RubrikMount.ps1 +++ b/Rubrik/Public/Get-RubrikMount.ps1 @@ -21,18 +21,27 @@ function Get-RubrikMount .EXAMPLE Get-RubrikMount + This will return details on all mounted virtual machines. + .EXAMPLE + Get-RubrikMount -DetailedObject + + This will retrieve all mounted virtual machines with additional details + .EXAMPLE Get-RubrikMount -id '11111111-2222-3333-4444-555555555555' + This will return details on mount id "11111111-2222-3333-4444-555555555555". .EXAMPLE Get-RubrikMount -VMID (Get-RubrikVM -VM 'Server1').id + This will return details for any mounts found using the id value from a virtual machine named "Server1" as a base reference. .EXAMPLE Get-RubrikMount -VMID 'VirtualMachine:::aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee-vm-12345' + This will return details for any mounts found using the virtual machine id of 'VirtualMachine:::aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee-vm-12345' as a base reference. #> @@ -44,6 +53,8 @@ function Get-RubrikMount # Filters live mounts by VM ID [Alias('vm_id')] [String]$VMID, + # DetailedObject will retrieved the detailed VM Mount object, the default behavior of the API is to only retrieve a subset of the full VM Mount object unless we query directly by ID. Using this parameter does affect performance as more data will be retrieved and more API-queries will be performed. + [Switch]$DetailedObject, # Rubrik server IP or FQDN [String]$Server = $global:RubrikConnection.server, # API version @@ -80,7 +91,17 @@ function Get-RubrikMount $result = Test-ReturnFormat -api $api -result $result -location $resources.Result $result = Test-FilterObject -filter ($resources.Filter) -result $result - return $result - + if (($DetailedObject) -and (-not $PSBoundParameters.containskey('id'))) { + for ($i = 0; $i -lt @($result).Count; $i++) { + $Percentage = [int]($i/@($result).count*100) + Write-Progress -Activity "DetailedObject queries in Progress, $($i+1) out of $(@($result).count)" -Status "$Percentage% Complete:" -PercentComplete $Percentage + if ($result) { + Get-RubrikMount -id $result[$i].id + } + } + } else { + $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result + return $result + } } # End of process } # End of function \ No newline at end of file diff --git a/Rubrik/Public/Get-RubrikNutanixVM.ps1 b/Rubrik/Public/Get-RubrikNutanixVM.ps1 index 6a1472ccc..a3e275020 100644 --- a/Rubrik/Public/Get-RubrikNutanixVM.ps1 +++ b/Rubrik/Public/Get-RubrikNutanixVM.ps1 @@ -18,14 +18,22 @@ function Get-RubrikNutanixVM .EXAMPLE Get-RubrikNutanixVM -Name 'Server1' + This will return details on all Nutanix (AHV) virtual machines named "Server1". .EXAMPLE Get-RubrikNutanixVM -Name 'Server1' -SLA Gold + This will return details on all Nutanix (AHV) virtual machines named "Server1" that are protected by the Gold SLA Domain. + .EXAMPLE + Get-RubrikNutanixVM -Name 'Server1' -DetailedObject + + This will return all Nutanix (AHV) virtual machines named "Server1" and returns the Detailed Objects of these VMs + .EXAMPLE Get-RubrikNutanixVM -Relic + This will return all removed Nutanix (AHV) virtual machines that were formerly protected by Rubrik. #> @@ -65,6 +73,8 @@ function Get-RubrikNutanixVM [Parameter(ParameterSetName='Query')] [Alias('effective_sla_domain_id')] [String]$SLAID, + # DetailedObject will retrieved the detailed Nutanix VM object, the default behavior of the API is to only retrieve a subset of the full Nutanix VM object unless we query directly by ID. Using this parameter does affect performance as more data will be retrieved and more API-queries will be performed. + [Switch]$DetailedObject, # Rubrik server IP or FQDN [Parameter(ParameterSetName='Query')] [Parameter(ParameterSetName='ID')] @@ -110,9 +120,18 @@ function Get-RubrikNutanixVM $result = Submit-Request -uri $uri -header $Header -method $($resources.Method) -body $body $result = Test-ReturnFormat -api $api -result $result -location $resources.Result $result = Test-FilterObject -filter ($resources.Filter) -result $result - $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result - - return $result + if (($DetailedObject) -and (-not $PSBoundParameters.containskey('id'))) { + for ($i = 0; $i -lt @($result).Count; $i++) { + $Percentage = [int]($i/@($result).count*100) + Write-Progress -Activity "DetailedObject queries in Progress, $($i+1) out of $(@($result).count)" -Status "$Percentage% Complete:" -PercentComplete $Percentage + if ($result) { + Get-RubrikNutanixVM -id $result[$i].id + } + } + } else { + $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result + return $result + } } # End of process } # End of function \ No newline at end of file diff --git a/Rubrik/Public/Get-RubrikReport.ps1 b/Rubrik/Public/Get-RubrikReport.ps1 index 82059fe62..695da2f34 100644 --- a/Rubrik/Public/Get-RubrikReport.ps1 +++ b/Rubrik/Public/Get-RubrikReport.ps1 @@ -18,14 +18,22 @@ function Get-RubrikReport .EXAMPLE Get-RubrikReport + This will return details on all reports - + + .EXAMPLE + Get-RubrikReport -DetailedObject + + This will return full details on all reports + .EXAMPLE Get-RubrikReport -Name 'SLA' -Type Custom + This will return details on all custom reports that contain the string "SLA" .EXAMPLE Get-RubrikReport -id '11111111-2222-3333-4444-555555555555' + This will return details on the report id "11111111-2222-3333-4444-555555555555" #> @@ -41,6 +49,8 @@ function Get-RubrikReport # The ID of the report. [Parameter(ValueFromPipelineByPropertyName = $true)] [String]$id, + # DetailedObject will retrieved the detailed Rubrik Report object, the default behavior of the API is to only retrieve a subset of the full Rubrik Report object unless we query directly by ID. Using this parameter does affect performance as more data will be retrieved and more API-queries will be performed. + [Switch]$DetailedObject, # Rubrik server IP or FQDN [String]$Server = $global:RubrikConnection.server, # API version @@ -75,9 +85,18 @@ function Get-RubrikReport $result = Submit-Request -uri $uri -header $Header -method $($resources.Method) -body $body $result = Test-ReturnFormat -api $api -result $result -location $resources.Result $result = Test-FilterObject -filter ($resources.Filter) -result $result - $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result - - return $result + if (($DetailedObject) -and (-not $PSBoundParameters.containskey('id'))) { + for ($i = 0; $i -lt @($result).Count; $i++) { + $Percentage = [int]($i/@($result).count*100) + Write-Progress -Activity "DetailedObject queries in Progress, $($i+1) out of $(@($result).count)" -Status "$Percentage% Complete:" -PercentComplete $Percentage + if ($result) { + Get-RubrikReport -id $result[$i].id + } + } + } else { + $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result + return $result + } } # End of process } # End of function \ No newline at end of file diff --git a/Rubrik/Public/Get-RubrikSLA.ps1 b/Rubrik/Public/Get-RubrikSLA.ps1 index fbbdf593d..2efe0f6cb 100644 --- a/Rubrik/Public/Get-RubrikSLA.ps1 +++ b/Rubrik/Public/Get-RubrikSLA.ps1 @@ -19,11 +19,18 @@ function Get-RubrikSLA .EXAMPLE Get-RubrikSLA + Will return all known SLA Domains .EXAMPLE Get-RubrikSLA -Name 'Gold' + Will return details on the SLA Domain named Gold + + .EXAMPLE + Get-RubrikSLA -Name 'Gold' -DetailedObject + + Will return information the SLA Domain named Gold, including full details on this SLA #> [CmdletBinding(DefaultParameterSetName = 'Query')] @@ -47,6 +54,8 @@ function Get-RubrikSLA ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [String]$id, + # DetailedObject will retrieved the detailed SLA object, the default behavior of the API is to only retrieve a subset of the full SLA object unless we query directly by ID. Using this parameter does affect performance as more data will be retrieved and more API-queries will be performed. + [Switch]$DetailedObject, # Rubrik server IP or FQDN [Parameter(ParameterSetName='Query')] [Parameter(ParameterSetName='ID')] @@ -85,9 +94,18 @@ function Get-RubrikSLA $result = Test-ReturnFormat -api $api -result $result -location $resources.Result $result = Test-FilterObject -filter ($resources.Filter) -result $result $result = $result | Select-Object -Property *,@{N="FrequencySummary";E={Get-RubrikSLAFrequencySummary -SLADomain $_}} - $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result - - return $result + if (($DetailedObject) -and (-not $PSBoundParameters.containskey('id'))) { + for ($i = 0; $i -lt @($result).Count; $i++) { + $Percentage = [int]($i/@($result).count*100) + Write-Progress -Activity "DetailedObject queries in Progress, $($i+1) out of $(@($result).count)" -Status "$Percentage% Complete:" -PercentComplete $Percentage + if ($result) { + Get-RubrikSLA -id $result[$i].id + } + } + } else { + $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result + return $result + } } # End of process } # End of function \ No newline at end of file diff --git a/Rubrik/Public/Get-RubrikUser.ps1 b/Rubrik/Public/Get-RubrikUser.ps1 index b5386665a..e82e1ad0b 100644 --- a/Rubrik/Public/Get-RubrikUser.ps1 +++ b/Rubrik/Public/Get-RubrikUser.ps1 @@ -18,22 +18,32 @@ function Get-RubrikUser .EXAMPLE Get-RubrikUser + This will return settings of all of the user accounts (local and LDAP) configured within the Rubrik cluster. .EXAMPLE Get-RubrikUser -authDomainId 'local' + This will return settings of all of the user accounts belonging to the local authoriation domain. .EXAMPLE Get-RubrikUser -username 'john.doe' + This will return settings for the user account with the username of john.doe configured within the Rubrik cluster. + .EXAMPLE + Get-RubrikUser -username 'john.doe' -DetailedObject + + This will return full details of the settings for the user account with the username of john.doe configured within the Rubrik cluster. + .EXAMPLE Get-RubrikUser -authDomainId '1111-222-333' + This will return settings of all of the user accounts belonging to the specified authoriation domain. .EXAMPLE Get-RubrikUser -id '1111-22222-33333-4444-5555' + This will return detailed information about the user with the specified ID. #> @@ -55,6 +65,8 @@ function Get-RubrikUser Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [String]$Id, + # DetailedObject will retrieved the detailed User object, the default behavior of the API is to only retrieve a subset of the full User object unless we query directly by ID. Using this parameter does affect performance as more data will be retrieved and more API-queries will be performed. + [Switch]$DetailedObject, # Rubrik server IP or FQDN [Parameter(ParameterSetName='Query')] [Parameter(ParameterSetName='ID')] @@ -97,9 +109,18 @@ function Get-RubrikUser $result = Submit-Request -uri $uri -header $Header -method $($resources.Method) -body $body $result = Test-ReturnFormat -api $api -result $result -location $resources.Result $result = Test-FilterObject -filter ($resources.Filter) -result $result - $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result - - return $result + if (($DetailedObject) -and (-not $PSBoundParameters.containskey('id'))) { + for ($i = 0; $i -lt @($result).Count; $i++) { + $Percentage = [int]($i/@($result).count*100) + Write-Progress -Activity "DetailedObject queries in Progress, $($i+1) out of $(@($result).count)" -Status "$Percentage% Complete:" -PercentComplete $Percentage + if ($result) { + Get-RubrikUser -id $result[$i].id + } + } + } else { + $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result + return $result + } } # End of process } # End of function \ No newline at end of file diff --git a/Rubrik/Public/Get-RubrikVCenter.ps1 b/Rubrik/Public/Get-RubrikVCenter.ps1 index 20f39dbe0..8c5ab3328 100644 --- a/Rubrik/Public/Get-RubrikVCenter.ps1 +++ b/Rubrik/Public/Get-RubrikVCenter.ps1 @@ -16,7 +16,13 @@ function Get-RubrikVCenter .EXAMPLE Get-RubrikVCenter + This will return the vCenter settings on the currently connected Rubrik cluster + + .EXAMPLE + Get-RubrikVCenter -DetailedObject + + This will return the detailed vCenter settings from currently connected Rubrik cluster #> [CmdletBinding()] @@ -25,9 +31,17 @@ function Get-RubrikVCenter [String]$Name, # Rubrik server IP or FQDN [String]$Server = $global:RubrikConnection.server, + # vCenter id + [Parameter( + ValueFromPipelineByPropertyName = $true + )] + [ValidateNotNullOrEmpty()] + [String]$id, # Filter the summary information based on the primarycluster_id of the primary Rubrik cluster. Use 'local' as the primary_cluster_id of the Rubrik cluster that is hosting the current REST API session. [Alias('primary_cluster_id')] - [String]$PrimaryClusterID, + [String]$PrimaryClusterID, + # DetailedObject will retrieved the detailed Nutanix VM object, the default behavior of the API is to only retrieve a subset of the full Nutanix VM object unless we query directly by ID. Using this parameter does affect performance as more data will be retrieved and more API-queries will be performed. + [Switch]$DetailedObject, # API version [ValidateNotNullorEmpty()] [String]$api = $global:RubrikConnection.api @@ -61,9 +75,18 @@ function Get-RubrikVCenter $result = Submit-Request -uri $uri -header $Header -method $($resources.Method) -body $body $result = Test-ReturnFormat -api $api -result $result -location $resources.Result $result = Test-FilterObject -filter ($resources.Filter) -result $result - $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result - - return $result + if (($DetailedObject) -and (-not $PSBoundParameters.containskey('id'))) { + for ($i = 0; $i -lt @($result).Count; $i++) { + $Percentage = [int]($i/@($result).count*100) + Write-Progress -Activity "DetailedObject queries in Progress, $($i+1) out of $(@($result).count)" -Status "$Percentage% Complete:" -PercentComplete $Percentage + if ($result) { + Get-RubrikVCenter -id $result[$i].id + } + } + } else { + $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result + return $result + } } # End of process } # End of function \ No newline at end of file diff --git a/Rubrik/Public/Get-RubrikVMSnapshot.ps1 b/Rubrik/Public/Get-RubrikVMSnapshot.ps1 index 762459852..cd95e4301 100644 --- a/Rubrik/Public/Get-RubrikVMSnapshot.ps1 +++ b/Rubrik/Public/Get-RubrikVMSnapshot.ps1 @@ -17,6 +17,7 @@ function Get-RubrikVMSnapshot .EXAMPLE Get-RubrikVMSnapshot -id 'cc1b363a-a0d4-40b7-9b09-7b8f3a805b27' + This will return details on the specific snapshot. #> diff --git a/Rubrik/Public/Get-RubrikVMwareDatastore.ps1 b/Rubrik/Public/Get-RubrikVMwareDatastore.ps1 index 5b4442553..eecba38a5 100644 --- a/Rubrik/Public/Get-RubrikVMwareDatastore.ps1 +++ b/Rubrik/Public/Get-RubrikVMwareDatastore.ps1 @@ -18,14 +18,22 @@ function Get-RubrikVMwareDatastore .EXAMPLE Get-RubrikVMwareDatastore + This will return a listing of all of the datastores known to a connected Rubrik cluster .EXAMPLE Get-RubrikVMwareDatastore -Name 'vSAN' + This will return a listing of all of the datastores named 'vSAN' known to a connected Rubrik cluster + .EXAMPLE + Get-RubrikVMwareDatastore -Name 'vSAN' -DetailedObject + + This will return a listing of all of the datastores named 'vSAN' known to a connected Rubrik cluster with fully detailed objects + .EXAMPLE Get-RubrikVMwareDatastore -DatastoreType 'NFS' + This will return a listing of all of the NFS datastores known to a connected Rubrik cluster #> @@ -35,9 +43,16 @@ function Get-RubrikVMwareDatastore [Parameter( Position = 0)] [String]$Name, + # Datastore id + [Parameter( + ValueFromPipelineByPropertyName = $true)] + [ValidateNotNullOrEmpty()] + [String]$id, # Filter Datastore type [ValidateSet('VMFS', 'NFS','vSAN')] [String]$DatastoreType, + # DetailedObject will retrieved the detailed VMware Datastore object, the default behavior of the API is to only retrieve a subset of the full VMware Datastore object unless we query directly by ID. Using this parameter does affect performance as more data will be retrieved and more API-queries will be performed. + [Switch]$DetailedObject, # Rubrik server IP or FQDN [String]$Server = $global:RubrikConnection.server, # API version @@ -73,9 +88,18 @@ function Get-RubrikVMwareDatastore $result = Submit-Request -uri $uri -header $Header -method $($resources.Method) -body $body $result = Test-ReturnFormat -api $api -result $result -location $resources.Result $result = Test-FilterObject -filter ($resources.Filter) -result $result - $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result - - return $result + if (($DetailedObject) -and (-not $PSBoundParameters.containskey('id'))) { + for ($i = 0; $i -lt @($result).Count; $i++) { + $Percentage = [int]($i/@($result).count*100) + Write-Progress -Activity "DetailedObject queries in Progress, $($i+1) out of $(@($result).count)" -Status "$Percentage% Complete:" -PercentComplete $Percentage + if ($result) { + Get-RubrikVMwareDatastore -id $result[$i].id + } + } + } else { + $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result + return $result + } } # End of process } # End of function \ No newline at end of file diff --git a/Rubrik/Public/Get-RubrikVMwareHost.ps1 b/Rubrik/Public/Get-RubrikVMwareHost.ps1 index 0bf25b9fe..899e1c104 100644 --- a/Rubrik/Public/Get-RubrikVMwareHost.ps1 +++ b/Rubrik/Public/Get-RubrikVMwareHost.ps1 @@ -18,14 +18,23 @@ function Get-RubrikVMwareHost .EXAMPLE Get-RubrikVMwareHost + This will return a listing of all of the ESXi hosts known to the connected Rubrik cluster + .EXAMPLE Get-RubrikVMwareHost -PrimarClusterId local + This will return a listing of all of the ESXi hosts whose primary cluster is that of the connected Rubrik cluster. .EXAMPLE Get-RubrikVMwareHost -Name 'esxi01' + This will return a listing of all of the ESXi hosts named 'esxi01' registered with the connected Rubrik cluster + + .EXAMPLE + Get-RubrikVMwareHost -Name 'esxi01' -DetailedObject + + This will return a listing of all of the ESXi hosts named 'esxi01' registered with the connected Rubrik cluster with fully detailed objects #> [CmdletBinding()] @@ -34,11 +43,18 @@ function Get-RubrikVMwareHost [Parameter( Position = 0)] [String]$Name, + # Datastore id + [Parameter( + ValueFromPipelineByPropertyName = $true)] + [ValidateNotNullOrEmpty()] + [String]$id, # Rubrik server IP or FQDN [String]$Server = $global:RubrikConnection.server, # Filter the summary information based on the primarycluster_id of the primary Rubrik cluster. Use 'local' as the primary_cluster_id of the Rubrik cluster that is hosting the current REST API session. [Alias('primary_cluster_id')] [String]$PrimaryClusterID, + # DetailedObject will retrieved the detailed VMware Host object, the default behavior of the API is to only retrieve a subset of the full VMware Host object unless we query directly by ID. Using this parameter does affect performance as more data will be retrieved and more API-queries will be performed. + [Switch]$DetailedObject, # API version [ValidateNotNullorEmpty()] [String]$api = $global:RubrikConnection.api @@ -72,9 +88,18 @@ function Get-RubrikVMwareHost $result = Submit-Request -uri $uri -header $Header -method $($resources.Method) -body $body $result = Test-ReturnFormat -api $api -result $result -location $resources.Result $result = Test-FilterObject -filter ($resources.Filter) -result $result - $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result - - return $result + if (($DetailedObject) -and (-not $PSBoundParameters.containskey('id'))) { + for ($i = 0; $i -lt @($result).Count; $i++) { + $Percentage = [int]($i/@($result).count*100) + Write-Progress -Activity "DetailedObject queries in Progress, $($i+1) out of $(@($result).count)" -Status "$Percentage% Complete:" -PercentComplete $Percentage + if ($result) { + Get-RubrikVMwareHost -id $result[$i].id + } + } + } else { + $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result + return $result + } } # End of process } # End of function \ No newline at end of file diff --git a/Rubrik/Public/Get-RubrikVolumeGroup.ps1 b/Rubrik/Public/Get-RubrikVolumeGroup.ps1 index 7a5513478..a7e984d86 100644 --- a/Rubrik/Public/Get-RubrikVolumeGroup.ps1 +++ b/Rubrik/Public/Get-RubrikVolumeGroup.ps1 @@ -15,24 +15,34 @@ function Get-RubrikVolumeGroup .LINK https://rubrik.gitbook.io/rubrik-sdk-for-powershell/command-documentation/reference/get-rubrikvolumegroup + .EXAMPLE + Get-RubrikVolumeGroup -Name 'Quokka volumes' + + This will return details of the volume group named "Quokka Volumes" + .EXAMPLE Get-RubrikVolumeGroup -Hostname 'Server1' + This will return details on all volume groups from host "Server1". .EXAMPLE Get-RubrikVolumeGroup -Hostname 'Server1' -SLA Gold + This will return details on all volume groups of "Server1" that are protected by the Gold SLA Domain. .EXAMPLE Get-RubrikVolumeGroup -Relic + This will return all removed volume groups that were formerly protected by Rubrik. .EXAMPLE Get-RubrikVolumeGroup -DetailedObject + This will return full details on all volume groups available on the Rubrik Cluster, this query will take longer as multiple API calls are required. The 'Includes' property will be populated .EXAMPLE Get-RubrikVolumeGroup -Id VolumeGroup:::205b0b65-b90c-48c5-9cab-66b95ed18c0f + This will return full details on for the specified VolumeGroup ID #> @@ -101,8 +111,6 @@ function Get-RubrikVolumeGroup $result = Test-ReturnFormat -api $api -result $result -location $resources.Result $result = Test-FilterObject -filter ($resources.Filter) -result $result - - # If the Get-RubrikVolumeGroup function has been called with the -DetailedObject parameter a separate API query will be performed if the initial query was not based on ID if (($DetailedObject) -and (-not $PSBoundParameters.containskey('id'))) { for ($i = 0; $i -lt @($result).Count; $i++) { diff --git a/Rubrik/Public/Invoke-RubrikRESTCall.ps1 b/Rubrik/Public/Invoke-RubrikRESTCall.ps1 index fb03556ea..4ff39a1f7 100644 --- a/Rubrik/Public/Invoke-RubrikRESTCall.ps1 +++ b/Rubrik/Public/Invoke-RubrikRESTCall.ps1 @@ -26,6 +26,7 @@ function Invoke-RubrikRESTCall { .EXAMPLE Invoke-RubrikRESTCall -Endpoint 'vmware/vm' -Method GET -Query @{'name'='msf-sql2016'} + Retrieve the raw output for the VMWare VM msf-sql2016 using a query parameter. .EXAMPLE @@ -44,6 +45,14 @@ function Invoke-RubrikRESTCall { Invoke-RubrikRESTCall -api internal -Endpoint nutanix/cluster/NutanixCluster:::d34d42c0-5468-4c37-a3cf-4376baf018e4/refresh -Method post Refreshes the information of the Nutanix cluster + + .EXAMPLE + $currentreport = Get-RubrikReport -name BoringReportName -DetailedObject + $currentreport.name = "Jaap's QuokkaReport" + $updatedbody = $currentreport|select * -exclude id,updatestatus,reportTemplate,reportType + Invoke-RubrikRESTCall -Endpoint "report/$($currentreport.id)" -api internal -Method PATCH -Body $updatedbody -Verbose + + Using this example it is possible to rename an existing report to the report name listed in the second row of this example #> [cmdletbinding()] @@ -114,7 +123,14 @@ function Invoke-RubrikRESTCall { } Write-Verbose "URI string: $uri" Write-Verbose "Body string: $JsonBody" - $result = Submit-Request -uri $uri -header $Header -method $Method -body $JsonBody + + if ($Method -eq 'Get' -and $Body) { + Write-Warning 'Executing a ''Get'' request in combination with a body object, processing request without body' + $result = Submit-Request -uri $uri -header $Header -method $Method + } else { + $result = Submit-Request -uri $uri -header $Header -method $Method -body $JsonBody + } + } catch { throw $_ diff --git a/Rubrik/Public/New-RubrikLDAP.ps1 b/Rubrik/Public/New-RubrikLDAP.ps1 index de39520f1..dfce87c64 100755 --- a/Rubrik/Public/New-RubrikLDAP.ps1 +++ b/Rubrik/Public/New-RubrikLDAP.ps1 @@ -42,7 +42,6 @@ function New-RubrikLDAP [Parameter(ParameterSetName='Credential',Mandatory=$true)] [System.Management.Automation.CredentialAttribute()]$BindCredential, # Dynamic DNS name for locating authentication servers. - [Parameter(Mandatory=$True)] [string]$DynamicDNSName, # The path to the directory where searches for users begin. [string]$baseDn, diff --git a/Rubrik/Public/New-RubrikVolumeGroupMount.ps1 b/Rubrik/Public/New-RubrikVolumeGroupMount.ps1 index 93daecca1..47ab0a4b5 100644 --- a/Rubrik/Public/New-RubrikVolumeGroupMount.ps1 +++ b/Rubrik/Public/New-RubrikVolumeGroupMount.ps1 @@ -18,7 +18,14 @@ function New-RubrikVolumeGroupMount .EXAMPLE New-RubrikVolumeGroupMount -TargetHost 'Restore-Server1' -VolumeGroupSnapshot $snap -ExcludeDrives -$DrivestoExclude - + + This will create a new VolumeGroup Mount on Restore-Server1 with the values specified in $snap & $DrivestoExclude + + .EXAMPLE + $snapshot = Get-RubrikVolumeGroup "MyVolumeGroup" | Get-RubrikSnapshot -Latest + New-RubrikVolumeGroupMount -TargetHost "MyTargetHostName" -VolumeGroupSnapshot $snapshot -ExcludeDrives @("D","E") + + This will create a new VolumeGroup Mount on MyTargetHostName with the latest snapshot retrieved in the first line, while exlcluding drives D & E #> [CmdletBinding(SupportsShouldProcess = $true,ConfirmImpact = 'High')] diff --git a/Rubrik/Public/Remove-RubrikOrgAuthorization.ps1 b/Rubrik/Public/Remove-RubrikOrgAuthorization.ps1 index 4592f33dc..c278dc8db 100644 --- a/Rubrik/Public/Remove-RubrikOrgAuthorization.ps1 +++ b/Rubrik/Public/Remove-RubrikOrgAuthorization.ps1 @@ -21,10 +21,12 @@ function Remove-RubrikOrgAuthorization .EXAMPLE Remove-RubrikOrgAuthorization -ID 'Organization:::01234567-8910-1abc-d435-0abc1234d567' -UseSLA '12345678-1234-abcd-8910-1234567890ab' + Removes authorization from the Organization with ID Organization:::01234567-8910-1abc-d435-0abc1234d567 to use the SLA Domain with ID 12345678-1234-abcd-8910-1234567890ab .EXAMPLE - Remove-RubrikOrgAuthorization -ID 'Organization:::01234567-8910-1abc-d435-0abc1234d567' -ManageResource 'VirtualMachine:::aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee-vm-12345' + Remove-RubrikOrgAuthorization -ID 'Organization:::01234567-8910-1abc-d435-0abc1234d567' -ManageResource 'VirtualMachine:::aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee-vm-12345' + Remove authorization from the Organization with ID Organization:::01234567-8910-1abc-d435-0abc1234d567 to manage the VM with ID VirtualMachine:::aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee-vm-12345 .EXAMPLE @@ -75,50 +77,53 @@ function Remove-RubrikOrgAuthorization } Process { - #region One-off - # If User ID was not specified, get the current user ID - if([string]::IsNullOrEmpty($id)) { - $id = (Get-RubrikUser -id me).id - Write-Verbose "Using User ID $($id) as principal. This will infer the Organization ID automatically." - } elseif ([string]::IsNullOrEmpty($PSBoundParameters.OrgID)) { - # Unless specified and not using an inferred Org ID, API expects principal (ID) and Org ID to be the same - $OrgID = $id - } - - # Throw error on Global Org - if((Get-RubrikOrganization -id $id).isGlobal) { Throw "Operation not supported on Global Organization" } + if (($rubrikConnection.version.substring(0,5) -as [version]) -ge [version]5.2) { + Write-Warning 'This cmdlet is no longer functional in Rubrik CDM 5.2' + } else { + #region One-off + # If User ID was not specified, get the current user ID + if([string]::IsNullOrEmpty($id)) { + $id = (Get-RubrikUser -id me).id + Write-Verbose "Using User ID $($id) as principal. This will infer the Organization ID automatically." + } elseif ([string]::IsNullOrEmpty($PSBoundParameters.OrgID)) { + # Unless specified and not using an inferred Org ID, API expects principal (ID) and Org ID to be the same + $OrgID = $id + } - # Throw error if UseSLA, ManageResource and ManageSLA are all empty - if([string]::IsNullOrEmpty($UseSLA) -and [string]::IsNullOrEmpty($ManageResource) -and [string]::IsNullOrEmpty($ManageSLA)) { - throw "At least one of the parameters -UseSLA, -ManageResource, or -ManageSLA must be supplied" - } + # Throw error on Global Org + if((Get-RubrikOrganization -id $id).isGlobal) { Throw "Operation not supported on Global Organization" } - # Build REST Body - if($UseSLA.Length -gt 0) { $resources.Body.privileges.useSla.AddRange($UseSLA) } - if($ManageResource.Length -gt 0) { - # Added changed body for 5.1, as ManageResource seems to be no longer used - if ([float]$rubrikConnection.version.substring(0,3) -gt [float]'5.0') { - $resources.Body.privileges.manageRestoreSource.AddRange($ManageResource) - } else { - $resources.Body.privileges.ManageResource.AddRange($ManageResource) + # Throw error if UseSLA, ManageResource and ManageSLA are all empty + if([string]::IsNullOrEmpty($UseSLA) -and [string]::IsNullOrEmpty($ManageResource) -and [string]::IsNullOrEmpty($ManageSLA)) { + throw "At least one of the parameters -UseSLA, -ManageResource, or -ManageSLA must be supplied" } - } - if($ManageSLA.Length -gt 0) { $resources.Body.privileges.ManageSLA.AddRange($ManageSLA) } - $resources.Body.principals.Add($id) | Out-Null - $resources.Body.organizationId = $OrgID - $body = ConvertTo-Json -InputObject $resources.Body - Write-Verbose -Message "Body = $body" - #endregion - - $uri = New-URIString -server $Server -endpoint ($resources.URI) - $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri - #$body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) - $result = Submit-Request -uri $uri -header $Header -method $($resources.Method) -body $body - $result = Test-ReturnFormat -api $api -result $result -location $resources.Result - $result = Test-FilterObject -filter ($resources.Filter) -result $result - $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result - return $result + # Build REST Body + if($UseSLA.Length -gt 0) { $resources.Body.privileges.useSla.AddRange($UseSLA) } + if($ManageResource.Length -gt 0) { + # Added changed body for 5.1, as ManageResource seems to be no longer used + if ([float]$rubrikConnection.version.substring(0,3) -gt [float]'5.0') { + $resources.Body.privileges.manageRestoreSource.AddRange($ManageResource) + } else { + $resources.Body.privileges.ManageResource.AddRange($ManageResource) + } + } + if($ManageSLA.Length -gt 0) { $resources.Body.privileges.ManageSLA.AddRange($ManageSLA) } + $resources.Body.principals.Add($id) | Out-Null + $resources.Body.organizationId = $OrgID + $body = ConvertTo-Json -InputObject $resources.Body + Write-Verbose -Message "Body = $body" + #endregion + + $uri = New-URIString -server $Server -endpoint ($resources.URI) + $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri + #$body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) + $result = Submit-Request -uri $uri -header $Header -method $($resources.Method) -body $body + $result = Test-ReturnFormat -api $api -result $result -location $resources.Result + $result = Test-FilterObject -filter ($resources.Filter) -result $result + $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result + return $result + } } # End of process } # End of function \ No newline at end of file diff --git a/Rubrik/Public/Remove-RubrikSLA.ps1 b/Rubrik/Public/Remove-RubrikSLA.ps1 index f21f3f18d..35c51913c 100644 --- a/Rubrik/Public/Remove-RubrikSLA.ps1 +++ b/Rubrik/Public/Remove-RubrikSLA.ps1 @@ -28,6 +28,11 @@ function Remove-RubrikSLA [Parameter(Mandatory = $true,ValueFromPipelineByPropertyName = $true)] [ValidateNotNullOrEmpty()] [String]$id, + # Should not be specified, used for better error handling and WhatIf/Confirm messages + [Parameter( + ValueFromPipelineByPropertyName=$true + )] + [string] $name, # Rubrik server IP or FQDN [String]$Server = $global:RubrikConnection.server, # API version diff --git a/Rubrik/Public/Set-RubrikBlackout.ps1 b/Rubrik/Public/Set-RubrikBlackout.ps1 index 9ab9e47a2..b52f2d68c 100644 --- a/Rubrik/Public/Set-RubrikBlackout.ps1 +++ b/Rubrik/Public/Set-RubrikBlackout.ps1 @@ -6,7 +6,7 @@ function Set-RubrikBlackout Connects to Rubrik and sets blackout (stops/starts all snaps) .DESCRIPTION - The Set-RubrikBlackout cmdlet will accept a flag of true/false to set cluster blackout + The Set-RubrikBlackout cmdlet uses a switch parameter to set cluster blackout .NOTES Written by Pete Milanese for community usage @@ -17,7 +17,14 @@ function Set-RubrikBlackout https://rubrik.gitbook.io/rubrik-sdk-for-powershell/command-documentation/reference/set-rubrikblackout .EXAMPLE - Set-RubrikBlackout -Set:[$true/$false] + Set-RubrikBlackout -Set + + Sets Rubrik Global Blackout window to be active on current cluster + + .EXAMPLE + Set-RubrikBlackout -Set:$false + + Sets Rubrik Global Blackout window to be set to inactive on current cluster #> [CmdletBinding(SupportsShouldProcess = $true,ConfirmImpact = 'High')] diff --git a/Rubrik/Public/Set-RubrikOrgAuthorization.ps1 b/Rubrik/Public/Set-RubrikOrgAuthorization.ps1 index 6a5871854..290b112e1 100644 --- a/Rubrik/Public/Set-RubrikOrgAuthorization.ps1 +++ b/Rubrik/Public/Set-RubrikOrgAuthorization.ps1 @@ -21,15 +21,18 @@ function Set-RubrikOrgAuthorization .EXAMPLE Set-RubrikOrgAuthorization -ID 'Organization:::01234567-8910-1abc-d435-0abc1234d567' -UseSLA '12345678-1234-abcd-8910-1234567890ab' + Authorizes the Organization with ID Organization:::01234567-8910-1abc-d435-0abc1234d567 to use the SLA Domain with ID 12345678-1234-abcd-8910-1234567890ab .EXAMPLE Set-RubrikOrgAuthorization -ID 'Organization:::01234567-8910-1abc-d435-0abc1234d567' -ManageResource 'VirtualMachine:::aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee-vm-12345' + Authorizes the Organization with ID Organization:::01234567-8910-1abc-d435-0abc1234d567 to manage the VM with ID VirtualMachine:::aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee-vm-12345 .EXAMPLE $vms = (Get-RubrikVM -PrimaryClusterId local -Relic:$false | Where-Object { $_.Name -like '*sql*' }).id Set-RubrikOrgAuthorization -ID 'Organization:::01234567-8910-1abc-d435-0abc1234d567' -ManageResource $vms + Authorizes the Organization with ID Organization:::01234567-8910-1abc-d435-0abc1234d567 to manage all VMs with names containing the string 'SQL' #> @@ -75,50 +78,53 @@ function Set-RubrikOrgAuthorization } Process { - #region One-off - # If User ID was not specified, get the current user ID - if([string]::IsNullOrEmpty($id)) { - $id = (Get-RubrikUser -id me).id - Write-Verbose "Using User ID $($id) as principal. This will infer the Organization ID automatically." - } elseif ([string]::IsNullOrEmpty($PSBoundParameters.OrgID)) { - # Unless specified and not using an inferred Org ID, API expects principal (ID) and Org ID to be the same - $OrgID = $id - } - - # Throw error on Global Org - if((Get-RubrikOrganization -id $id).isGlobal) { throw "Operation not supported on Global Organization" } + if (($rubrikConnection.version.substring(0,5) -as [version]) -ge [version]5.2) { + Write-Warning 'This cmdlet is no longer functional in Rubrik CDM 5.2' + } else { + #region One-off + # If User ID was not specified, get the current user ID + if([string]::IsNullOrEmpty($id)) { + $id = (Get-RubrikUser -id me).id + Write-Verbose "Using User ID $($id) as principal. This will infer the Organization ID automatically." + } elseif ([string]::IsNullOrEmpty($PSBoundParameters.OrgID)) { + # Unless specified and not using an inferred Org ID, API expects principal (ID) and Org ID to be the same + $OrgID = $id + } - # Throw error if UseSLA, ManageResource and ManageSLA are all empty - if([string]::IsNullOrEmpty($UseSLA) -and [string]::IsNullOrEmpty($ManageResource) -and [string]::IsNullOrEmpty($ManageSLA)) { - throw "At least one of the parameters -UseSLA, -ManageResource, or -ManageSLA must be supplied" - } + # Throw error on Global Org + if((Get-RubrikOrganization -id $id).isGlobal) { throw "Operation not supported on Global Organization" } - # Build REST Body - if($UseSLA.Length -gt 0) { $resources.Body.privileges.useSla.AddRange($UseSLA) } - if($ManageResource.Length -gt 0) { - # Added changed body for 5.1, as ManageResource seems to be no longer used - if ([float]$rubrikConnection.version.substring(0,3) -gt [float]'5.0') { - $resources.Body.privileges.manageRestoreSource.AddRange($ManageResource) - } else { - $resources.Body.privileges.ManageResource.AddRange($ManageResource) + # Throw error if UseSLA, ManageResource and ManageSLA are all empty + if([string]::IsNullOrEmpty($UseSLA) -and [string]::IsNullOrEmpty($ManageResource) -and [string]::IsNullOrEmpty($ManageSLA)) { + throw "At least one of the parameters -UseSLA, -ManageResource, or -ManageSLA must be supplied" } - } - if($ManageSLA.Length -gt 0) { $resources.Body.privileges.ManageSLA.AddRange($ManageSLA) } - $resources.Body.principals.Add($id) | Out-Null - $resources.Body.organizationId = $OrgID - $body = ConvertTo-Json -InputObject $resources.Body - Write-Verbose -Message "Body = $body" - #endregion - - $uri = New-URIString -server $Server -endpoint ($resources.URI) - $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri - #$body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) - $result = Submit-Request -uri $uri -header $Header -method $($resources.Method) -body $body - $result = Test-ReturnFormat -api $api -result $result -location $resources.Result - $result = Test-FilterObject -filter ($resources.Filter) -result $result - $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result - return $result + # Build REST Body + if($UseSLA.Length -gt 0) { $resources.Body.privileges.useSla.AddRange($UseSLA) } + if($ManageResource.Length -gt 0) { + # Added changed body for 5.1, as ManageResource seems to be no longer used + if ([float]$rubrikConnection.version.substring(0,3) -gt [float]'5.0') { + $resources.Body.privileges.manageRestoreSource.AddRange($ManageResource) + } else { + $resources.Body.privileges.ManageResource.AddRange($ManageResource) + } + } + if($ManageSLA.Length -gt 0) { $resources.Body.privileges.ManageSLA.AddRange($ManageSLA) } + $resources.Body.principals.Add($id) | Out-Null + $resources.Body.organizationId = $OrgID + $body = ConvertTo-Json -InputObject $resources.Body + Write-Verbose -Message "Body = $body" + #endregion + + $uri = New-URIString -server $Server -endpoint ($resources.URI) + $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri + #$body = New-BodyString -bodykeys ($resources.Body.Keys) -parameters ((Get-Command $function).Parameters.Values) + $result = Submit-Request -uri $uri -header $Header -method $($resources.Method) -body $body + $result = Test-ReturnFormat -api $api -result $result -location $resources.Result + $result = Test-FilterObject -filter ($resources.Filter) -result $result + $result = Set-ObjectTypeName -TypeName $resources.ObjectTName -result $result + return $result + } } # End of process } # End of function \ No newline at end of file diff --git a/Rubrik/Public/Set-RubrikReport.ps1 b/Rubrik/Public/Set-RubrikReport.ps1 new file mode 100644 index 000000000..a04f42e3d --- /dev/null +++ b/Rubrik/Public/Set-RubrikReport.ps1 @@ -0,0 +1,116 @@ +#requires -Version 3 +function Set-RubrikReport +{ + <# + .SYNOPSIS + Change report settings by taking an existing report and making the desired changes + + .DESCRIPTION + The Set-RubrikReport cmdlet is used to change settings on an existing report by specifying one or more parameters to make these changes. Currently it is supported to change the new and the colums displayed in the table. + + .NOTES + Written by Jaap Brasser for community usage + Twitter: @jaap_brasser + GitHub: jaapbrasser + + .LINK + https://rubrik.gitbook.io/rubrik-sdk-for-powershell/command-documentation/reference/set-rubrikreport + + .EXAMPLE + Get-RubrikReport -Name 'Boring Report' -DetailedObject | Set-RubrikReport -NewName 'Quokka Report' + + This will rename the report named 'Boring Report' to 'Quokka Report' + + .EXAMPLE + Get-RubrikReport -Name 'Quokka Report' -DetailedObject | Set-RubrikReport -NewTableColumns TaskStatus, TaskType, ObjectName, ObjectType, Location, SlaDomain, StartTime, EndTime, Duration, DataTransferred, DataStored, DedupRatioForJob + + This will change the table colums in 'Quokka Report' to the specified values in the -NewTableColums parameter + #> + + [CmdletBinding()] + Param( + # The ID of the report. + [Parameter( + Mandatory = $true, + ValueFromPipelineByPropertyName = $true + )] + [String]$id, + # The new name of the report + [Parameter( + Mandatory = $true, + ValueFromPipelineByPropertyName = $true )] + [String]$Name, + [Parameter( + Mandatory = $true, + ValueFromPipelineByPropertyName = $true )] + $chart0, + [Parameter( + Mandatory = $true, + ValueFromPipelineByPropertyName = $true )] + $chart1, + [Parameter( + Mandatory = $true, + ValueFromPipelineByPropertyName = $true )] + $filters, + [Parameter( + Mandatory = $true, + ValueFromPipelineByPropertyName = $true )] + $table, + [string] $NewName, + [ValidateSet('Hour', 'Day', 'Month', 'Quarter', 'Year', 'SlaDomain', 'ReplicationTarget', 'ArchivalTarget', 'TaskStatus', 'TaskType', 'Location', 'ObjectName', 'ObjectType', 'ObjectIndexType', 'ClusterLocation', 'ComplianceStatus', 'Organization', 'RecoveryPoint', 'RecoveryPointType', 'Username', 'FailureReason', 'SnapshotConsistency', 'QueuedTime', 'StartTime', 'EndTime', 'Duration', 'DataTransferred', 'LogicalDataProtected', 'DataStored', 'NumFilesTransferred', 'EffectiveThroughput', 'DedupRatio', 'LogicalDedupRatio', 'DataReductionPercent', 'LogicalDataReductionPercent', 'TaskCount', 'SuccessfulTaskCount', 'CanceledTaskCount', 'FailedTaskCount', 'AverageDuration', 'ObjectCount', 'TotalLocalStorage', 'TotalReplicaStorage', 'TotalArchiveStorage', 'LocalStorageGrowth', 'ArchiveStorageGrowth', 'ReplicaStorageGrowth', 'ProtectedOn', 'InComplianceCount', 'NonComplianceCount', 'ArchivalInComplianceCount', 'ArchivalNonComplianceCount', 'TotalSnapshots', 'MissedLocalSnapshots', 'MissedArchivalSnapshots', 'LocalSnapshots', 'ReplicaSnapshots', 'ArchiveSnapshots', 'LatestLocalSnapshot', 'LocalCdpStatus', 'PercentLocal24HourCdpHealthy', 'LocalCdpLogStorage', 'LocalCdpThroughput', 'LatestLocalSnapshotIndexState', 'LocalIndexedSnapshotsCount', 'LocalUnindexedSnapshotsCount', 'LocalPendingForIndexSnapshotsCount', 'LatestLocalIndexedSnapshotTime', 'CdpReplicationStatus', IgnoreCase = $false)] + [string[]]$NewTableColumns, + # Rubrik server IP or FQDN + [String]$Server = $global:RubrikConnection.server, + # API version + [String]$api = $global:RubrikConnection.api + ) + + Begin { + + # The Begin section is used to perform one-time loads of data necessary to carry out the function's purpose + # If a command needs to be run with each iteration or pipeline input, place it in the Process section + + # Check to ensure that a session to the Rubrik cluster exists and load the needed header data for authentication + Test-RubrikConnection + + # API data references the name of the function + # For convenience, that name is saved here to $function + $function = $MyInvocation.MyCommand.Name + + # Retrieve all of the URI, method, body, query, result, filter, and success details for the API endpoint + Write-Verbose -Message "Gather API Data for $function" + $resources = Get-RubrikAPIData -endpoint $function + Write-Verbose -Message "Load API data for $($resources.Function)" + Write-Verbose -Message "Description: $($resources.Description)" + } + + Process { + # Build body object + $CurrentBody = [pscustomobject]@{ + name = $Name + filters = $filters + chart0 = $chart0 + chart1 = $chart1 + table = $table + } + + switch ($true) { + {$NewName} {$CurrentBody.Name = $NewName} + {$NewTableColumns} {$CurrentBody.table.columns = $NewTableColumns} + } + + $uri = New-URIString -server $Server -endpoint ($resources.URI) -id $id + $uri = Test-QueryParam -querykeys ($resources.Query.Keys) -parameters ((Get-Command $function).Parameters.Values) -uri $uri + $body = $CurrentBody | ConvertTo-Json -Depth 10 + Write-Verbose -Message "Body = $body" + if ($NewName -or $NewTableColumns) { + $result = Submit-Request -uri $uri -header $Header -method $($resources.Method) -body $body + } else { + Write-Warning ('No new values submitted, no changes made to report: {0} ({1})' -f $Name, $id) + } + $result = Test-ReturnFormat -api $api -result $result -location $resources.Result + $result = Test-FilterObject -filter ($resources.Filter) -result $result + + return $result + } # End of process +} # End of function \ No newline at end of file diff --git a/Rubrik/Rubrik.psd1 b/Rubrik/Rubrik.psd1 index c5f2f532f..6aa9dad7a 100644 --- a/Rubrik/Rubrik.psd1 +++ b/Rubrik/Rubrik.psd1 @@ -3,7 +3,7 @@ # # Generated by: Jaap Brasser # -# Generated on: 2019/10/07 +# Generated on: 2020/09/07 # @{ @@ -11,7 +11,7 @@ RootModule = 'Rubrik.psm1' # Version number of this module. - ModuleVersion = '5.0.3' + ModuleVersion = '5.2.0' # Supported PSEditions # CompatiblePSEditions = @() @@ -93,6 +93,7 @@ 'ObjectDefinitions/Rubrik.VMwareDatacenter.ps1xml', 'ObjectDefinitions/Rubrik.VMwareDatastore.ps1xml', 'ObjectDefinitions/Rubrik.VMwareHost.ps1xml', + 'ObjectDefinitions/Rubrik.VMwareVmMount.ps1xml', 'ObjectDefinitions/Rubrik.VolumeGroup.ps1xml', 'ObjectDefinitions/Rubrik.User.ps1xml', 'ObjectDefinitions/Rubrik.SLADomainv1.ps1xml', @@ -118,6 +119,7 @@ 'Get-RubrikAPIVersion', 'Get-RubrikArchive', 'Get-RubrikAvailabilityGroup', + 'Get-RubrikBlackout', 'Get-RubrikBackupServiceDeployment', 'Get-RubrikBootStrap', 'Get-RubrikClusterInfo', @@ -286,6 +288,7 @@ 'Set-RubrikNutanixVM', 'Set-RubrikOrgAuthorization', 'Set-RubrikProxySetting', + 'Set-RubrikReport', 'Set-RubrikSetting', 'Set-RubrikSLA', 'Set-RubrikSQLInstance', @@ -350,7 +353,7 @@ # ReleaseNotes = '' # Prerelease string of this module - # Prerelease = 'develxxx' + Prerelease = 'devel687' # Flag to indicate whether the module requires explicit user acceptance for install/update # RequireLicenseAcceptance = $false diff --git a/Tests/Set-RubrikReport.Tests.ps1 b/Tests/Set-RubrikReport.Tests.ps1 new file mode 100644 index 000000000..f08cd1c89 --- /dev/null +++ b/Tests/Set-RubrikReport.Tests.ps1 @@ -0,0 +1,78 @@ +Remove-Module -Name 'Rubrik' -ErrorAction 'SilentlyContinue' +Import-Module -Name './Rubrik/Rubrik.psd1' -Force + +foreach ( $privateFunctionFilePath in ( Get-ChildItem -Path './Rubrik/Private' | Where-Object extension -eq '.ps1').FullName ) { + . $privateFunctionFilePath +} + +Describe -Name 'Public/Set-RubrikReport' -Tag 'Public', 'Set-RubrikReport' -Fixture { + #region init + $global:rubrikConnection = @{ + id = 'test-id' + userId = 'test-userId' + token = 'test-token' + server = 'test-server' + header = @{ 'Authorization' = 'Bearer test-authorization' } + time = (Get-Date) + api = 'v1' + version = '4.0.5' + } + #endregion + + Context -Name 'Returned Results' { + Mock -CommandName Test-RubrikConnection -Verifiable -ModuleName 'Rubrik' -MockWith {} + Mock -CommandName Submit-Request -Verifiable -ModuleName 'Rubrik' -MockWith { + [pscustomobject]@{ + 'id' = 'CustomReport:::1:1:1:1' + 'name' = 'TestReport1' + 'filters' = 'Ready' + 'chart0' = 'Custom' + 'chart1' = 'CustomReport:::11111' + 'table' = [pscustomobject]@{columns = 1,2,3} + } + } + Mock -CommandName Submit-Request -Verifiable -ModuleName 'Rubrik' -ParameterFilter {$Method -eq 'Patch'} -MockWith { + [pscustomobject]@{ + 'id' = 'CustomReport:::1:1:1:1' + 'name' = 'Quokka' + 'filters' = 'Ready' + 'chart0' = 'Custom' + 'chart1' = 'CustomReport:::11111' + 'table' = [pscustomobject]@{columns = 'ReplicationTarget', 'ArchivalTarget', 'TaskStatus'} + } + } + + It -Name 'Should display warning if no new values are presented' -Test { + $Output = Get-RubrikReport | Set-RubrikReport *>&1 + (-join $Output) | Should -BeLike "*No new values submitted, no changes made to report:*" + } + + It -Name 'Should return name field with correct name' -Test { + (Get-RubrikReport | Set-RubrikReport -NewName Quokka).Name | + Should -Be "Quokka" + } + + It -Name 'Should return correct array of table columns' -Test { + (Get-RubrikReport | Set-RubrikReport -NewTableColumns 'ReplicationTarget', 'ArchivalTarget', 'TaskStatus').Table.Columns | + Should -Be @('ReplicationTarget', 'ArchivalTarget', 'TaskStatus') + } + + Assert-VerifiableMock + Assert-MockCalled -CommandName Test-RubrikConnection -ModuleName 'Rubrik' -Times 1 + Assert-MockCalled -CommandName Submit-Request -ModuleName 'Rubrik' -Times 1 + } + Context -Name 'Parameter Validation' { + It -Name 'ID Missing' -Test { + { Get-RubrikReport -id | Set-RubrikReport} | + Should -Throw "Missing an argument for parameter 'id'. Specify a parameter of type 'System.String' and try again." + } + It -Name 'Type validation validateset should work for NewTableColumns' -Test { + { Set-RubrikReport -NewTableColumns 'NewReport' } | + Should -Throw 'Cannot validate argument on parameter ''NewTableColumns''. The argument "NewReport" does not belong to the set "Hour,Day,Month,Quarter,Year,SlaDomain,ReplicationTarget,ArchivalTarget,TaskStatus,TaskType,Location,ObjectName,ObjectType,ObjectIndexType,ClusterLocation,ComplianceStatus,Organization,RecoveryPoint,RecoveryPointType,Username,FailureReason,SnapshotConsistency,QueuedTime,StartTime,EndTime,Duration,DataTransferred,LogicalDataProtected,DataStored,NumFilesTransferred,EffectiveThroughput,DedupRatio,LogicalDedupRatio,DataReductionPercent,LogicalDataReductionPercent,TaskCount,SuccessfulTaskCount,CanceledTaskCount,FailedTaskCount,AverageDuration,ObjectCount,TotalLocalStorage,TotalReplicaStorage,TotalArchiveStorage,LocalStorageGrowth,ArchiveStorageGrowth,ReplicaStorageGrowth,ProtectedOn,InComplianceCount,NonComplianceCount,ArchivalInComplianceCount,ArchivalNonComplianceCount,TotalSnapshots,MissedLocalSnapshots,MissedArchivalSnapshots,LocalSnapshots,ReplicaSnapshots,ArchiveSnapshots,LatestLocalSnapshot,LocalCdpStatus,PercentLocal24HourCdpHealthy,LocalCdpLogStorage,LocalCdpThroughput,LatestLocalSnapshotIndexState,LocalIndexedSnapshotsCount,LocalUnindexedSnapshotsCount,LocalPendingForIndexSnapshotsCount,LatestLocalIndexedSnapshotTime,CdpReplicationStatus" specified by the ValidateSet attribute. Supply an argument that is in the set and then try the command again.' + } + It -Name 'Type validation validateset should be case-sensitive NewTableColumns' -Test { + { Set-RubrikReport -NewTableColumns 'hour' } | + Should -Throw 'Cannot validate argument on parameter ''NewTableColumns''. The argument "hour" does not belong to the set "Hour,Day,Month,Quarter,Year,SlaDomain,ReplicationTarget,ArchivalTarget,TaskStatus,TaskType,Location,ObjectName,ObjectType,ObjectIndexType,ClusterLocation,ComplianceStatus,Organization,RecoveryPoint,RecoveryPointType,Username,FailureReason,SnapshotConsistency,QueuedTime,StartTime,EndTime,Duration,DataTransferred,LogicalDataProtected,DataStored,NumFilesTransferred,EffectiveThroughput,DedupRatio,LogicalDedupRatio,DataReductionPercent,LogicalDataReductionPercent,TaskCount,SuccessfulTaskCount,CanceledTaskCount,FailedTaskCount,AverageDuration,ObjectCount,TotalLocalStorage,TotalReplicaStorage,TotalArchiveStorage,LocalStorageGrowth,ArchiveStorageGrowth,ReplicaStorageGrowth,ProtectedOn,InComplianceCount,NonComplianceCount,ArchivalInComplianceCount,ArchivalNonComplianceCount,TotalSnapshots,MissedLocalSnapshots,MissedArchivalSnapshots,LocalSnapshots,ReplicaSnapshots,ArchiveSnapshots,LatestLocalSnapshot,LocalCdpStatus,PercentLocal24HourCdpHealthy,LocalCdpLogStorage,LocalCdpThroughput,LatestLocalSnapshotIndexState,LocalIndexedSnapshotsCount,LocalUnindexedSnapshotsCount,LocalPendingForIndexSnapshotsCount,LatestLocalIndexedSnapshotTime,CdpReplicationStatus" specified by the ValidateSet attribute. Supply an argument that is in the set and then try the command again.' + } + } +} \ No newline at end of file