Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,7 @@ Thumbs.db

# Custom #
######################
.vscode/
.vscode/

# Exclude while tests are being developed to not break CI processes
/Tests/Performance
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

### Added

* Added new ModuleOption in the `Set-RubrikModuleOption` cmdlet: `LegacyJSONConversion` allows for setting the options for JSON conversion. Either fallback to ConvertTo-Json on Windows PowerShell, or use a newer faster set of functions. Old functionality is maintained for backwards compatibility. Resolves [Issue 788](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/788)

### Fixed

* `Format-JSON` issue fixed on Windows PowerShell, issue with slowness for large JSON responses, two alternatives now available: `Set-RubrikModuleOption -OptionName LegacyJSONConversion -OptionValue AlwaysConvertToJson` to fall back to, on Windows PowerShell 5.1 occasionally buggy, ConvertTo-Json cmdlet. Or `Set-RubrikModuleOption -OptionName LegacyJSONConversion -OptionValue Experimental` to use the improved ParseItemExp function, should be a 40~50% speed improvement left old functionality in place for backwards compat. Resolves [Issue 788](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/788) & [Issue 763](https://github.com/rubrikinc/rubrik-sdk-for-powershell/issues/763)

## [6.0.0](https://github.com/rubrikinc/rubrik-sdk-for-powershell/tree/6.0.0) - 2022-01-07

### Changed
Expand Down
3 changes: 2 additions & 1 deletion Rubrik/OptionsDefault/rubrik_sdk_for_powershell_options.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"ModuleOption": {
"ApplyCustomViewDefinitions": "True",
"CredentialPath": "",
"DefaultWebRequestTimeOut": 100
"DefaultWebRequestTimeOut": 100,
"LegacyJSONConversion": ""
}
}
66 changes: 62 additions & 4 deletions Rubrik/Private/Format-JSON.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,24 @@ function ExpandPayload($response) {
.SYNOPSIS
This function use the .Net JSON Serializer in order to bypass the maxJson Length limitation
#>
[void][System.Reflection.Assembly]::LoadWithPartialName('System.Web.Extensions')
return ParseItem -jsonItem ((New-Object -TypeName System.Web.Script.Serialization.JavaScriptSerializer -Property @{
MaxJsonLength = 67108864
}).DeserializeObject($response.Content))
try {
[void][System.Reflection.Assembly]::LoadWithPartialName('System.Web.Extensions')
} catch {
Write-Warning 'Run `Set-RubrikModuleOption -OptionName LegacyJSONConversion -OptionValue Default` to restore functionality...'
throw 'The System.Web.Extensions class is not available on this OS'
}

if ($rubrikOptions.ModuleOption.LegacyJSONConversion -eq 'Experimental' -or $rubrikOptions.ModuleOption.LegacyJSONConversion -eq 'AlwaysExperimental') {
Write-Verbose 'Using ParseItemExp (Experimental) to convert JSON to PowerShell Object'
return ParseItemExp -jsonItem ((New-Object -TypeName System.Web.Script.Serialization.JavaScriptSerializer -Property @{
MaxJsonLength = $response.length
}).DeserializeObject($response))
} else {
Write-Verbose 'Using ParseItem to convert JSON to PowerShell Object'
return ParseItem -jsonItem ((New-Object -TypeName System.Web.Script.Serialization.JavaScriptSerializer -Property @{
MaxJsonLength = 67108864
}).DeserializeObject($response))
}
}


Expand Down Expand Up @@ -60,4 +74,48 @@ function ParseJsonArray($jsonArray) {
$result += , (ParseItem -jsonItem $_)
}
return $result
}

function ParseItemExp($jsonItem) {
<#
.SYNOPSIS
Experimental faster: main function that determines the type of object and calls either ParseJsonObjectExp or ParseJsonArrayExp
#>
if($jsonItem.PSObject.TypeNames -match 'Array') {
ParseJsonArrayExp -jsonArray ($jsonItem)
} elseif($jsonItem.PSObject.TypeNames -match 'Dictionary') {
ParseJsonObjectExp -jsonObj ([HashTable]$jsonItem)
} else {
$jsonItem
}
}

function ParseJsonObjectExp($jsonObj) {
<#
.SYNOPSIS
Experimental faster: Converts JSON to PowerShell Custom objects
#>
$result = @{}
foreach ($key in $jsonObj.Keys)
{

if (-not [string]::IsNullOrEmpty($jsonObj[$key])) {
$result[$key] = ParseItemExp -jsonItem $jsonObj[$key]
} else {
$result[$key] = $null
}
}
[pscustomobject]$result
}

function ParseJsonArrayExp($jsonArray) {
<#
.SYNOPSIS
Experimental faster: Expands the array and feeds this back into ParseItem, in case of nested arrays this might occur multiple times
#>
@(
$jsonArray | ForEach-Object -Process {
, (ParseItemExp -jsonItem $_)
}
)
}
20 changes: 16 additions & 4 deletions Rubrik/Private/Submit-Request.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,17 @@ function Submit-Request {
Write-Verbose -Message 'Submitting the request'
if ($resources.method -in ('Delete','Post','Put','Patch')) {
# Delete operations (and some post) generally have no response body, skip JSON formatting and store the response from Invoke-WebRequest
if (Test-PowerShellSix) {
if ((Test-PowerShellSix) -and (
($rubrikOptions.ModuleOption.LegacyJSONConversion -eq 'AlwaysLegacy') -or
($rubrikOptions.ModuleOption.LegacyJSONConversion -eq 'AlwaysExperimental'))) {
$WebResult = Invoke-RubrikWebRequest -Uri $uri -Headers $header -Method $method -Body $body
$result = ExpandPayload -response $WebResult.Content
} elseif ((Test-PowerShellSix) -or ($rubrikOptions.ModuleOption.LegacyJSONConversion -eq 'AlwaysConvertToJson')) {
# Uses the improved ConvertFrom-Json cmdlet as provided in PowerShell 6.1
# In the case of DELETE, there is no content (json body) to parse.
$result = if (($WebResult = Invoke-RubrikWebRequest -Uri $uri -Headers $header -Method $method -Body $body)) {
if ($WebResult.Content) {
Write-Verbose 'Using ConvertFrom-Json to convert JSON to PowerShell Object'
ConvertFrom-Json -InputObject $WebResult.Content
}
}
Expand All @@ -51,7 +57,7 @@ function Submit-Request {
StatusDescription = $WebResult.StatusDescription
}
}
$result = ExpandPayload -response $WebResult
$result = ExpandPayload -response $WebResult.Content
}
# If $result is null, build a $result object to return to the user. Otherwise, $result will be returned.
if ($null -eq $result) {
Expand All @@ -74,8 +80,14 @@ function Submit-Request {
}
}
else {
if (Test-PowerShellSix) {
if ((Test-PowerShellSix) -and (
($rubrikOptions.ModuleOption.LegacyJSONConversion -eq 'AlwaysLegacy') -or
($rubrikOptions.ModuleOption.LegacyJSONConversion -eq 'AlwaysExperimental'))) {
$WebResult = Invoke-RubrikWebRequest -Uri $uri -Headers $header -Method $method -Body $body
$result = ExpandPayload -response $WebResult.Content
} elseif ((Test-PowerShellSix) -or ($rubrikOptions.ModuleOption.LegacyJSONConversion -eq 'AlwaysConvertToJson')) {
# Uses the improved ConvertFrom-Json cmdlet as provided in PowerShell 6.1
Write-Verbose 'Using ConvertFrom-Json to convert JSON to PowerShell Object'
$result = ConvertFrom-Json -InputObject (Invoke-RubrikWebRequest -Uri $uri -Headers $header -Method $method -Body $body).Content
} else {
# Because some calls require more than the default payload limit of 2MB, ExpandPayload dynamically adjusts the payload limit
Expand All @@ -87,7 +99,7 @@ function Submit-Request {
StatusDescription = $WebResult.StatusDescription
}
}
$result = ExpandPayload -response $WebResult
$result = ExpandPayload -response $WebResult.Content
}
}
}
Expand Down
17 changes: 16 additions & 1 deletion Rubrik/Public/Set-RubrikModuleOption.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,21 @@ function Set-RubrikModuleOption
Set-RubrikModuleOption -OptionName DefaultWebRequestTimeOut -OptionValue 30

Changes the default timeout for request to the Rubrik cluster to 30 seconds

.EXAMPLE
Set-RubrikModuleOption -OptionName LegacyJSONConversion -OptionValue Default

Same as undefined, using ExpandPayload to process JSON to PowerShell object conversion on Windows PowerShell

.EXAMPLE
Set-RubrikModuleOption -OptionName LegacyJSONConversion -OptionValue AlwaysConvertToJson

Forces the use of ConvertTo-Json, which is available on Windows PowerShell but it can cause unexpected behavior

.EXAMPLE
Set-RubrikModuleOption -OptionName LegacyJSONConversion -OptionValue Experimental

Using ExpandPayload to process JSON to Windows PowerShell object conversion using the new experimental, accelerated functions
#>

[CmdletBinding(DefaultParameterSetName = 'NameValue')]
Expand All @@ -56,7 +71,7 @@ function Set-RubrikModuleOption
ParameterSetName='NameValue',
Position=0,
Mandatory=$true)]
[ValidateSet('ApplyCustomViewDefinitions', 'CredentialPath', 'DefaultWebRequestTimeOut')]
[ValidateSet('ApplyCustomViewDefinitions', 'CredentialPath', 'DefaultWebRequestTimeOut', 'LegacyJSONConversion')]
[string]$OptionName,
# Desired value for option
[Parameter(
Expand Down
2 changes: 1 addition & 1 deletion Rubrik/Rubrik.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -366,7 +366,7 @@

# Prerelease string of this module

# Prerelease = 'RC1'
Prerelease = 'RC1'

# Flag to indicate whether the module requires explicit user acceptance for install/update
# RequireLicenseAcceptance = $false
Expand Down
2 changes: 1 addition & 1 deletion Tests/Set-RubrikModuleOption.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ Describe -Name 'Public/Set-RubrikModuleOption' -Tag 'Public', 'Set-RubrikModuleO

It -Name "Should throw not found error" -Test {
{Set-RubrikModuleOption -OptionName 'Test' -OptionValue 'Value' } |
Should -Throw '''OptionName''. The argument "Test" does not belong to the set "ApplyCustomViewDefinitions,CredentialPath,DefaultWebRequestTimeOut" specified by the ValidateSet attribute. Supply an argument that is in the set and then try the command again.'
Should -Throw '''OptionName''. The argument "Test" does not belong to the set "ApplyCustomViewDefinitions,CredentialPath,DefaultWebRequestTimeOut,LegacyJSONConversion" specified by the ValidateSet attribute. Supply an argument that is in the set and then try the command again.'
}

}
Expand Down