diff --git a/.github/workflows/cross-platform-tests.yml b/.github/workflows/cross-platform-tests.yml index 00262395..c39785fe 100644 --- a/.github/workflows/cross-platform-tests.yml +++ b/.github/workflows/cross-platform-tests.yml @@ -131,6 +131,212 @@ jobs: shell: pwsh run: ./scripts/Invoke-PfbCiPester.ps1 -Edition pwsh7 + # T8 + T11 -- PSScriptAnalyzer. + # + # WHY A CI JOB AND NOT A HOOK. The PostToolUse parse-check hook is per-edit and only ever + # sees the file just written. This rule set is repo-wide and low-frequency: what it catches + # is "someone added a 5.1-incompatible construct anywhere", which no per-file check can see. + # + # WHY ubuntu-latest AND ONE LEG. The analyzer parses; it does not execute the module, so its + # findings do not vary by host OS or PowerShell edition -- verified by running the identical + # sweep on Windows pwsh 7 and on Ubuntu 26.04 / pwsh 7.6.3 and getting the same total (276 + # at the time of that check, 149 once the dead-variable cleanup landed), the same zeros on + # every guard, and the same Private/ controls at 12 and 2. Running it + # across the existing 4-leg matrix would quadruple the cost for four identical results. + # + # The COMPATIBILITY rules are the apparent exception and are not: they target 5.1 and 7.0 by + # configuration, from static profiles that ship with the analyzer on every platform, so this + # job reports on 5.1 from a Linux runner with no 5.1 in sight. That the two Windows profiles + # resolve on a Linux install was checked, not assumed -- if they did not, the rule would + # evaluate nothing and hand the Public/ gate a permanent free pass. + # + # WHY IT DOES NOT NEED prepare-specs. Nothing here reads tools/specs/, so the job does not + # download the spec artifact and does not depend on that job. It starts immediately and + # finishes while the test matrix is still running. + analyze: + name: PSScriptAnalyzer + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v7 + + # Pinned and cached for the same reason Pester and Posh-SSH are pinned in + # .github/actions/install-test-modules: an unpinned MinimumVersion is how this + # repo silently moved from Pester 5 to Pester 6 with nobody deciding to, and a + # transient PSGallery blip has already failed a run on a SHA that passed 47s + # later. A new analyzer version can add rules or change counts, which would + # present as an unexplained CI failure on an unrelated PR. + # + # Deliberately NOT added as a third module to install-test-modules: that action + # runs in all four test legs, which would download the analyzer four times per + # run for a job that needs it once. + - name: Restore cached PSScriptAnalyzer + id: pssa-cache + uses: actions/cache@v6 + with: + path: .psmodules + key: pssa-${{ runner.os }}-1.25.0 + + - name: Save PSScriptAnalyzer + if: steps.pssa-cache.outputs.cache-hit != 'true' + shell: pwsh + run: | + New-Item -ItemType Directory -Force -Path .psmodules | Out-Null + Save-Module PSScriptAnalyzer -RequiredVersion 1.25.0 -Path .psmodules -Force + + - name: Run PSScriptAnalyzer + shell: pwsh + run: | + $ErrorActionPreference = 'Stop' + $env:PSModulePath = (Resolve-Path .psmodules).Path + [IO.Path]::PathSeparator + $env:PSModulePath + Import-Module PSScriptAnalyzer -RequiredVersion 1.25.0 + $settings = './PSScriptAnalyzerSettings.psd1' + + # --------------------------------------------------------------- + # CONTROL FIRST. Every assertion below is "this count is zero", and an + # analyzer that returns nothing satisfies all of them. That is not + # hypothetical: Invoke-ScriptAnalyzer honours -WhatIf and returns an empty + # set, and a mis-specified rule name or an unparseable settings file can + # produce the same silence. So prove the tool reports a finding it must + # report before believing any zero it gives us. + # --------------------------------------------------------------- + $control = @(Invoke-ScriptAnalyzer -ScriptDefinition 'function Test-Probe { $x = 1 }' ` + -IncludeRule PSUseDeclaredVarsMoreThanAssignments) + if ($control.Count -lt 1) { + throw 'CONTROL FAILED: the analyzer found nothing in a snippet that definitely has a finding. Every zero in this run is vacuous.' + } + Write-Host "control: analyzer live ($($control.Count) finding on the probe)" + + # Paths. The repo ROOT is included as an explicit FILE list, not as a + # directory: the module .psd1/.psm1 live there, and a directory sweep of the + # five source folders never analyses them -- which silently disables four + # manifest/module rules including the PSGallery preset's own + # PSMissingModuleManifestField. As files it also cannot recurse and + # double-count. build/ is gitignored generated output and stays out. + $paths = @('Public', 'Private', 'Tests', 'tools', 'scripts') | + Where-Object { Test-Path $_ } | + ForEach-Object { [pscustomobject]@{ Path = $_; Recurse = $true } } + $paths += Get-ChildItem -File | + Where-Object Extension -in '.ps1', '.psm1', '.psd1' | + ForEach-Object { [pscustomobject]@{ Path = $_.FullName; Recurse = $false } } + + # -Path takes a single string. Passing an array fails with a type-conversion + # error and leaves the variable empty, so a naive .Count then reports a + # confident "0 findings". Hence the loop. + $all = foreach ($p in $paths) { + $splat = @{ Path = $p.Path; Settings = $settings } + if ($p.Recurse) { $splat.Recurse = $true } + Invoke-ScriptAnalyzer @splat + } + $all = @($all) + + # Severity round-trips as UInt32 in some paths and compares as neither + # reliably; cast to string before comparing, always. + $errors = @($all | Where-Object { [string]$_.Severity -eq 'Error' }) + $warnings = @($all | Where-Object { [string]$_.Severity -eq 'Warning' }) + Write-Host "total $($all.Count): $($errors.Count) Error, $($warnings.Count) Warning" + + $failures = [System.Collections.Generic.List[string]]::new() + + # --- Guard 1: no Errors, ever. Reached by T9; this holds the line. + if ($errors.Count) { + $failures.Add("$($errors.Count) Error-severity finding(s)") + $errors | ForEach-Object { Write-Host "::error file=$($_.ScriptPath),line=$($_.Line)::$($_.RuleName): $($_.Message)" } + } + + # --- Guards 2-5: rules at a genuine repo-wide zero. Each is a REGRESSION + # guard: it is not cleaning anything up, it is refusing to let the first one + # in. PSUseCompatibleSyntax is the load-bearing one -- it enforces the 5.1 + # mandate with the real parser rather than the hook's regexes. + # + # PSUseDeclaredVarsMoreThanAssignments is here only because the 127 dead + # $manifest assignments were deleted first. That is the whole point of having + # deleted them: at 127 the rule reported nothing but known boilerplate, so a + # genuinely dead variable in a new test file was finding 128 of 127 and + # invisible, and no gate could ever be written. It is also the rule the + # control probe above uses, so its liveness is proven on every run. + foreach ($rule in 'PSUseCompatibleSyntax', 'PSAvoidAssignmentToAutomaticVariable', 'PSUseBOMForUnicodeEncodedFile', 'PSUseApprovedVerbs', 'PSUseDeclaredVarsMoreThanAssignments') { + $hits = @($all | Where-Object RuleName -eq $rule) + if ($hits.Count) { + $failures.Add("$rule regressed: $($hits.Count) finding(s), expected 0") + $hits | ForEach-Object { Write-Host "::error file=$($_.ScriptPath),line=$($_.Line)::$($_.RuleName): $($_.Message)" } + } + } + + # --- Guards 6-7 (T11): two rules that are clean in Public/ ONLY, so they are + # requested explicitly and scoped there. + # + # THE RuleName FILTER IS MANDATORY, NOT DEFENSIVE. A caller's -IncludeRule is + # UNION'd with the settings file's IncludeRules -- measured; it does not + # replace it. Unfiltered, this scan returns 22 records over Public/ and none + # of them belong to the rule being gated, so the gate would fail on unrelated + # preset findings while reporting the wrong cause. + foreach ($rule in 'PSProvideCommentHelp', 'PSUseCompatibleCommands') { + $scoped = @(Invoke-ScriptAnalyzer -Path 'Public' -Recurse -Settings $settings -IncludeRule $rule | + Where-Object RuleName -eq $rule) + + # Per-rule control: the same rule must be NONZERO in Private/. Without it + # a zero cannot be distinguished from an inert rule -- and for + # PSProvideCommentHelp that is the LIKELY failure, because its default + # ExportedOnly = $true silences it completely in this codebase (one + # function per dot-sourced file, exports declared in the manifest). The + # settings file sets $false; if that config is ever dropped, this control + # fails instead of the gate silently passing forever. + $control2 = @(Invoke-ScriptAnalyzer -Path 'Private' -Recurse -Settings $settings -IncludeRule $rule | + Where-Object RuleName -eq $rule) + if ($control2.Count -eq 0) { + $failures.Add("CONTROL FAILED for ${rule}: 0 findings in Private/ too, so the Public/ zero proves nothing") + } + + if ($scoped.Count) { + # ${rule}, not $rule -- "$rule:" parses the colon as a SCOPE qualifier + # (as in $script:x) and is a syntax error, not a runtime surprise. + $failures.Add("${rule}: $($scoped.Count) finding(s) in Public/, expected 0") + $scoped | ForEach-Object { Write-Host "::error file=$($_.ScriptPath),line=$($_.Line)::$($_.RuleName): $($_.Message)" } + } else { + Write-Host "gate $rule (Public/): 0, control Private/: $($control2.Count)" + } + } + + # Warnings are reported, not gated. 149 stand today and the plan does not + # clear them; a threshold would either be met trivially or block every PR. + # Revisit only with a number someone has committed to driving down. + Write-Host "::notice::PSScriptAnalyzer: $($warnings.Count) Warning-severity findings (not gated)" + + if ($failures.Count) { + Write-Host '' + $failures | ForEach-Object { Write-Host "FAIL: $_" } + throw "PSScriptAnalyzer gate failed: $($failures.Count) condition(s)." + } + Write-Host 'PSScriptAnalyzer gate passed.' + + # ===================================================================== + # NOT gated, and why -- each of these would fail today: + # + # PSUseCompatibleCommands (repo-wide) 21,889 -- 21,870 of them in Tests/, because + # the rule knows only built-in commands and so + # reports every Pester `Should` parameter. + # Gated on Public/ only, above. + # PSAvoidGlobalVars 61, a deliberate Pester cross-mock-scope + # pattern. In the PSGallery preset, so it is + # kept in the settings file and not gated. + # PSUseSingularNouns 44, deliberately kept in the settings file + # and deliberately not gated. + # PSAvoidUsingEmptyCatchBlock 11, deferred to dmann000/fb-powershell#117, + # which already adjudicated all three shipped + # sites. Reported, never gated -- so this job + # is green with them outstanding, and fixing + # one would need a live FlashBlade run because + # every working fix adds an executable line to + # shipped code. A comment does NOT clear this + # rule. + # + # Warning count today: 149. Measured under the committed settings file, not carried + # forward -- every earlier figure here went stale within days: 302, then 276 once + # T1/T2 and T3 took the BOM 24 and the automatic-variable 1 to zero, then 149 once the + # 127 dead $manifest assignments went. Re-measure rather than trusting this line. + # ===================================================================== + test-windows-powershell-5-1: name: Test (windows-latest, Windows PowerShell 5.1) runs-on: windows-latest diff --git a/PSScriptAnalyzerSettings.psd1 b/PSScriptAnalyzerSettings.psd1 new file mode 100644 index 00000000..d50ba48d --- /dev/null +++ b/PSScriptAnalyzerSettings.psd1 @@ -0,0 +1,156 @@ +@{ + # PSScriptAnalyzer settings for PureStorageFlashBladePowerShell. + # + # Every count below was measured by pssa-tasks\New-PfbPssaSettings.ps1 at the moment + # this file was generated, so each is reproducible against a known tree: + # 2026-08-28, commit 03ea602, PSScriptAnalyzer 1.25.0 + # The sweep covers Public/, Private/, + # Tests/, tools/, scripts/ AND the repo root (the root matters: the .psd1/.psm1 live + # there, and a five-directory sweep silently never analyses them, which makes four + # manifest/module rules -- including the preset's own PSMissingModuleManifestField -- + # unable to fire at all). + + IncludeRules = @( + # --- the PSGallery preset verbatim, because publication is the goal. + # Kept complete even where it costs signal. PSUseSingularNouns produces + # 44 findings -- 29 internal helpers, 15 exported cmdlets + # and stays in, because a file claiming to target the preset should not quietly + # diverge from it. They are documented in + # PSScriptAnalyzer-baseline-2026-08-26.md, which is the + # "compelling reason ... add that information to your documentation" the + # Gallery guidelines ask for. + 'PSUseApprovedVerbs', 'PSReservedCmdletChar', 'PSReservedParams', + 'PSShouldProcess', 'PSUseShouldProcessForStateChangingFunctions', + 'PSUseSingularNouns', 'PSMissingModuleManifestField', + 'PSAvoidDefaultValueSwitchParameter', 'PSAvoidUsingCmdletAliases', + 'PSAvoidUsingWMICmdlet', 'PSAvoidUsingEmptyCatchBlock', + 'PSUseCmdletCorrectly', 'PSAvoidUsingPositionalParameters', + 'PSAvoidGlobalVars', 'PSUseDeclaredVarsMoreThanAssignments', + 'PSAvoidUsingInvokeExpression', 'PSAvoidUsingPlainTextForPassword', + 'PSAvoidUsingComputerNameHardcoded', 'PSUsePSCredentialType', 'PSDSC*', + + # --- not in the preset, but each caught something real in this repo + 'PSUseBOMForUnicodeEncodedFile', # the BOM-less non-ASCII defect: such a + # file decodes as UTF-8 on pwsh 7 and + # Windows-1252 on 5.1, so Get-Help + # renders mojibake on 5.1 only + 'PSAvoidAssignmentToAutomaticVariable', # assignment to $matches + + # --- not in the preset, at ZERO repo-wide, adopted as a regression guard. + # Configured below; without that configuration it finds nothing and reports a + # vacuous zero rather than an error. + 'PSUseCompatibleSyntax' + + # PSUseCompatibleCommands is NOT listed, and this is a correction to an earlier + # draft that adopted it as a second guard on a measured "zero". That zero was + # scope-limited. Repo-wide it is 21889: + # Public/ 0 Private/ 2 Tests/ 21870 tools/ 14 scripts/ 3 root 0 + # Tests/ dominates because the rule compares against profiles of BUILT-IN + # commands only, so every Pester assertion is reported -- "The parameter 'Throw' + # is not available for command 'Should'". Private/'s 2 are ConvertFrom-Json + # -Depth, both already inside an `if ($PSVersionTable.PSVersion.Major -ge 6)` + # guard: the rule reads neither version guards nor #Requires, the same + # guard-blindness that makes PSUseCompatibleTypes unusable here. + # Only Public/ is genuinely clean, so it is gated there like T11 -- see below. + + # PSProvideCommentHelp is deliberately NOT listed here. It is configured below + # but only ever requested explicitly by the CI step, scoped to Public/. + # Listing it would add 133 Information findings to every ordinary run. + # + # A caller's -IncludeRule is UNION'd with this allowlist -- measured, and NOT + # the override an earlier draft recorded. So the CI step must filter its results + # by RuleName: with this file, `-IncludeRule PSProvideCommentHelp` over Public/ + # returns 22 records, none of them PSProvideCommentHelp, and a naive + # `.Count -gt 0` gate fails on unrelated preset findings. + # ExcludeRules is the asymmetric one: it VETOES a caller's -IncludeRule. So + # excluding this rule here, rather than merely not listing it, would break the + # gate outright. + ) + + Rules = @{ + # Gate for Public/ only. ExportedOnly = $true -- the DEFAULT -- makes this rule + # inert in this codebase: one function per dot-sourced file, exports declared in + # the manifest, so no analysed file holds its own export statement and the rule + # reports 0 across all 544 cmdlets WITHOUT EVALUATING ANY OF THEM. + # With ExportedOnly = $false, tools/ counted with tools/lib/: + # Public/ 0 Private/ 12 Tests/ 102 tools/ 17 scripts/ 2 root 0 + # Public/ being 0 is the real finding -- every exported cmdlet is + # documented -- and that is what CI holds. Severity is Information, so the CI + # step must name the rule; a severity threshold would never see it. + PSProvideCommentHelp = @{ + Enable = $true + ExportedOnly = $false + } + + # TargetVersions / TargetProfiles are REQUIRED, not tuning. Without them these + # two rules evaluate nothing and return 0. Control-verified 2026-08-28. + PSUseCompatibleSyntax = @{ + Enable = $true + TargetVersions = @('5.1', '7.0') + } + # Configured but NOT in IncludeRules, for the reason recorded above. CI requests + # it explicitly and scoped to Public/, where it is genuinely 0. + PSUseCompatibleCommands = @{ + Enable = $true + TargetProfiles = @( + 'win-48_x64_10.0.17763.0_5.1.17763.316_x64_4.0.30319.42000_framework', + 'win-8_x64_10.0.17763.0_7.0.0_x64_3.1.2_core' + ) + } + } + + # ===================================================================== + # T10 -- the ten default-disabled rules stay OFF. Recorded, not omitted. + # ===================================================================== + # + # These are disabled by default in PSScriptAnalyzer and are NOT enabled here. Their + # counts are written down so their absence reads as a decision rather than an + # oversight, and so nobody enables one without knowing the size of the sweep it + # implies. Force-enable sweep, 2026-08-28, all five directories plus the + # root, each rule enabled on its own (PSAvoidLongLines at its 120-column default, + # without which it measures nothing): + # + # PSUseConstrainedLanguageMode 4825 + # PSAvoidLongLines 3614 + # PSUseConsistentWhitespace 3419 + # PSUseConsistentIndentation 980 + # PSAlignAssignmentStatement 503 + # PSPlaceCloseBrace 180 + # PSAvoidUsingDoubleQuotesForConstantString 106 + # PSUseConsistentParameterSetName 93 + # PSUseConsistentParametersKind 54 + # PSUseCorrectCasing 52 + # ------ + # 13826 + # + # PSUseConstrainedLanguageMode is the one to be careful about: it is not a style + # rule, and its 4825 findings are not formatting debt. It reports constructs that + # would fail under Constrained Language Mode. This module is not supported under CLM + # and does not claim to be, so the rule is off -- but enabling it "to tidy up" would + # be a functional change, not a cosmetic one. + # + # ALSO NOT ADOPTED, and for a different reason: PSUseCompatibleTypes. It is at + # 30, not 0. All were verified false positives -- each flagged member was + # executed on both 5.1 and 7 -- because it reads neither $PSVersionTable guards nor + # #Requires, so a type used only inside a correctly-guarded branch is still + # reported. It must not be adopted on a mistaken "it's already clean" reading. + # + # Rules deliberately left out of IncludeRules, with counts and reasons: + # PSReviewUnusedParameter 62 ArgumentCompleter scriptblocks must take + # the full signature even when only + # $WordToComplete is used; also fires on + # Pester scriptblock params it cannot see + # through + # PSAvoidUsingWriteHost 94 the flagged files are CLI scripts and + # build tools whose job is console output + # PSUseOutputTypeCorrectly 108 Information-only polish across + # 544 cmdlets; no correctness content + # PSUseProcessBlockForPipelineCommand 31 test helpers are not pipeline cmdlets + # PSAvoidUsingConvertToSecureStringWithPlainText + # 21 test fixtures only, and SUPPRESSED at the + # sites (T9) rather than switched off + # globally -- so it still fires for Public/ + # and Private/, where it would be real. + # The count is suppressed SITES, not live + # findings +} \ No newline at end of file diff --git a/Private/Invoke-PfbApiRequest.ps1 b/Private/Invoke-PfbApiRequest.ps1 index 8b998634..f06cc14b 100644 --- a/Private/Invoke-PfbApiRequest.ps1 +++ b/Private/Invoke-PfbApiRequest.ps1 @@ -213,7 +213,7 @@ function Invoke-PfbApiRequest { $restParams['SkipCertificateCheck'] = $true } - # HTTP timeout handling — default to 30s if the connection object predates this field + # HTTP timeout handling -- default to 30s if the connection object predates this field $restParams['TimeoutSec'] = if ($Array.HttpTimeoutMs) { [int][Math]::Ceiling($Array.HttpTimeoutMs / 1000.0) } else { 30 } # If the caller set a page-size/limit query param (every Get-Pfb* cmdlet's -Limit maps to @@ -313,7 +313,7 @@ function Invoke-PfbApiRequest { $reconnectSucceeded = $true } catch { - # Reconnect failed — fall through to error formatting below + # Reconnect failed -- fall through to error formatting below } if (-not $reconnectSucceeded) { diff --git a/Private/New-PfbJwtToken.ps1 b/Private/New-PfbJwtToken.ps1 index 9043bc20..169c1a2a 100644 --- a/Private/New-PfbJwtToken.ps1 +++ b/Private/New-PfbJwtToken.ps1 @@ -72,7 +72,7 @@ function New-PfbJwtToken { $rsa.ImportRSAPrivateKey($keyBytes, [ref]$bytesRead) } else { - # PS 5.1 — use RSACryptoServiceProvider with manual PKCS#1 parsing + # PS 5.1 -- use RSACryptoServiceProvider with manual PKCS#1 parsing $rsa = New-Object System.Security.Cryptography.RSACryptoServiceProvider # Try importing as PKCS#1 via CNG if available try { @@ -95,7 +95,7 @@ function New-PfbJwtToken { $rsa.ImportPkcs8PrivateKey($keyBytes, [ref]$bytesRead) } else { - # PS 5.1 — CNG can import PKCS#8 directly + # PS 5.1 -- CNG can import PKCS#8 directly $cng = [System.Security.Cryptography.CngKey]::Import($keyBytes, [System.Security.Cryptography.CngKeyBlobFormat]::Pkcs8PrivateBlob) $rsa = New-Object System.Security.Cryptography.RSACng($cng) } diff --git a/Public/Connection/Connect-PfbArray.ps1 b/Public/Connection/Connect-PfbArray.ps1 index 0c1985a1..de43232e 100644 --- a/Public/Connection/Connect-PfbArray.ps1 +++ b/Public/Connection/Connect-PfbArray.ps1 @@ -44,7 +44,7 @@ function Connect-PfbArray { The API token for authentication. Generate via the FlashBlade CLI or GUI. .PARAMETER Username Login name of the array user. For Credential auth: used with -Password. - For Certificate auth: the JWT 'sub' claim — the array user to act as. + For Certificate auth: the JWT 'sub' claim -- the array user to act as. .PARAMETER Password Password for the specified username as a SecureString. .PARAMETER Credential @@ -318,7 +318,7 @@ function Connect-PfbArray { $nativeLoginSupported = [bool]($parsedVersions | Where-Object { $_.Major -gt 2 -or ($_.Major -eq 2 -and $_.Minor -ge 26) }) if ($nativeLoginSupported) { - # Native REST 2.x username/password login — POST /api/login with JSON body. + # Native REST 2.x username/password login -- POST /api/login with JSON body. # /api/login is unversioned and is part of REST 2.x. No SSH required. $bstr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password) try { @@ -485,7 +485,7 @@ function Connect-PfbArray { 'release (Update-Module).') } - # Build connection object — properties align with PureRestClientBase (Pfa2) + # Build connection object -- properties align with PureRestClientBase (Pfa2) $connection = [PSCustomObject]@{ PSTypeName = 'PureStorage.FlashBlade.Connection' # Pfa2-aligned properties @@ -508,7 +508,7 @@ function Connect-PfbArray { # Diagnostic: array outruns the bundled capability map's scanned range. Deliberately # NOT in $defaultProps below -- diagnostic state, not default-display material. ExceedsCapabilityMapCoverage = $exceedsCapabilityMapCoverage - # Certificate/OAuth2 refresh state — only populated when AuthMethod is 'Certificate' + # Certificate/OAuth2 refresh state -- only populated when AuthMethod is 'Certificate' ClientId = $ClientId Issuer = $Issuer KeyId = $KeyId @@ -530,8 +530,8 @@ function Connect-PfbArray { } # Hide secrets from default display. Sensitive fields (ApiToken, AuthToken, - # BearerToken) are still accessible programmatically — Format-List * / direct - # property access ($conn.ApiToken) work — but they no longer appear in the + # BearerToken) are still accessible programmatically -- Format-List * / direct + # property access ($conn.ApiToken) work -- but they no longer appear in the # default Format-List view that runs when a user just types $conn at the prompt. $defaultProps = @( 'HttpEndpoint', 'Endpoint', 'Username', 'AuthMethod', diff --git a/Public/DataEviction/Remove-PfbDataEvictionPolicy.ps1 b/Public/DataEviction/Remove-PfbDataEvictionPolicy.ps1 index 07052df8..1166b2e4 100644 --- a/Public/DataEviction/Remove-PfbDataEvictionPolicy.ps1 +++ b/Public/DataEviction/Remove-PfbDataEvictionPolicy.ps1 @@ -4,7 +4,7 @@ function Remove-PfbDataEvictionPolicy { Removes a data eviction policy from the FlashBlade. .DESCRIPTION Deletes a data eviction policy. The policy must not be attached to any file - systems — detach via Remove-PfbDataEvictionPolicyFileSystem first. + systems -- detach via Remove-PfbDataEvictionPolicyFileSystem first. .PARAMETER Name Policy name to remove. .PARAMETER Id diff --git a/Public/FileSystem/New-PfbFileSystem.ps1 b/Public/FileSystem/New-PfbFileSystem.ps1 index 67049cca..06c47dba 100644 --- a/Public/FileSystem/New-PfbFileSystem.ps1 +++ b/Public/FileSystem/New-PfbFileSystem.ps1 @@ -10,11 +10,11 @@ function New-PfbFileSystem { Note: when neither -Nfs nor -Smb nor -Http is passed, the file system is created with all protocols disabled. The FlashBlade may still expose internal NFS/SMB - export records in a disabled state — this is API behavior, not a module bug. Only + export records in a disabled state -- this is API behavior, not a module bug. Only the protocol switches you pass are flipped to enabled. Default exports: on REST 2.16 and newer, this cmdlet sends the API's documented - empty value — a quoted empty string as the single default_exports array item — when + empty value -- a quoted empty string as the single default_exports array item -- when -DefaultExports is omitted, so no default NFS or SMB export is created unless you ask for one. On REST 2.0 through 2.15, omission sends no unsupported query key and preserves that API era's filesystem access semantics. Explicit -DefaultExports @@ -51,7 +51,7 @@ function New-PfbFileSystem { Enable SMB. .PARAMETER SmbSharePolicy Name of a pre-existing SMB Share Policy to attach. Without this, SMB defaults to - full access — set this for any non-lab share. + full access -- set this for any non-lab share. .PARAMETER SmbClientPolicy Name of a pre-existing SMB Client Policy to attach. .PARAMETER SmbContinuousAvailabilityEnabled @@ -105,7 +105,7 @@ function New-PfbFileSystem { attach its built-in full-access share policy to the default SMB export. .PARAMETER Attributes Full request body as a hashtable. Mutually exclusive with the typed parameters - above — use only when the typed params don't expose a field you need. + above -- use only when the typed params don't expose a field you need. -DefaultExports still applies: it is a query parameter and never enters the body, so the hashtable you supply is passed through untouched. .PARAMETER Array @@ -240,7 +240,7 @@ function New-PfbFileSystem { if ($SourceSnapshot) { $body['source'] = @{ name = $SourceSnapshot } } if ($QosPolicy) { $body['qos_policy'] = @{ name = $QosPolicy } } - # NFS — note: local hashtable name avoids collision with [switch]$Nfs (PowerShell vars are case-insensitive) + # NFS -- note: local hashtable name avoids collision with [switch]$Nfs (PowerShell vars are case-insensitive) $nfsBody = @{} if ($Nfs -or $NfsV3) { $nfsBody['v3_enabled'] = $true } if ($Nfs -or $NfsV41) { $nfsBody['v4_1_enabled'] = $true } @@ -251,11 +251,11 @@ function New-PfbFileSystem { elseif ($NfsRules) { $nfsBody['rules'] = $NfsRules } if ($nfsBody.Count -gt 0) { $body['nfs'] = $nfsBody } - # SMB — local name avoids collision with [switch]$Smb + # SMB -- local name avoids collision with [switch]$Smb # # Two independent triggers build the smb body, and only one of them turns SMB on. # -SmbContinuousAvailabilityEnabled configures how SMB behaves if it is serving, so - # supplying it must never flip smb.enabled — that would silently expose the file + # supplying it must never flip smb.enabled -- that would silently expose the file # system over a protocol the caller never asked for, and (without a share policy) # under the array's built-in full-access policy. $smbEnablementRequested = [bool]($Smb -or $SmbSharePolicy -or $SmbClientPolicy) @@ -293,7 +293,7 @@ function New-PfbFileSystem { $queryParams = @{ 'names' = $Name } - # default_exports is a QUERY parameter only — it must never enter $body, including on the + # default_exports is a QUERY parameter only -- it must never enter $body, including on the # -Attributes path, where the caller owns the body outright. # # The local is deliberately named differently from the parameter: a local whose name @@ -301,7 +301,7 @@ function New-PfbFileSystem { # $DefaultExports here would re-run its ValidateSet against the empty value and throw. # # On REST 2.16 and newer, the omitted case is a single-element array whose one item is a - # QUOTED empty string — two literal single-quote characters. The API's documented "empty + # QUOTED empty string -- two literal single-quote characters. The API's documented "empty # string" value for "create no default exports" is that quoted empty string as the array # item: a bare `default_exports=` is rejected by the array with HTTP 400 "Missing or invalid # parameter", while the quoted form (`default_exports=%27%27` on the wire) is accepted and @@ -310,7 +310,7 @@ function New-PfbFileSystem { # It must also be an array rather than a scalar: ConvertTo-PfbQueryString joins arrays with # commas, and the array form is what the parameter is specified to take. It is assigned in # two statements rather than from an if/else expression because an if/else yields pipeline - # output, where a single-element array collapses back to its element — direct assignment of + # output, where a single-element array collapses back to its element -- direct assignment of # an array literal does not. $defaultExportsSupported = $false if ($Array.ApiVersion) { diff --git a/Public/FileSystem/New-PfbFileSystemExport.ps1 b/Public/FileSystem/New-PfbFileSystemExport.ps1 index a5692648..ab14cd03 100644 --- a/Public/FileSystem/New-PfbFileSystemExport.ps1 +++ b/Public/FileSystem/New-PfbFileSystemExport.ps1 @@ -6,11 +6,11 @@ function New-PfbFileSystemExport { Creates a file system export that makes a file system visible on a server under an export policy. Per the FlashBlade REST API, an export links three things: - a file system (query parameter 'member_names'), - - an export policy (query parameter 'policy_names') — an NFS export policy for NFS, + - an export policy (query parameter 'policy_names') -- an NFS export policy for NFS, - a server, plus (for SMB) an SMB share policy, supplied in the request body. This replaces the previous behavior, which incorrectly sent 'names=' and an - arbitrary body — the API rejected it, so export creation did not work. + arbitrary body -- the API rejected it, so export creation did not work. .PARAMETER FileSystem Name of the file system the export exposes. Sent as 'member_names'. .PARAMETER Policy diff --git a/Public/Network/New-PfbNetworkInterface.ps1 b/Public/Network/New-PfbNetworkInterface.ps1 index 9db6d267..3f31e079 100644 --- a/Public/Network/New-PfbNetworkInterface.ps1 +++ b/Public/Network/New-PfbNetworkInterface.ps1 @@ -4,7 +4,7 @@ function New-PfbNetworkInterface { Creates a new network interface (VIP) on the FlashBlade. .DESCRIPTION Creates a virtual IP. The FlashBlade derives the associated subnet, gateway, - netmask, MTU and VLAN from `-Address` — those fields are read-only in the API + netmask, MTU and VLAN from `-Address` -- those fields are read-only in the API and cannot be sent in the create body. A subnet covering `-Address` must already exist (create with New-PfbSubnet). .PARAMETER Name @@ -23,7 +23,7 @@ function New-PfbNetworkInterface { .PARAMETER Attributes Full request body as a hashtable. Use this only when the typed parameters above don't expose a field you need (e.g. a brand-new 2.x API field). Mutually - exclusive with -Address / -Services / -AttachedServers / -Type — if you pass + exclusive with -Address / -Services / -AttachedServers / -Type -- if you pass -Attributes, those typed params will not be accepted. .PARAMETER Array The FlashBlade connection object. diff --git a/Public/Policy/Get-PfbPolicyAllMember.ps1 b/Public/Policy/Get-PfbPolicyAllMember.ps1 index 7c9bb7b8..a34dc6ff 100644 --- a/Public/Policy/Get-PfbPolicyAllMember.ps1 +++ b/Public/Policy/Get-PfbPolicyAllMember.ps1 @@ -30,7 +30,7 @@ function Get-PfbPolicyAllMember { One or more member types to filter by (e.g. "file-systems", "object-store-users"). Tab-completes the values documented as of this module's release, but the server's accepted set has grown across REST versions and may include newer values not offered - here — any value is passed through as-is, not validated client-side. + here -- any value is passed through as-is, not validated client-side. .PARAMETER Filter A server-side filter expression to narrow results. .PARAMETER Limit diff --git a/Public/Presets/New-PfbPresetWorkload.ps1 b/Public/Presets/New-PfbPresetWorkload.ps1 index 2d489d76..45a53fff 100644 --- a/Public/Presets/New-PfbPresetWorkload.ps1 +++ b/Public/Presets/New-PfbPresetWorkload.ps1 @@ -6,7 +6,7 @@ function New-PfbPresetWorkload { Defines a parameterized template that workloads can be instantiated from. The body schema (PresetWorkloadPost) is heavily nested (directory_configurations, placement_configurations, platform_features are required; export/QoS/quota/snapshot - configurations are optional). Pass the full body via -Attributes — the typed surface + configurations are optional). Pass the full body via -Attributes -- the typed surface would be too large to be useful. .PARAMETER Name Preset name(s) to create. diff --git a/Public/Server/New-PfbServer.ps1 b/Public/Server/New-PfbServer.ps1 index a3e424fa..5cf840ae 100644 --- a/Public/Server/New-PfbServer.ps1 +++ b/Public/Server/New-PfbServer.ps1 @@ -17,7 +17,7 @@ function New-PfbServer { Pass an empty string to skip auto-creation if the FlashBlade supports it. .PARAMETER Attributes Full request body as a hashtable. Mutually exclusive with the typed parameters - above — use only when a field you need isn't exposed. + above -- use only when a field you need isn't exposed. .PARAMETER Array FlashBlade connection. .EXAMPLE diff --git a/Reports/PfbValueEnumReconciliation.md b/Reports/PfbValueEnumReconciliation.md index ba9835a2..c0d2bb0b 100644 --- a/Reports/PfbValueEnumReconciliation.md +++ b/Reports/PfbValueEnumReconciliation.md @@ -2,7 +2,7 @@ Generated by `tools/Build-PfbValueEnumMap.ps1` against `Reports/PfbValueEnumMap.json` (29 REST versions, 301 entries). -Compares every hand-written `ValidateSet` in `Public/` that encodes a spec-documented value enum against the newly extracted prose data. Report only — no `Public/` cmdlet is edited by this script. See `Value-Enum-Extraction-Work.md` for the full non-goal list. +Compares every hand-written `ValidateSet` in `Public/` that encodes a spec-documented value enum against the newly extracted prose data. Report only -- no `Public/` cmdlet is edited by this script. See `Value-Enum-Extraction-Work.md` for the full non-goal list. | File:Line | Parameter | Hand-written values | Spec values | Status | Note | |---|---|---|---|---|---| diff --git a/Tests/Assert-PfbAdminNameNotCoerced.Tests.ps1 b/Tests/Assert-PfbAdminNameNotCoerced.Tests.ps1 index 6c7809fd..ff14bad5 100644 --- a/Tests/Assert-PfbAdminNameNotCoerced.Tests.ps1 +++ b/Tests/Assert-PfbAdminNameNotCoerced.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule } diff --git a/Tests/Assert-PfbApiCapability.Tests.ps1 b/Tests/Assert-PfbApiCapability.Tests.ps1 index 63808ff8..c4d76706 100644 --- a/Tests/Assert-PfbApiCapability.Tests.ps1 +++ b/Tests/Assert-PfbApiCapability.Tests.ps1 @@ -9,8 +9,6 @@ #> BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Assert-PfbSelectorNotCoerced.Tests.ps1 b/Tests/Assert-PfbSelectorNotCoerced.Tests.ps1 index 4ecadb83..d98cffba 100644 --- a/Tests/Assert-PfbSelectorNotCoerced.Tests.ps1 +++ b/Tests/Assert-PfbSelectorNotCoerced.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule $script:fakeArray = [PSCustomObject]@{ diff --git a/Tests/Build-PfbCapabilityMap.Tests.ps1 b/Tests/Build-PfbCapabilityMap.Tests.ps1 index 56d4fdc5..37c188f5 100644 --- a/Tests/Build-PfbCapabilityMap.Tests.ps1 +++ b/Tests/Build-PfbCapabilityMap.Tests.ps1 @@ -15,7 +15,7 @@ Describe 'Build-PfbCapabilityMap: introduced-in diffing' -Skip:($PSVersionTable. BeforeAll { New-Item -ItemType Directory -Path 'TestDrive:\specs' -Force | Out-Null - # v9.0: baseline — GET /widgets (param: filter), POST /widgets (body: name) + # v9.0: baseline -- GET /widgets (param: filter), POST /widgets (body: name) $specV1 = [ordered]@{ openapi = '3.0.1' info = @{ version = '9.0' } diff --git a/Tests/Build-PfbValueEnumMap.Tests.ps1 b/Tests/Build-PfbValueEnumMap.Tests.ps1 index 2c955cbd..500623d9 100644 --- a/Tests/Build-PfbValueEnumMap.Tests.ps1 +++ b/Tests/Build-PfbValueEnumMap.Tests.ps1 @@ -6,7 +6,7 @@ regression check of the real committed manifest when present. .DESCRIPTION Every invocation below passes explicit -OutputPath AND -ReconciliationPath under - TestDrive: — never let the script fall back to its real-repo defaults, or running + TestDrive: -- never let the script fall back to its real-repo defaults, or running these tests would overwrite Reports/PfbValueEnumMap.json and Reports/PfbValueEnumReconciliation.md as a side effect. #> diff --git a/Tests/Connect-PfbArray.CapabilityMapStaleness.Tests.ps1 b/Tests/Connect-PfbArray.CapabilityMapStaleness.Tests.ps1 index e05571f8..d94d0543 100644 --- a/Tests/Connect-PfbArray.CapabilityMapStaleness.Tests.ps1 +++ b/Tests/Connect-PfbArray.CapabilityMapStaleness.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule } diff --git a/Tests/Connect-PfbArray.Context.Tests.ps1 b/Tests/Connect-PfbArray.Context.Tests.ps1 index 84535280..a5f0d57a 100644 --- a/Tests/Connect-PfbArray.Context.Tests.ps1 +++ b/Tests/Connect-PfbArray.Context.Tests.ps1 @@ -1,4 +1,7 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', + Justification = 'Test fixture credential built from a literal; no other idiom exists for constructing a known-value SecureString in a test.')] +param() BeforeAll { . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') diff --git a/Tests/Connect-PfbArray.NativeLoginVersionGate.Tests.ps1 b/Tests/Connect-PfbArray.NativeLoginVersionGate.Tests.ps1 index 3e0c8731..61015e87 100644 --- a/Tests/Connect-PfbArray.NativeLoginVersionGate.Tests.ps1 +++ b/Tests/Connect-PfbArray.NativeLoginVersionGate.Tests.ps1 @@ -1,8 +1,9 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', + Justification = 'Test fixture credential built from a literal; no other idiom exists for constructing a known-value SecureString in a test.')] +param() BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Connect-PfbArray.OAuth2TokenRefresh.Tests.ps1 b/Tests/Connect-PfbArray.OAuth2TokenRefresh.Tests.ps1 index 20de7d98..bd0ac4d1 100644 --- a/Tests/Connect-PfbArray.OAuth2TokenRefresh.Tests.ps1 +++ b/Tests/Connect-PfbArray.OAuth2TokenRefresh.Tests.ps1 @@ -1,8 +1,9 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', + Justification = 'Test fixture credential built from a literal; no other idiom exists for constructing a known-value SecureString in a test.')] +param() BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/ConvertTo-PfbApiError.Tests.ps1 b/Tests/ConvertTo-PfbApiError.Tests.ps1 index 5b502fe9..3617ad13 100644 --- a/Tests/ConvertTo-PfbApiError.Tests.ps1 +++ b/Tests/ConvertTo-PfbApiError.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/ConvertTo-PfbVersionObject.Tests.ps1 b/Tests/ConvertTo-PfbVersionObject.Tests.ps1 index caaadb24..8c539cd9 100644 --- a/Tests/ConvertTo-PfbVersionObject.Tests.ps1 +++ b/Tests/ConvertTo-PfbVersionObject.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule } diff --git a/Tests/FileSystemExportAndLocalDirectoryServices.Tests.ps1 b/Tests/FileSystemExportAndLocalDirectoryServices.Tests.ps1 index e0fe25a5..c3b990f2 100644 --- a/Tests/FileSystemExportAndLocalDirectoryServices.Tests.ps1 +++ b/Tests/FileSystemExportAndLocalDirectoryServices.Tests.ps1 @@ -1,7 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule $script:fakeArray = [PSCustomObject]@{ Endpoint = 'fb.example.test'; ApiVersion = '2.26'; AuthToken = 'x' } diff --git a/Tests/Get-PfbApiToken.Tests.ps1 b/Tests/Get-PfbApiToken.Tests.ps1 index afca6222..afa2d079 100644 --- a/Tests/Get-PfbApiToken.Tests.ps1 +++ b/Tests/Get-PfbApiToken.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbApiTokenViaSsh.Tests.ps1 b/Tests/Get-PfbApiTokenViaSsh.Tests.ps1 index 6ef4b8a7..7929c618 100644 --- a/Tests/Get-PfbApiTokenViaSsh.Tests.ps1 +++ b/Tests/Get-PfbApiTokenViaSsh.Tests.ps1 @@ -1,8 +1,9 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', + Justification = 'Test fixture credential built from a literal; no other idiom exists for constructing a known-value SecureString in a test.')] +param() BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbArrayConnection.Tests.ps1 b/Tests/Get-PfbArrayConnection.Tests.ps1 index 66d099cf..34fd688e 100644 --- a/Tests/Get-PfbArrayConnection.Tests.ps1 +++ b/Tests/Get-PfbArrayConnection.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbArrayConnectionKey.Tests.ps1 b/Tests/Get-PfbArrayConnectionKey.Tests.ps1 index 2f403532..f7762b26 100644 --- a/Tests/Get-PfbArrayConnectionKey.Tests.ps1 +++ b/Tests/Get-PfbArrayConnectionKey.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbArrayConnectionPath.Tests.ps1 b/Tests/Get-PfbArrayConnectionPath.Tests.ps1 index 471916fa..cf9e00fe 100644 --- a/Tests/Get-PfbArrayConnectionPath.Tests.ps1 +++ b/Tests/Get-PfbArrayConnectionPath.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbBucketReplicaLink.Tests.ps1 b/Tests/Get-PfbBucketReplicaLink.Tests.ps1 index 9ac6e9a5..bb078c87 100644 --- a/Tests/Get-PfbBucketReplicaLink.Tests.ps1 +++ b/Tests/Get-PfbBucketReplicaLink.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbCapabilityMap.Tests.ps1 b/Tests/Get-PfbCapabilityMap.Tests.ps1 index 990ac4e3..55b335aa 100644 --- a/Tests/Get-PfbCapabilityMap.Tests.ps1 +++ b/Tests/Get-PfbCapabilityMap.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbFileSystemGroup.Tests.ps1 b/Tests/Get-PfbFileSystemGroup.Tests.ps1 index 403a0cb9..3e5c3047 100644 --- a/Tests/Get-PfbFileSystemGroup.Tests.ps1 +++ b/Tests/Get-PfbFileSystemGroup.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbFileSystemGroupQuota.Tests.ps1 b/Tests/Get-PfbFileSystemGroupQuota.Tests.ps1 index 3b4c8951..1a3b6332 100644 --- a/Tests/Get-PfbFileSystemGroupQuota.Tests.ps1 +++ b/Tests/Get-PfbFileSystemGroupQuota.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbFileSystemReplicaLink.Tests.ps1 b/Tests/Get-PfbFileSystemReplicaLink.Tests.ps1 index e2a023b4..e02c7c0e 100644 --- a/Tests/Get-PfbFileSystemReplicaLink.Tests.ps1 +++ b/Tests/Get-PfbFileSystemReplicaLink.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbFileSystemReplicaLinkTransfer.Tests.ps1 b/Tests/Get-PfbFileSystemReplicaLinkTransfer.Tests.ps1 index febf2135..97cb4e0c 100644 --- a/Tests/Get-PfbFileSystemReplicaLinkTransfer.Tests.ps1 +++ b/Tests/Get-PfbFileSystemReplicaLinkTransfer.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbFileSystemUser.Tests.ps1 b/Tests/Get-PfbFileSystemUser.Tests.ps1 index 0fc9f53c..c718ecd3 100644 --- a/Tests/Get-PfbFileSystemUser.Tests.ps1 +++ b/Tests/Get-PfbFileSystemUser.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbFileSystemUserGroupQuotaPolicy.Tests.ps1 b/Tests/Get-PfbFileSystemUserGroupQuotaPolicy.Tests.ps1 index e916a351..59504ef3 100644 --- a/Tests/Get-PfbFileSystemUserGroupQuotaPolicy.Tests.ps1 +++ b/Tests/Get-PfbFileSystemUserGroupQuotaPolicy.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbFileSystemUserQuota.Tests.ps1 b/Tests/Get-PfbFileSystemUserQuota.Tests.ps1 index a77ea970..dfb8d8c6 100644 --- a/Tests/Get-PfbFileSystemUserQuota.Tests.ps1 +++ b/Tests/Get-PfbFileSystemUserQuota.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbFleetMember.Tests.ps1 b/Tests/Get-PfbFleetMember.Tests.ps1 index 32c2e000..1e5a4dd5 100644 --- a/Tests/Get-PfbFleetMember.Tests.ps1 +++ b/Tests/Get-PfbFleetMember.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbRemoteArray.Tests.ps1 b/Tests/Get-PfbRemoteArray.Tests.ps1 index 711eb952..2c6d08e3 100644 --- a/Tests/Get-PfbRemoteArray.Tests.ps1 +++ b/Tests/Get-PfbRemoteArray.Tests.ps1 @@ -17,7 +17,6 @@ #> BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbSmtpServer.Tests.ps1 b/Tests/Get-PfbSmtpServer.Tests.ps1 index db6a1386..c990a6d1 100644 --- a/Tests/Get-PfbSmtpServer.Tests.ps1 +++ b/Tests/Get-PfbSmtpServer.Tests.ps1 @@ -6,8 +6,6 @@ #> BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbUserGroupQuotaPolicy.Tests.ps1 b/Tests/Get-PfbUserGroupQuotaPolicy.Tests.ps1 index beb951c9..887653b0 100644 --- a/Tests/Get-PfbUserGroupQuotaPolicy.Tests.ps1 +++ b/Tests/Get-PfbUserGroupQuotaPolicy.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbUserGroupQuotaPolicyFileSystem.Tests.ps1 b/Tests/Get-PfbUserGroupQuotaPolicyFileSystem.Tests.ps1 index 46c739ab..f01b99fc 100644 --- a/Tests/Get-PfbUserGroupQuotaPolicyFileSystem.Tests.ps1 +++ b/Tests/Get-PfbUserGroupQuotaPolicyFileSystem.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbUserGroupQuotaPolicyMember.Tests.ps1 b/Tests/Get-PfbUserGroupQuotaPolicyMember.Tests.ps1 index d0137203..10f10d03 100644 --- a/Tests/Get-PfbUserGroupQuotaPolicyMember.Tests.ps1 +++ b/Tests/Get-PfbUserGroupQuotaPolicyMember.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbUserGroupQuotaPolicyRule.Tests.ps1 b/Tests/Get-PfbUserGroupQuotaPolicyRule.Tests.ps1 index 508a4a13..ba19574a 100644 --- a/Tests/Get-PfbUserGroupQuotaPolicyRule.Tests.ps1 +++ b/Tests/Get-PfbUserGroupQuotaPolicyRule.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Get-PfbVersionMap.Tests.ps1 b/Tests/Get-PfbVersionMap.Tests.ps1 index 55f4398f..80ec8f84 100644 --- a/Tests/Get-PfbVersionMap.Tests.ps1 +++ b/Tests/Get-PfbVersionMap.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Invoke-PfbApiRequest.EmptyResult.Tests.ps1 b/Tests/Invoke-PfbApiRequest.EmptyResult.Tests.ps1 index b5bad121..ff4f2ac7 100644 --- a/Tests/Invoke-PfbApiRequest.EmptyResult.Tests.ps1 +++ b/Tests/Invoke-PfbApiRequest.EmptyResult.Tests.ps1 @@ -20,8 +20,6 @@ # wrapper survives for a total-only read, and nothing else ever sees it. BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule } diff --git a/Tests/Invoke-PfbApiRequest.Tests.ps1 b/Tests/Invoke-PfbApiRequest.Tests.ps1 index 454926bc..9cfc39b2 100644 --- a/Tests/Invoke-PfbApiRequest.Tests.ps1 +++ b/Tests/Invoke-PfbApiRequest.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule } diff --git a/Tests/Invoke-PfbApiTokenLogin.Tests.ps1 b/Tests/Invoke-PfbApiTokenLogin.Tests.ps1 index c21982a7..c6be8d48 100644 --- a/Tests/Invoke-PfbApiTokenLogin.Tests.ps1 +++ b/Tests/Invoke-PfbApiTokenLogin.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule } diff --git a/Tests/Issue88.SelectorReachability.Tests.ps1 b/Tests/Issue88.SelectorReachability.Tests.ps1 index cd68ae81..f21db77a 100644 --- a/Tests/Issue88.SelectorReachability.Tests.ps1 +++ b/Tests/Issue88.SelectorReachability.Tests.ps1 @@ -188,7 +188,6 @@ $tableCoverageCase = @( # --------------------------------------------------------------------------- BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbApiClient.Tests.ps1 b/Tests/New-PfbApiClient.Tests.ps1 index e9e9c26e..2dba5286 100644 --- a/Tests/New-PfbApiClient.Tests.ps1 +++ b/Tests/New-PfbApiClient.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbApiToken.Tests.ps1 b/Tests/New-PfbApiToken.Tests.ps1 index 9b334a5e..b6af004f 100644 --- a/Tests/New-PfbApiToken.Tests.ps1 +++ b/Tests/New-PfbApiToken.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbArrayConnection.Tests.ps1 b/Tests/New-PfbArrayConnection.Tests.ps1 index 3bc1bb85..31606db7 100644 --- a/Tests/New-PfbArrayConnection.Tests.ps1 +++ b/Tests/New-PfbArrayConnection.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbCertificateCertificateGroup.Tests.ps1 b/Tests/New-PfbCertificateCertificateGroup.Tests.ps1 index b82f9e18..f889a694 100644 --- a/Tests/New-PfbCertificateCertificateGroup.Tests.ps1 +++ b/Tests/New-PfbCertificateCertificateGroup.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbFileSystem.Tests.ps1 b/Tests/New-PfbFileSystem.Tests.ps1 index d0c93408..01037d17 100644 --- a/Tests/New-PfbFileSystem.Tests.ps1 +++ b/Tests/New-PfbFileSystem.Tests.ps1 @@ -1,7 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule $script:fakeArray = [PSCustomObject]@{ Endpoint = 'fb.example.test'; ApiVersion = '2.26'; AuthToken = 'x' } diff --git a/Tests/New-PfbFileSystemReplicaLink.Tests.ps1 b/Tests/New-PfbFileSystemReplicaLink.Tests.ps1 index 1e0d842e..fb20cbc5 100644 --- a/Tests/New-PfbFileSystemReplicaLink.Tests.ps1 +++ b/Tests/New-PfbFileSystemReplicaLink.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbFileSystemReplicaLinkPolicy.Tests.ps1 b/Tests/New-PfbFileSystemReplicaLinkPolicy.Tests.ps1 index aef0d4b7..0d41fdb7 100644 --- a/Tests/New-PfbFileSystemReplicaLinkPolicy.Tests.ps1 +++ b/Tests/New-PfbFileSystemReplicaLinkPolicy.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbFileSystemUserGroupQuotaPolicy.Tests.ps1 b/Tests/New-PfbFileSystemUserGroupQuotaPolicy.Tests.ps1 index a5daf74c..886a1c7f 100644 --- a/Tests/New-PfbFileSystemUserGroupQuotaPolicy.Tests.ps1 +++ b/Tests/New-PfbFileSystemUserGroupQuotaPolicy.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbFleetMember.Tests.ps1 b/Tests/New-PfbFleetMember.Tests.ps1 index b2a01596..677b2256 100644 --- a/Tests/New-PfbFleetMember.Tests.ps1 +++ b/Tests/New-PfbFleetMember.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbJwtToken.Tests.ps1 b/Tests/New-PfbJwtToken.Tests.ps1 index 7aabdce5..de487802 100644 --- a/Tests/New-PfbJwtToken.Tests.ps1 +++ b/Tests/New-PfbJwtToken.Tests.ps1 @@ -1,8 +1,9 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } +[Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidUsingConvertToSecureStringWithPlainText', '', + Justification = 'Test fixture credential built from a literal; no other idiom exists for constructing a known-value SecureString in a test.')] +param() BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule } diff --git a/Tests/New-PfbLegalHoldEntity.Tests.ps1 b/Tests/New-PfbLegalHoldEntity.Tests.ps1 index b1129bf7..0ae42768 100644 --- a/Tests/New-PfbLegalHoldEntity.Tests.ps1 +++ b/Tests/New-PfbLegalHoldEntity.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbNetworkAccessRule.Tests.ps1 b/Tests/New-PfbNetworkAccessRule.Tests.ps1 index 1d52f066..aeda16a9 100644 --- a/Tests/New-PfbNetworkAccessRule.Tests.ps1 +++ b/Tests/New-PfbNetworkAccessRule.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbNetworkInterfaceTlsPolicy.Tests.ps1 b/Tests/New-PfbNetworkInterfaceTlsPolicy.Tests.ps1 index 64debc70..5b5361c2 100644 --- a/Tests/New-PfbNetworkInterfaceTlsPolicy.Tests.ps1 +++ b/Tests/New-PfbNetworkInterfaceTlsPolicy.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbNfsExportRule.Tests.ps1 b/Tests/New-PfbNfsExportRule.Tests.ps1 index 2c2e7beb..da2a96ff 100644 --- a/Tests/New-PfbNfsExportRule.Tests.ps1 +++ b/Tests/New-PfbNfsExportRule.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbNodeGroupNode.Tests.ps1 b/Tests/New-PfbNodeGroupNode.Tests.ps1 index 890c3fde..ec6b848b 100644 --- a/Tests/New-PfbNodeGroupNode.Tests.ps1 +++ b/Tests/New-PfbNodeGroupNode.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbObjectStoreAccountExport.Tests.ps1 b/Tests/New-PfbObjectStoreAccountExport.Tests.ps1 index 7506b57a..f3924b96 100644 --- a/Tests/New-PfbObjectStoreAccountExport.Tests.ps1 +++ b/Tests/New-PfbObjectStoreAccountExport.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbPolicyFileSystem.Tests.ps1 b/Tests/New-PfbPolicyFileSystem.Tests.ps1 index 81948564..5a9a2c50 100644 --- a/Tests/New-PfbPolicyFileSystem.Tests.ps1 +++ b/Tests/New-PfbPolicyFileSystem.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbPolicyFileSystemReplicaLink.Tests.ps1 b/Tests/New-PfbPolicyFileSystemReplicaLink.Tests.ps1 index 5ba6cc7d..4305eacd 100644 --- a/Tests/New-PfbPolicyFileSystemReplicaLink.Tests.ps1 +++ b/Tests/New-PfbPolicyFileSystemReplicaLink.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbQosPolicyMember.Tests.ps1 b/Tests/New-PfbQosPolicyMember.Tests.ps1 index b3fd1373..cc3af09b 100644 --- a/Tests/New-PfbQosPolicyMember.Tests.ps1 +++ b/Tests/New-PfbQosPolicyMember.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbQuotaGroup.Tests.ps1 b/Tests/New-PfbQuotaGroup.Tests.ps1 index fda230b7..3ee00878 100644 --- a/Tests/New-PfbQuotaGroup.Tests.ps1 +++ b/Tests/New-PfbQuotaGroup.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbQuotaUser.Tests.ps1 b/Tests/New-PfbQuotaUser.Tests.ps1 index 95f7a72a..de682c43 100644 --- a/Tests/New-PfbQuotaUser.Tests.ps1 +++ b/Tests/New-PfbQuotaUser.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule @@ -75,7 +73,7 @@ Describe 'New-PfbQuotaUser' { # Deliberately does NOT invoke the cmdlet with neither -UserName nor -UserId: # PowerShell's own parameter binder can't resolve a parameter set in that case, # falls back to the default ('ByName'), and then PROMPTS INTERACTIVELY for the - # missing mandatory -UserName instead of letting the cmdlet's own code run — + # missing mandatory -UserName instead of letting the cmdlet's own code run -- # which hangs forever with no TTY to answer it (confirmed live, in both a real # interactive terminal and this suite's own non-interactive runner). Asserting # against the parameter metadata proves the same "neither supplied" case is diff --git a/Tests/New-PfbS3ExportRule.Tests.ps1 b/Tests/New-PfbS3ExportRule.Tests.ps1 index 0a5677e0..9c609b0d 100644 --- a/Tests/New-PfbS3ExportRule.Tests.ps1 +++ b/Tests/New-PfbS3ExportRule.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbSmbClientRule.Tests.ps1 b/Tests/New-PfbSmbClientRule.Tests.ps1 index 26a360c7..ecc33cc3 100644 --- a/Tests/New-PfbSmbClientRule.Tests.ps1 +++ b/Tests/New-PfbSmbClientRule.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbSmbShareRule.Tests.ps1 b/Tests/New-PfbSmbShareRule.Tests.ps1 index 02450bbd..03065047 100644 --- a/Tests/New-PfbSmbShareRule.Tests.ps1 +++ b/Tests/New-PfbSmbShareRule.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbUserGroupQuotaPolicy.Tests.ps1 b/Tests/New-PfbUserGroupQuotaPolicy.Tests.ps1 index 9309bdd6..ce83c9df 100644 --- a/Tests/New-PfbUserGroupQuotaPolicy.Tests.ps1 +++ b/Tests/New-PfbUserGroupQuotaPolicy.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbUserGroupQuotaPolicyFileSystem.Tests.ps1 b/Tests/New-PfbUserGroupQuotaPolicyFileSystem.Tests.ps1 index 73cd2b06..b3741608 100644 --- a/Tests/New-PfbUserGroupQuotaPolicyFileSystem.Tests.ps1 +++ b/Tests/New-PfbUserGroupQuotaPolicyFileSystem.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/New-PfbUserGroupQuotaPolicyRule.Tests.ps1 b/Tests/New-PfbUserGroupQuotaPolicyRule.Tests.ps1 index 51c86685..966ece57 100644 --- a/Tests/New-PfbUserGroupQuotaPolicyRule.Tests.ps1 +++ b/Tests/New-PfbUserGroupQuotaPolicyRule.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/ObjectStoreAccountExport.Tests.ps1 b/Tests/ObjectStoreAccountExport.Tests.ps1 index 195461ab..7e336749 100644 --- a/Tests/ObjectStoreAccountExport.Tests.ps1 +++ b/Tests/ObjectStoreAccountExport.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/PfbApiDriftTools.Tests.ps1 b/Tests/PfbApiDriftTools.Tests.ps1 index 8587ee9f..465aeade 100644 --- a/Tests/PfbApiDriftTools.Tests.ps1 +++ b/Tests/PfbApiDriftTools.Tests.ps1 @@ -1802,7 +1802,7 @@ if ($null -ne $response.items) { $allItems.Add($response.items) } It 'sorts unhandled envelope fields by EndpointCount desc/Field asc with differing counts' { # zulu appears on 2 endpoints, alpha and bravo on 1 each - # Correct sort: zulu (2), alpha (1), bravo (1) — count takes precedence + # Correct sort: zulu (2), alpha (1), bravo (1) -- count takes precedence $map = [PSCustomObject]@{ generatedFrom = @('2.0', '2.1') endpoints = [PSCustomObject]@{ diff --git a/Tests/PfbApprovedVerbSuppressions.Tests.ps1 b/Tests/PfbApprovedVerbSuppressions.Tests.ps1 new file mode 100644 index 00000000..41a21452 --- /dev/null +++ b/Tests/PfbApprovedVerbSuppressions.Tests.ps1 @@ -0,0 +1,202 @@ +#Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } +<# +.SYNOPSIS + Pins the PSUseApprovedVerbs population at exactly three known functions, and pins + the shape of the SuppressMessageAttribute that silences them. +.DESCRIPTION + Three internal helpers in tools/ use the unapproved verb Sort-: + + tools/Build-PfbDeadKeyReport.ps1 Sort-PfbDeadKeyRecords + tools/lib/PfbPipelineSelectorTools.ps1 Sort-PfbSelectorRecord + tools/lib/PfbPipelineSelectorTools.ps1 Sort-PfbSelectorString + + They are suppressed rather than renamed. Nothing exports them -- they appear in + neither the manifest nor the .psm1, and have no reference in Public/ or Private/ + -- while renaming would touch ~27 call sites across five files, two of which + generate committed derived artifacts, so a missed call site would surface later + as artifact churn rather than as a clean failure at rename time. + + WHY THE ASSERTIONS ARE EQUALITIES, IN BOTH DIRECTIONS. A suppression that is + only checked for "no more than N" cannot fail: it accepts a new unapproved verb + as long as it is suppressed too. Checked only for "at least N", it cannot notice + that someone renamed one of the three and left a suppression behind that now + proves nothing. So the count is pinned at exactly 3 and the names are pinned + exactly, and a legitimate change to either is expected to edit this test. + + WHY THE ATTRIBUTE SHAPE IS ASSERTED SEPARATELY. SuppressMessageAttribute has no + one-argument constructor. PSScriptAnalyzer accepts ('PSUseApprovedVerbs') from + the AST and reports the finding as suppressed, but PowerShell throws + `Cannot find an overload for ".ctor" and the argument count: "1"` when it + constructs the attribute. An analyzer run therefore cannot tell the working form + from the broken one: only running it can. Hence the second argument is pinned to + the empty string, and there is a test that actually exercises each form. + + AND IT THROWS ON INVOCATION, NOT ON DEFINITION -- measured here, not assumed. + Dot-sourcing a file containing the one-argument form succeeds silently; the + exception arrives the first time the function is CALLED. So a broken suppression + in tools/ would survive module load, survive any test that only imports the file, + and fail in the middle of a build-tool run. The probes below therefore invoke the + function; a probe that only defined it would pass on both forms and prove + nothing. + + This file deliberately does not require PSScriptAnalyzer. The live count is + gated in CI by the analyze job in .github/workflows/cross-platform-tests.yml; + what is checked here is the population and the attribute shape, from the AST, + on both editions. +#> + +# The three are a fact this test pins, not an input it discovers. It lives in +# BeforeDiscovery because -ForEach is evaluated during Pester's DISCOVERY phase, +# before any BeforeAll has run: defined in BeforeAll it is $null at that point and +# the whole file dies with "Value can not be null or empty array (Parameter +# 'ForEach')" -- a container failure, which reports as 3 passed rather than as the +# 9 tests silently never generated. +BeforeDiscovery { + $script:expectedUnapproved = @( + 'Sort-PfbDeadKeyRecords' + 'Sort-PfbSelectorRecord' + 'Sort-PfbSelectorString' + ) +} + +BeforeAll { + $repoRoot = Split-Path -Parent $PSScriptRoot + + $script:approvedVerbs = @(Get-Verb | ForEach-Object { $_.Verb }) + + # Every function definition in the source tree, with the file it came from. + # scripts/ and tools/ are in scope as well as the shipped folders: a bad verb in + # a build tool is what these three are, so excluding tooling would make the + # population trivially correct. + $script:allFunctions = @( + foreach ($dir in 'Public', 'Private', 'tools', 'scripts') { + $dirPath = Join-Path $repoRoot $dir + if (-not (Test-Path -LiteralPath $dirPath)) { continue } + foreach ($file in Get-ChildItem -LiteralPath $dirPath -Filter '*.ps1' -Recurse -File) { + $ast = [System.Management.Automation.Language.Parser]::ParseFile( + $file.FullName, [ref]$null, [ref]$null) + foreach ($fn in $ast.FindAll( + { $args[0] -is [System.Management.Automation.Language.FunctionDefinitionAst] }, $true)) { + [pscustomobject]@{ + Name = $fn.Name + File = $file.FullName + Ast = $fn + } + } + } + } + ) +} + +Describe 'PSUseApprovedVerbs population' { + + It 'found functions to examine at all' { + # Control. Every assertion below is over $allFunctions, and an empty + # collection satisfies "the unapproved set is exactly these three" only by + # accident of an off-by-everything -- a moved directory or a parse failure + # would otherwise read as a clean pass. + $allFunctions.Count | Should -BeGreaterThan 100 + } + + It 'has exactly the three known unapproved-verb functions, and no others' { + $unapproved = @( + $allFunctions | + Where-Object { $_.Name -like '*-*' } | + Where-Object { ($_.Name -split '-', 2)[0] -notin $approvedVerbs } | + ForEach-Object { $_.Name } | + Sort-Object -Unique + ) + + # Equality, not containment: this fails on a NEW bad verb and on the silent + # disappearance of an old one. + $unapproved | Should -Be ($expectedUnapproved | Sort-Object -Unique) + } + + It 'pins the count at three' { + $expectedUnapproved.Count | Should -Be 3 + } +} + +Describe 'The suppression attribute on each of the three' { + + It 'carries a SuppressMessageAttribute for PSUseApprovedVerbs: <_>' -ForEach $script:expectedUnapproved { + $fn = @($allFunctions | Where-Object Name -EQ $_) + $fn.Count | Should -Be 1 -Because "$_ should be defined exactly once" + + $attrs = @( + $fn[0].Ast.Body.ParamBlock.Attributes | + Where-Object { $_.TypeName.FullName -like '*SuppressMessageAttribute' } + ) + $suppression = @( + $attrs | Where-Object { + $_.PositionalArguments.Count -ge 1 -and + $_.PositionalArguments[0].Value -eq 'PSUseApprovedVerbs' + } + ) + $suppression.Count | Should -Be 1 + } + + It 'passes exactly two positional arguments, the second empty: <_>' -ForEach $script:expectedUnapproved { + $fn = @($allFunctions | Where-Object Name -EQ $_) + $suppression = @( + $fn[0].Ast.Body.ParamBlock.Attributes | + Where-Object { $_.TypeName.FullName -like '*SuppressMessageAttribute' } | + Where-Object { $_.PositionalArguments[0].Value -eq 'PSUseApprovedVerbs' } + )[0] + + # Two, not one. PSScriptAnalyzer reports the one-argument form as suppressed + # because it only ever walks the AST; PowerShell throws when it constructs + # the attribute. See the next Describe. + $suppression.PositionalArguments.Count | Should -Be 2 + $suppression.PositionalArguments[1].Value | Should -Be '' + } + + It 'gives a justification: <_>' -ForEach $script:expectedUnapproved { + $fn = @($allFunctions | Where-Object Name -EQ $_) + $suppression = @( + $fn[0].Ast.Body.ParamBlock.Attributes | + Where-Object { $_.TypeName.FullName -like '*SuppressMessageAttribute' } | + Where-Object { $_.PositionalArguments[0].Value -eq 'PSUseApprovedVerbs' } + )[0] + + $named = @($suppression.NamedArguments | Where-Object ArgumentName -EQ 'Justification') + $named.Count | Should -Be 1 + $named[0].Argument.Value | Should -Not -BeNullOrEmpty + } +} + +Describe 'The attribute form actually constructs' { + # This is the point of the file. An analyzer never constructs the attribute, so + # an analysis-only check cannot distinguish a working suppression from one that + # throws the moment the file is dot-sourced. + + It 'the two-argument form used in tools/ runs' { + . ([scriptblock]::Create(@' +function Sort-PfbAttributeShapeProbe { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseApprovedVerbs', '', + Justification = 'probe')] + [CmdletBinding()] + param() + 'ran' +} +'@)) + { Sort-PfbAttributeShapeProbe } | Should -Not -Throw + Sort-PfbAttributeShapeProbe | Should -Be 'ran' + } + + It 'the one-argument form the analyzer accepts throws when called' { + # Control for the assertion above: if this ever stops throwing, the two-arg + # requirement has become a preference and the comment explaining it is stale. + . ([scriptblock]::Create(@' +function Sort-PfbAttributeShapeProbeBroken { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseApprovedVerbs')] + [CmdletBinding()] + param() + 'ran' +} +'@)) + # Defining it is NOT enough -- that succeeds. The failure is at the call. + { Sort-PfbAttributeShapeProbeBroken } | + Should -Throw -ExpectedMessage '*argument count*' + } +} diff --git a/Tests/PfbBucketPolicySelectors.Tests.ps1 b/Tests/PfbBucketPolicySelectors.Tests.ps1 index 094044ab..14b7e2b2 100644 --- a/Tests/PfbBucketPolicySelectors.Tests.ps1 +++ b/Tests/PfbBucketPolicySelectors.Tests.ps1 @@ -106,8 +106,6 @@ $script:bucketOnlyPostCases = @( ) BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/PfbCmdletParamTools.Tests.ps1 b/Tests/PfbCmdletParamTools.Tests.ps1 index 866f7775..d9f0540a 100644 --- a/Tests/PfbCmdletParamTools.Tests.ps1 +++ b/Tests/PfbCmdletParamTools.Tests.ps1 @@ -1,14 +1,14 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } <# .SYNOPSIS - Unit tests for tools/lib/PfbCmdletParamTools.ps1 — the AST-based cmdlet parameter + Unit tests for tools/lib/PfbCmdletParamTools.ps1 -- the AST-based cmdlet parameter inventory used by tools/Build-PfbFieldCmdletMap.ps1. .DESCRIPTION Runs against a small synthetic Public/-shaped directory under TestDrive, built from real patterns observed in this repo's actual cmdlets (New-PfbAlertWatcher's simple $body['wire_name'] = $Param assignment, New-PfbNetworkInterface's -Attributes escape hatch and its unresolvable $AttachedServers | ForEach-Object {...} pipeline, and - Get-PfbArrayPerformance's $queryParams assignment) — no dependency on the real Public/ + Get-PfbArrayPerformance's $queryParams assignment) -- no dependency on the real Public/ tree so the test stays stable if cmdlets change. #> diff --git a/Tests/PfbDeadSelectorRemoval.Tests.ps1 b/Tests/PfbDeadSelectorRemoval.Tests.ps1 index 7516cf39..05716f7d 100644 --- a/Tests/PfbDeadSelectorRemoval.Tests.ps1 +++ b/Tests/PfbDeadSelectorRemoval.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/PfbHelpCoverage.Tests.ps1 b/Tests/PfbHelpCoverage.Tests.ps1 index 238c44e7..09891239 100644 --- a/Tests/PfbHelpCoverage.Tests.ps1 +++ b/Tests/PfbHelpCoverage.Tests.ps1 @@ -174,7 +174,7 @@ BeforeAll { # harmless. Measured, not assumed -- the two look alike and behave oppositely. # # This is what closes the shapes the position-only version of this lookup failed open on. An - # ordinary `<#…#>` block, or an unknown-keyword one, on the line directly above a help block + # ordinary `<#...#>` block, or an unknown-keyword one, on the line directly above a help block # takes the help block down with it; a stray `.WIBBLE` below one does the same. A blank line # before an offending BLOCK makes them two runs again and the help renders -- but a bad line # INSIDE the block cannot be rescued that way. @@ -264,7 +264,7 @@ BeforeAll { # so there is one rule to encode rather than one per edition. # # The unit is the RUN, defined by Get-PfbCommentRun above, not the block. Modelling position - # alone is precisely what made the previous version fail open: it asked where a `<#…#>` block + # alone is precisely what made the previous version fail open: it asked where a `<#...#>` block # sat and never asked what shared its run. # # REGIONS, searched in this order and moving on whenever a region holds no help run: @@ -1585,7 +1585,7 @@ function Get-PfbFixture { Should -BeNullOrEmpty -Because 'the voided run''s .PARAMETER Other never renders, so crediting it would invent an orphan' # LINE-COMMENT help is real help, both as the thing that renders and as the thing that - # suppresses. The old lookup only ever looked at `<#…#>` tokens, so it skipped this run + # suppresses. The old lookup only ever looked at `<#...#>` tokens, so it skipped this run # entirely and credited the block below -- a block Get-Help never reaches. $records['linecomment-help-claims-run'].HasHelpBlock | Should -BeTrue -Because 'measured: `# .SYNOPSIS` on consecutive lines is comment-based help and Get-Help renders it' diff --git a/Tests/PfbSpecTools.DeclaredQueryKey.Tests.ps1 b/Tests/PfbSpecTools.DeclaredQueryKey.Tests.ps1 index 54e6137c..0fff37d4 100644 --- a/Tests/PfbSpecTools.DeclaredQueryKey.Tests.ps1 +++ b/Tests/PfbSpecTools.DeclaredQueryKey.Tests.ps1 @@ -3,7 +3,7 @@ .SYNOPSIS Unit tests for Get-PfbDeclaredQueryKey (tools/lib/PfbSpecTools.ps1). .DESCRIPTION - Pure-function unit tests against in-memory synthetic spec objects — no network access + Pure-function unit tests against in-memory synthetic spec objects -- no network access and no dependency on the cached specs in tools/specs/, so this file runs with no spec cache present. diff --git a/Tests/PfbSpecTools.Tests.ps1 b/Tests/PfbSpecTools.Tests.ps1 index aafb4100..36458051 100644 --- a/Tests/PfbSpecTools.Tests.ps1 +++ b/Tests/PfbSpecTools.Tests.ps1 @@ -1,12 +1,12 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } <# .SYNOPSIS - Unit tests for tools/lib/PfbSpecTools.ps1 — the shared spec-extraction and + Unit tests for tools/lib/PfbSpecTools.ps1 -- the shared spec-extraction and capability-diffing helpers used by tools/Update-PfbApiSpecs.ps1 and tools/Build-PfbCapabilityMap.ps1. .DESCRIPTION These are pure-function unit tests against a small synthetic fixture - (Tests/Fixtures/sample-redoc-page.html) and inline synthetic spec objects — no + (Tests/Fixtures/sample-redoc-page.html) and inline synthetic spec objects -- no network access and no dependency on the real cached specs in tools/specs/. #> @@ -31,7 +31,7 @@ Describe 'ConvertFrom-PfbRedocHtml' -Skip:($PSVersionTable.PSVersion.Major -lt 7 It 'correctly walks past braces embedded inside string values (does not truncate early)' { # The fixture's description contains a literal "{this}" and the trailing - # options.theme.spacing value contains "({ spacing }) => 10" — both would break + # options.theme.spacing value contains "({ spacing }) => 10" -- both would break # a naive scan for the *first* unmatched-looking '}' instead of a real # string-aware balanced-brace scan. $spec = ConvertFrom-PfbRedocHtml -Html $fixtureHtml @@ -47,7 +47,7 @@ Describe 'ConvertFrom-PfbRedocHtml' -Skip:($PSVersionTable.PSVersion.Major -lt 7 It 'decodes non-ASCII characters correctly' { $spec = ConvertFrom-PfbRedocHtml -Html $fixtureHtml - $spec.info.description | Should -Match 'café' + $spec.info.description | Should -Match "caf$([char]0x00E9)" } It 'throws a clear error when the __redoc_state marker is missing' { diff --git a/Tests/PfbSpecializedSelectorKeys.Tests.ps1 b/Tests/PfbSpecializedSelectorKeys.Tests.ps1 index fda52f3f..96034a43 100644 --- a/Tests/PfbSpecializedSelectorKeys.Tests.ps1 +++ b/Tests/PfbSpecializedSelectorKeys.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/PfbValueEnumTools.Tests.ps1 b/Tests/PfbValueEnumTools.Tests.ps1 index b2666ac7..f8b8b388 100644 --- a/Tests/PfbValueEnumTools.Tests.ps1 +++ b/Tests/PfbValueEnumTools.Tests.ps1 @@ -1,11 +1,11 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } <# .SYNOPSIS - Unit tests for tools/lib/PfbValueEnumTools.ps1 — the prose "Valid/Possible values" + Unit tests for tools/lib/PfbValueEnumTools.ps1 -- the prose "Valid/Possible values" extraction helpers used by tools/Build-PfbValueEnumMap.ps1. .DESCRIPTION Pure-function unit tests against small synthetic spec objects (same - [PSCustomObject]-fixture style as Tests/PfbSpecTools.Tests.ps1) — no network access + [PSCustomObject]-fixture style as Tests/PfbSpecTools.Tests.ps1) -- no network access and no dependency on the real cached specs in tools/specs/. #> @@ -40,7 +40,7 @@ Describe 'Get-PfbValueEnumTriggerSentence' { It 'isolates only the trigger sentence, not trailing prose that repeats the values' { # Regression for the trigger-sentence-scoping rule: the preset export-rule # description explains each backtick-quoted value again in a paragraph *after* - # the enum sentence — the trigger sentence itself must not swallow that tail. + # the enum sentence -- the trigger sentence itself must not swallow that tail. $desc = @' Specifies access control for the export. Valid values are `root-squash`, `all-squash`, and `no-root-squash`. @@ -473,7 +473,7 @@ Describe 'Build-PfbValueEnumMap.ps1: inline-parameter-to-$ref refactor keeps the # Reproduces the real Get-PfbArraySpace `type` history exactly: v1 defines it # inline on GET /arrays/space with a full "Valid values..." description; v2 # refactors the SAME parameter into a components.parameters $ref with - # byte-identical description text — a pure documentation refactor, not an API + # byte-identical description text -- a pure documentation refactor, not an API # change. The field must still be attributed to v1, not v2, once diffed. New-Item -ItemType Directory -Path 'TestDrive:\inlineSpecs' -Force | Out-Null diff --git a/Tests/Remove-PfbApiToken.Tests.ps1 b/Tests/Remove-PfbApiToken.Tests.ps1 index d6db0eea..6ff14565 100644 --- a/Tests/Remove-PfbApiToken.Tests.ps1 +++ b/Tests/Remove-PfbApiToken.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Remove-PfbArrayConnection.Tests.ps1 b/Tests/Remove-PfbArrayConnection.Tests.ps1 index 21b54a19..75df23db 100644 --- a/Tests/Remove-PfbArrayConnection.Tests.ps1 +++ b/Tests/Remove-PfbArrayConnection.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Remove-PfbFileSystemReplicaLink.Tests.ps1 b/Tests/Remove-PfbFileSystemReplicaLink.Tests.ps1 index 0ee653ad..d6e2d86c 100644 --- a/Tests/Remove-PfbFileSystemReplicaLink.Tests.ps1 +++ b/Tests/Remove-PfbFileSystemReplicaLink.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Remove-PfbFileSystemSnapshotTransfer.Tests.ps1 b/Tests/Remove-PfbFileSystemSnapshotTransfer.Tests.ps1 index 4b26335b..1528791e 100644 --- a/Tests/Remove-PfbFileSystemSnapshotTransfer.Tests.ps1 +++ b/Tests/Remove-PfbFileSystemSnapshotTransfer.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Remove-PfbFileSystemUserGroupQuotaPolicy.Tests.ps1 b/Tests/Remove-PfbFileSystemUserGroupQuotaPolicy.Tests.ps1 index a9d31898..bde35259 100644 --- a/Tests/Remove-PfbFileSystemUserGroupQuotaPolicy.Tests.ps1 +++ b/Tests/Remove-PfbFileSystemUserGroupQuotaPolicy.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Remove-PfbPolicyFileSystem.Tests.ps1 b/Tests/Remove-PfbPolicyFileSystem.Tests.ps1 index 92e68835..72c50ea1 100644 --- a/Tests/Remove-PfbPolicyFileSystem.Tests.ps1 +++ b/Tests/Remove-PfbPolicyFileSystem.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Remove-PfbUserGroupQuotaPolicy.Tests.ps1 b/Tests/Remove-PfbUserGroupQuotaPolicy.Tests.ps1 index 472c1fe6..c6f7ad25 100644 --- a/Tests/Remove-PfbUserGroupQuotaPolicy.Tests.ps1 +++ b/Tests/Remove-PfbUserGroupQuotaPolicy.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Remove-PfbUserGroupQuotaPolicyFileSystem.Tests.ps1 b/Tests/Remove-PfbUserGroupQuotaPolicyFileSystem.Tests.ps1 index 6f96c05f..90801ec2 100644 --- a/Tests/Remove-PfbUserGroupQuotaPolicyFileSystem.Tests.ps1 +++ b/Tests/Remove-PfbUserGroupQuotaPolicyFileSystem.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Remove-PfbUserGroupQuotaPolicyRule.Tests.ps1 b/Tests/Remove-PfbUserGroupQuotaPolicyRule.Tests.ps1 index 01854e51..5d177338 100644 --- a/Tests/Remove-PfbUserGroupQuotaPolicyRule.Tests.ps1 +++ b/Tests/Remove-PfbUserGroupQuotaPolicyRule.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Resolve-PfbParameterComponent.Tests.ps1 b/Tests/Resolve-PfbParameterComponent.Tests.ps1 index 8de7ee49..b76e7b7f 100644 --- a/Tests/Resolve-PfbParameterComponent.Tests.ps1 +++ b/Tests/Resolve-PfbParameterComponent.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule } diff --git a/Tests/Set-PfbPresetWorkload.Tests.ps1 b/Tests/Set-PfbPresetWorkload.Tests.ps1 index 75c68273..ad063286 100644 --- a/Tests/Set-PfbPresetWorkload.Tests.ps1 +++ b/Tests/Set-PfbPresetWorkload.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Set-PfbTlsProtocol.Tests.ps1 b/Tests/Set-PfbTlsProtocol.Tests.ps1 index f5093991..03e74085 100644 --- a/Tests/Set-PfbTlsProtocol.Tests.ps1 +++ b/Tests/Set-PfbTlsProtocol.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule } diff --git a/Tests/Set-PfbWorkloadTag.Tests.ps1 b/Tests/Set-PfbWorkloadTag.Tests.ps1 index f7387f27..1069d896 100644 --- a/Tests/Set-PfbWorkloadTag.Tests.ps1 +++ b/Tests/Set-PfbWorkloadTag.Tests.ps1 @@ -9,8 +9,6 @@ #> BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Test-PfbSyslogServer.Tests.ps1 b/Tests/Test-PfbSyslogServer.Tests.ps1 index 43b4f0f8..09036d09 100644 --- a/Tests/Test-PfbSyslogServer.Tests.ps1 +++ b/Tests/Test-PfbSyslogServer.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/TotalOnlyCapability.Tests.ps1 b/Tests/TotalOnlyCapability.Tests.ps1 index 3594c6fe..f437144c 100644 --- a/Tests/TotalOnlyCapability.Tests.ps1 +++ b/Tests/TotalOnlyCapability.Tests.ps1 @@ -42,7 +42,6 @@ $supportedTotalOnlyCmdlets = @( BeforeAll { $repoRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $repoRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbActiveDirectory.Tests.ps1 b/Tests/Update-PfbActiveDirectory.Tests.ps1 index 51d1f356..fe75f5a4 100644 --- a/Tests/Update-PfbActiveDirectory.Tests.ps1 +++ b/Tests/Update-PfbActiveDirectory.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbAdmin.Tests.ps1 b/Tests/Update-PfbAdmin.Tests.ps1 index 463ddeaf..e0fdcbbb 100644 --- a/Tests/Update-PfbAdmin.Tests.ps1 +++ b/Tests/Update-PfbAdmin.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbApiClient.Tests.ps1 b/Tests/Update-PfbApiClient.Tests.ps1 index ecc9aecb..44f5245d 100644 --- a/Tests/Update-PfbApiClient.Tests.ps1 +++ b/Tests/Update-PfbApiClient.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbArrayConnection.Tests.ps1 b/Tests/Update-PfbArrayConnection.Tests.ps1 index 9ad7b323..2b0204f4 100644 --- a/Tests/Update-PfbArrayConnection.Tests.ps1 +++ b/Tests/Update-PfbArrayConnection.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbAsyncLog.Tests.ps1 b/Tests/Update-PfbAsyncLog.Tests.ps1 index 9ba2a510..91a81470 100644 --- a/Tests/Update-PfbAsyncLog.Tests.ps1 +++ b/Tests/Update-PfbAsyncLog.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbBucketAuditFilter.Tests.ps1 b/Tests/Update-PfbBucketAuditFilter.Tests.ps1 index 86e4a01e..26b9075a 100644 --- a/Tests/Update-PfbBucketAuditFilter.Tests.ps1 +++ b/Tests/Update-PfbBucketAuditFilter.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbCertificate.Tests.ps1 b/Tests/Update-PfbCertificate.Tests.ps1 index b1311421..43da33e5 100644 --- a/Tests/Update-PfbCertificate.Tests.ps1 +++ b/Tests/Update-PfbCertificate.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbDirectoryServiceRole.Tests.ps1 b/Tests/Update-PfbDirectoryServiceRole.Tests.ps1 index 6b289c49..ff19b3f9 100644 --- a/Tests/Update-PfbDirectoryServiceRole.Tests.ps1 +++ b/Tests/Update-PfbDirectoryServiceRole.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbDns.Tests.ps1 b/Tests/Update-PfbDns.Tests.ps1 index fe230768..1ede1447 100644 --- a/Tests/Update-PfbDns.Tests.ps1 +++ b/Tests/Update-PfbDns.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbEmptyPipelineGuards.Tests.ps1 b/Tests/Update-PfbEmptyPipelineGuards.Tests.ps1 index 075f8758..dfbc68ba 100644 --- a/Tests/Update-PfbEmptyPipelineGuards.Tests.ps1 +++ b/Tests/Update-PfbEmptyPipelineGuards.Tests.ps1 @@ -282,7 +282,7 @@ Describe 'Update-PfbEmptyPipelineGuards - fixture shapes' { $lines = @(Get-NormalFixtureLines -FunctionName 'Get-PfbRemoteArray') $requestIndex = [array]::IndexOf($lines, ($lines | Where-Object { $_ -like '*Invoke-PfbApiRequest*' } | Select-Object -First 1)) $withGuard = @($lines[0..($requestIndex - 1)]) + @(' ' + $script:guard) + @($lines[$requestIndex..($lines.Count - 1)]) - $file = New-GuardFixture -Root $root -Name 'Get-PfbRemoteArray' -Lines $withGuard + $null = New-GuardFixture -Root $root -Name 'Get-PfbRemoteArray' -Lines $withGuard $summary = & $script:generator -PublicRoot $root -Confirm:$false diff --git a/Tests/Update-PfbFileSystem.Demote.Tests.ps1 b/Tests/Update-PfbFileSystem.Demote.Tests.ps1 index 4aca45ba..1c1f4102 100644 --- a/Tests/Update-PfbFileSystem.Demote.Tests.ps1 +++ b/Tests/Update-PfbFileSystem.Demote.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbFileSystemExport.Tests.ps1 b/Tests/Update-PfbFileSystemExport.Tests.ps1 index edd25a70..89761093 100644 --- a/Tests/Update-PfbFileSystemExport.Tests.ps1 +++ b/Tests/Update-PfbFileSystemExport.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbFleet.Tests.ps1 b/Tests/Update-PfbFleet.Tests.ps1 index 137a315b..c970df51 100644 --- a/Tests/Update-PfbFleet.Tests.ps1 +++ b/Tests/Update-PfbFleet.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbHardware.Tests.ps1 b/Tests/Update-PfbHardware.Tests.ps1 index b5f49fef..7fc23ae7 100644 --- a/Tests/Update-PfbHardware.Tests.ps1 +++ b/Tests/Update-PfbHardware.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbHardwareConnector.Tests.ps1 b/Tests/Update-PfbHardwareConnector.Tests.ps1 index 15529cb1..44cd2a30 100644 --- a/Tests/Update-PfbHardwareConnector.Tests.ps1 +++ b/Tests/Update-PfbHardwareConnector.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbKmip.Tests.ps1 b/Tests/Update-PfbKmip.Tests.ps1 index 98539f7f..e661f730 100644 --- a/Tests/Update-PfbKmip.Tests.ps1 +++ b/Tests/Update-PfbKmip.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbLag.Tests.ps1 b/Tests/Update-PfbLag.Tests.ps1 index 196929d6..1c65d70a 100644 --- a/Tests/Update-PfbLag.Tests.ps1 +++ b/Tests/Update-PfbLag.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbLegalHold.Tests.ps1 b/Tests/Update-PfbLegalHold.Tests.ps1 index 2733ee9c..96618e19 100644 --- a/Tests/Update-PfbLegalHold.Tests.ps1 +++ b/Tests/Update-PfbLegalHold.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbLegalHoldEntity.Tests.ps1 b/Tests/Update-PfbLegalHoldEntity.Tests.ps1 index f112e838..2f018df6 100644 --- a/Tests/Update-PfbLegalHoldEntity.Tests.ps1 +++ b/Tests/Update-PfbLegalHoldEntity.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbLifecycleRule.Tests.ps1 b/Tests/Update-PfbLifecycleRule.Tests.ps1 index b0155a5d..16e8deac 100644 --- a/Tests/Update-PfbLifecycleRule.Tests.ps1 +++ b/Tests/Update-PfbLifecycleRule.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbLogTargetFileSystem.Tests.ps1 b/Tests/Update-PfbLogTargetFileSystem.Tests.ps1 index 0079bcf0..fc332036 100644 --- a/Tests/Update-PfbLogTargetFileSystem.Tests.ps1 +++ b/Tests/Update-PfbLogTargetFileSystem.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbLogTargetObjectStore.Tests.ps1 b/Tests/Update-PfbLogTargetObjectStore.Tests.ps1 index 21b9ca2c..481a9595 100644 --- a/Tests/Update-PfbLogTargetObjectStore.Tests.ps1 +++ b/Tests/Update-PfbLogTargetObjectStore.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbManagementAccessPolicy.Tests.ps1 b/Tests/Update-PfbManagementAccessPolicy.Tests.ps1 index 6c5871f3..bf86b2db 100644 --- a/Tests/Update-PfbManagementAccessPolicy.Tests.ps1 +++ b/Tests/Update-PfbManagementAccessPolicy.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbNetworkInterface.Tests.ps1 b/Tests/Update-PfbNetworkInterface.Tests.ps1 index affcb722..88f7cd66 100644 --- a/Tests/Update-PfbNetworkInterface.Tests.ps1 +++ b/Tests/Update-PfbNetworkInterface.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbNetworkInterfaceConnector.Tests.ps1 b/Tests/Update-PfbNetworkInterfaceConnector.Tests.ps1 index 38d2053c..666c2862 100644 --- a/Tests/Update-PfbNetworkInterfaceConnector.Tests.ps1 +++ b/Tests/Update-PfbNetworkInterfaceConnector.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbNode.Tests.ps1 b/Tests/Update-PfbNode.Tests.ps1 index 9de2dc0a..34016486 100644 --- a/Tests/Update-PfbNode.Tests.ps1 +++ b/Tests/Update-PfbNode.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbNodeGroup.Tests.ps1 b/Tests/Update-PfbNodeGroup.Tests.ps1 index caea568f..ce5a2953 100644 --- a/Tests/Update-PfbNodeGroup.Tests.ps1 +++ b/Tests/Update-PfbNodeGroup.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbObjectStoreAccountExport.Tests.ps1 b/Tests/Update-PfbObjectStoreAccountExport.Tests.ps1 index 0d940545..dc45b8a2 100644 --- a/Tests/Update-PfbObjectStoreAccountExport.Tests.ps1 +++ b/Tests/Update-PfbObjectStoreAccountExport.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbObjectStoreRemoteCredential.Tests.ps1 b/Tests/Update-PfbObjectStoreRemoteCredential.Tests.ps1 index 25a1c575..796652b0 100644 --- a/Tests/Update-PfbObjectStoreRemoteCredential.Tests.ps1 +++ b/Tests/Update-PfbObjectStoreRemoteCredential.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbObjectStoreRole.Tests.ps1 b/Tests/Update-PfbObjectStoreRole.Tests.ps1 index 32df17ba..6fc85fcc 100644 --- a/Tests/Update-PfbObjectStoreRole.Tests.ps1 +++ b/Tests/Update-PfbObjectStoreRole.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbObjectStoreVirtualHost.Tests.ps1 b/Tests/Update-PfbObjectStoreVirtualHost.Tests.ps1 index ed4f4a23..2ceac2ef 100644 --- a/Tests/Update-PfbObjectStoreVirtualHost.Tests.ps1 +++ b/Tests/Update-PfbObjectStoreVirtualHost.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbOidcIdp.Tests.ps1 b/Tests/Update-PfbOidcIdp.Tests.ps1 index 83a809e5..713687fc 100644 --- a/Tests/Update-PfbOidcIdp.Tests.ps1 +++ b/Tests/Update-PfbOidcIdp.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbQosPolicy.Tests.ps1 b/Tests/Update-PfbQosPolicy.Tests.ps1 index 89bbe5f4..204c6350 100644 --- a/Tests/Update-PfbQosPolicy.Tests.ps1 +++ b/Tests/Update-PfbQosPolicy.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbRealmDefaults.Tests.ps1 b/Tests/Update-PfbRealmDefaults.Tests.ps1 index ec45274b..38ce33c5 100644 --- a/Tests/Update-PfbRealmDefaults.Tests.ps1 +++ b/Tests/Update-PfbRealmDefaults.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbSaml2Idp.Tests.ps1 b/Tests/Update-PfbSaml2Idp.Tests.ps1 index 80f370ee..07682286 100644 --- a/Tests/Update-PfbSaml2Idp.Tests.ps1 +++ b/Tests/Update-PfbSaml2Idp.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbSmtpServer.Tests.ps1 b/Tests/Update-PfbSmtpServer.Tests.ps1 index d5982770..e19fcde6 100644 --- a/Tests/Update-PfbSmtpServer.Tests.ps1 +++ b/Tests/Update-PfbSmtpServer.Tests.ps1 @@ -6,8 +6,6 @@ #> BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbSnmpManager.Tests.ps1 b/Tests/Update-PfbSnmpManager.Tests.ps1 index ed1a15cc..84a3b3ee 100644 --- a/Tests/Update-PfbSnmpManager.Tests.ps1 +++ b/Tests/Update-PfbSnmpManager.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbSshCaPolicy.Tests.ps1 b/Tests/Update-PfbSshCaPolicy.Tests.ps1 index 21bb8a66..7bbcf27b 100644 --- a/Tests/Update-PfbSshCaPolicy.Tests.ps1 +++ b/Tests/Update-PfbSshCaPolicy.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbStorageClassTieringPolicy.Tests.ps1 b/Tests/Update-PfbStorageClassTieringPolicy.Tests.ps1 index 50308de7..5cff5dab 100644 --- a/Tests/Update-PfbStorageClassTieringPolicy.Tests.ps1 +++ b/Tests/Update-PfbStorageClassTieringPolicy.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbSubnet.Tests.ps1 b/Tests/Update-PfbSubnet.Tests.ps1 index ce00a229..46b2156a 100644 --- a/Tests/Update-PfbSubnet.Tests.ps1 +++ b/Tests/Update-PfbSubnet.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbSyslogServer.Tests.ps1 b/Tests/Update-PfbSyslogServer.Tests.ps1 index 9212fcda..57a759ea 100644 --- a/Tests/Update-PfbSyslogServer.Tests.ps1 +++ b/Tests/Update-PfbSyslogServer.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbTarget.Tests.ps1 b/Tests/Update-PfbTarget.Tests.ps1 index 79d45848..608c0268 100644 --- a/Tests/Update-PfbTarget.Tests.ps1 +++ b/Tests/Update-PfbTarget.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbTlsPolicy.Tests.ps1 b/Tests/Update-PfbTlsPolicy.Tests.ps1 index ede04963..ec49ed69 100644 --- a/Tests/Update-PfbTlsPolicy.Tests.ps1 +++ b/Tests/Update-PfbTlsPolicy.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbUserGroupQuotaPolicy.Tests.ps1 b/Tests/Update-PfbUserGroupQuotaPolicy.Tests.ps1 index 615e9a19..c0284f53 100644 --- a/Tests/Update-PfbUserGroupQuotaPolicy.Tests.ps1 +++ b/Tests/Update-PfbUserGroupQuotaPolicy.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbUserGroupQuotaPolicyRule.Tests.ps1 b/Tests/Update-PfbUserGroupQuotaPolicyRule.Tests.ps1 index 3f11cdc3..2e83d29e 100644 --- a/Tests/Update-PfbUserGroupQuotaPolicyRule.Tests.ps1 +++ b/Tests/Update-PfbUserGroupQuotaPolicyRule.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/Tests/Update-PfbWormPolicy.Tests.ps1 b/Tests/Update-PfbWormPolicy.Tests.ps1 index 72adf29e..9763ebda 100644 --- a/Tests/Update-PfbWormPolicy.Tests.ps1 +++ b/Tests/Update-PfbWormPolicy.Tests.ps1 @@ -1,8 +1,6 @@ #Requires -Modules @{ ModuleName = 'Pester'; ModuleVersion = '5.0' } BeforeAll { - $moduleRoot = Split-Path -Parent $PSScriptRoot - $manifest = Join-Path $moduleRoot 'PureStorageFlashBladePowerShell.psd1' . (Join-Path $PSScriptRoot 'PfbTestModule.ps1') $null = Import-PfbTestModule diff --git a/docs/script-analysis.md b/docs/script-analysis.md new file mode 100644 index 00000000..8284fc31 --- /dev/null +++ b/docs/script-analysis.md @@ -0,0 +1,240 @@ +# Static analysis (PSScriptAnalyzer) + +How PSScriptAnalyzer is configured in this repo, what CI enforces, and — more +importantly — what it deliberately does *not* enforce and why. If you have hit a red +`analyze` job, the rule that failed is gated on purpose and the reason is below. + +Two files carry the policy: + +| File | Holds | +|---|---| +| `PSScriptAnalyzerSettings.psd1` | the rule allowlist, and the per-rule rationale as comments | +| `.github/workflows/cross-platform-tests.yml` (`analyze` job) | what actually blocks a PR | + +Per-rule reasoning lives beside the rule in the `.psd1`, not here, so it cannot drift +away from the thing it explains. This document covers the architecture: the shape of +the configuration and the decisions that are not attached to any single rule. + +## An allowlist, never exclusions + +`PSScriptAnalyzerSettings.psd1` names the rules that run (`IncludeRules`) and never +uses `ExcludeRules`. + +That is not a style preference. The two settings are asymmetric: + +- A caller's `-IncludeRule` is **unioned** with the settings file's `IncludeRules`. + Both sets run. +- `ExcludeRules` **vetoes** a caller's `-IncludeRule` outright. A rule excluded in the + settings file cannot be re-enabled from the command line. + +So an exclusion-based configuration silently breaks ad-hoc checks: someone +investigating a specific rule gets a clean result and concludes the code is fine. An +allowlist has the opposite failure mode — it can only under-report, and it never lies +about a rule you explicitly asked for. + +The consequence to know about, because it bites: **the union means a scoped check gets +the whole allowlist too.** A step that runs `-IncludeRule PSProvideCommentHelp` over +`Public/` also runs every allowlisted rule over `Public/`. Every gate in the `analyze` +job therefore filters its results by `RuleName` before counting. That filtering is +load-bearing, not tidiness — without it a gate expecting 0 sees 22 unrelated +records and fails for the wrong reason. + +## CI, not a git hook + +The analyzer's value here is repo-wide and low-frequency. A per-edit hook only ever +sees the file just written, so it would rescan single files and never observe the other +800-odd. Whole-repo coverage against one held baseline is the useful thing, and that is +a CI job. + +There is a separate `PostToolUse` parse-check hook in the agent tooling; it does a +different job (syntax, per edit) and is not part of this regime. + +## The gate is specific rules, not a severity + +The obvious gate — fail if any `Error` appears — is **vacuous under this allowlist**. +The `Error` count is already zero, so such a gate would pass from day one and could +never catch anything. Severity is a property of the rule, not a measure of whether the +repo regressed. + +Instead the job gates a small set of named rules that measure exactly zero, and +requires them to stay there: + +| Guard | Scope | Note | +|---|---|---| +| `PSUseCompatibleSyntax` | all | targets 5.1 and 7.0 | +| `PSUseBOMForUnicodeEncodedFile` | all | the mojibake defect; see below | +| `PSAvoidAssignmentToAutomaticVariable` | all | | +| `PSUseApprovedVerbs` | all | the three `Sort-*` helpers are suppressed at the site, not excluded | +| `PSUseDeclaredVarsMoreThanAssignments` | all | gateable only because the 127 dead `$manifest` assignments were deleted first | +| `PSUseCompatibleCommands` | `Public/` only | see "Scoped, not repo-wide" | +| `PSProvideCommentHelp` | `Public/` only | needs `ExportedOnly = $false` to evaluate anything here | + +Pre-existing warnings from the PSGallery preset rules are **reported but +non-blocking**. Nothing gates the warning count, so it can grow. That is a deliberate +choice to keep the gate meaningful rather than to freeze a number nobody has agreed +to; do not read a green build as evidence the warning count is holding. + +### Every gate carries a control + +A rule reporting zero because it is *inert* is indistinguishable from a rule reporting +zero because the code is clean. Each scoped gate therefore runs the same rule against +a directory where the finding count is known to be non-zero, in the same job, and +fails if that control comes back empty. + +This is not hypothetical caution. Two rules in this configuration were originally +adopted on a zero that turned out to be vacuous: one because the sweep never reached +the files the rule applies to, one because the measurement was scoped to a directory +that happens to be clean. The controls exist because both mistakes were made. + +## Two traps that make a sweep silently measure nothing + +Both were found in this repo's own tooling. If you write a new analyzer invocation, +these are the two ways it will appear to work while checking nothing. + +**1. `-Settings` must be passed explicitly.** Implicit discovery of +`PSScriptAnalyzerSettings.psd1` only looks in the immediate directory of `-Path`. A +sweep that loops over `Public/`, `Private/`, `Tests/`, `tools/`, `scripts/` never sees +a root-level settings file — no warning, no error, the file simply has no effect. + +**2. The repo root must be scanned, as an explicit file list.** +`PureStorageFlashBladePowerShell.psd1` and `.psm1` live at the root, so a +five-directory loop never analyses them. That silently disables every manifest and +module rule, including `PSMissingModuleManifestField` — the one rule here that bears +directly on publication. Pass the root files individually rather than the root +directory, or add the root non-recursively: a recursive root scan re-analyses all five +directories and doubles every count. + +A third, if you use `-EnableExit`: the exit code is the *count* of records, and it +truncates mod 256. Pair it with a rule or severity filter, or a sweep finding 276 +issues exits 20 -- a number small enough to look like a real count. (276 is this +repo's own figure from before the dead-variable cleanup, not a hypothetical.) + +## Rules deliberately not enabled + +### Scoped, not repo-wide: `PSUseCompatibleCommands` + +Configured, but gated on `Public/` only. Repo-wide it reports **21,889** findings, of +which `Tests/` accounts for 21,870 — the rule compares against profiles of *built-in* +commands, so it reports every Pester assertion (`The parameter 'Throw' is not +available for command 'Should'`). `Private/`'s handful are `ConvertFrom-Json -Depth` +calls inside a `$PSVersionTable.PSVersion.Major -ge 6` guard. + +That last point generalises: **the compatibility rules cannot see guards.** Neither +`$PSVersionTable` branching nor `#Requires` is honoured, so correctly fenced +version-specific code is reported as incompatible. `PSUseCompatibleTypes` is excluded +for exactly this reason — its findings are all false positives, and adopting it would +penalise the fencing that supporting both 5.1 and 7 requires. + +### The default-disabled rules stay off + +PSScriptAnalyzer ships ten rules disabled by default. None is in the PSGallery list. +Force-enabling all ten across the five source directories produces **13,826** findings +(**9,001** excluding `PSUseConstrainedLanguageMode`). They are recorded with counts in +`PSScriptAnalyzerSettings.psd1` so their absence is not mistaken for an oversight. + +Their zero in a default run means *never evaluated*, not *clean*. One is worth reading +twice: `PSUseConstrainedLanguageMode` at 4,825 is the largest single rule group +anywhere in this codebase, and it is not a formatting rule — it checks whether code +would run under PowerShell's Constrained Language Mode, which is irrelevant unless the +module is expected to work under an application-allowlisting policy such as +WDAC/AppLocker. Nothing here claims that. + +If formatting enforcement is ever wanted, it should be an `Invoke-Formatter` run on a +deliberate commit, not a gate that reports thousands of findings against code nobody +is about to reformat. + +### `PSUseSingularNouns` is kept, and it is noisy + +It stays in the allowlist because it is part of the PSGallery preset, and dropping it +would make a file that claims to target that preset diverge from it. The cost is +accepted signal-to-noise on every run. The findings split into internal helpers and +exported cmdlets; renaming the internal ones would clear the rule but is a separate +sweep with call-site churn and is not planned. + +## Adding a suppression + +Suppress at the narrowest scope that works, with a `Justification`, and **always pass +two arguments**: + +```powershell +[Diagnostics.CodeAnalysis.SuppressMessageAttribute( + 'PSAvoidUsingConvertToSecureStringWithPlainText', '', + Justification = 'Test fixture credential built from a literal; no other idiom exists.')] +param() +``` + +The empty second argument is load-bearing. `SuppressMessageAttribute` has **no +one-argument constructor**. PSScriptAnalyzer walks the AST and never constructs the +attribute, so the one-argument form suppresses cleanly in analysis — and then throws +`Cannot find an overload for ".ctor" and the argument count: "1"` the moment the file +is executed. An analyzer check is not sufficient evidence that a suppression is +correct; the file has to load. + +Two more things, if you are suppressing in a `Tests/` file: + +- A file-scope `param()` block in a Pester file can change discovery. Confirm the file + still discovers and runs the same number of tests, not merely that Pester exits + zero — `Invoke-Pester` reporting `total=0` is a pass-shaped result, because zero + discovered means zero failed. +- Prefer a suppression at the site over an `ExcludeRules` entry. See the top of this + document for why exclusions are worse than they look. + +## Re-measuring + +Deliberately no counts are quoted here except where the *magnitude* is the decision +(the 13,826 and the 21,889 above). Baselines move with every cleanup commit, and a +document asserting last month's totals is worse than one asserting none. + +Even those two moved within a day of first being written down — 20,966 to 21,889 and +13,188 to 13,826 — which is why `PSScriptAnalyzerSettings.psd1` no longer carries any +count as a literal. Its generator measures each one at generation time and stamps the +file with the date and commit it measured against. Treat the figures in this document +the same way: they are the magnitude behind a decision, not a baseline to hold. + +To re-measure, run the analyzer with the settings file passed explicitly and the root +included: + +```powershell +$repo = +$paths = 'Public','Private','Tests','tools','scripts' | ForEach-Object { Join-Path $repo $_ } +$paths += Get-ChildItem -LiteralPath $repo -File | + Where-Object Extension -in '.ps1','.psm1','.psd1' | ForEach-Object FullName + +$all = foreach ($p in $paths) { + Invoke-ScriptAnalyzer -Path $p -Recurse:(Test-Path -PathType Container $p) ` + -Settings (Join-Path $repo 'PSScriptAnalyzerSettings.psd1') +} +$all | Group-Object RuleName | Sort-Object Count -Descending | Format-Table Count, Name +``` + +`build/` is gitignored generated output and stays out of the sweep. + +Before believing any zero from a run of your own, prove the analyzer is live in that +session — analyse a snippet with a known defect and confirm it reports: + +```powershell +Invoke-ScriptAnalyzer -ScriptDefinition 'function Test-Probe { $x = 1 }' ` + -IncludeRule PSUseDeclaredVarsMoreThanAssignments -WhatIf:$false +``` + +`-WhatIf:$false` is not decoration. `Invoke-ScriptAnalyzer` declares +`SupportsShouldProcess`, so a `$WhatIfPreference` set by a *calling* script propagates +into it: it analyses nothing and returns an empty result with no error. Reading is not +a side effect, and a read must never be suppressed by `-WhatIf`. + +## Why `PSUseDeclaredVarsMoreThanAssignments` is a gate at all + +It is worth recording, because the rule spent a long time reporting 127 findings and +being useless. All 127 were the same dead `$manifest` / `$moduleRoot` boilerplate in +`Tests/`, left behind deliberately by `tools/Update-PfbTestModuleImport.ps1`. While +they stood, a genuinely dead variable in a *new* test file arrived as finding 128 of +127 known ones and was invisible, and no gate could be written at any threshold. + +Deleting them is what converted the rule from noise into a signal, which is the +argument for having done it. Note also that this is the rule the job's liveness probe +uses, so its own guard is the one that cannot pass vacuously. + +Two of the 127 needed hands rather than the script, and both are the interesting kind +of exception: one file assigns `$moduleRoot` twice, only one of which is dead; the +other's right-hand side is a call that creates the fixture the test depends on, so the +assignment went and the call stayed. diff --git a/tools/Build-PfbCapabilityMap.ps1 b/tools/Build-PfbCapabilityMap.ps1 index a3f05366..ad75971c 100644 --- a/tools/Build-PfbCapabilityMap.ps1 +++ b/tools/Build-PfbCapabilityMap.ps1 @@ -5,18 +5,18 @@ .DESCRIPTION Loads every cached tools/specs/fb.json in ascending version order and records, for each (HTTP method, normalized path), the earliest version it appears - in — and likewise for each parameter name and request-body top-level property name + in -- and likewise for each parameter name and request-body top-level property name on that endpoint. This is the data Phase 2's per-cmdlet capability check and Phase 3's version-aware ArgumentCompleters will consume. Deliberately NOT included: per-enum-value "introduced in version X" tracking. The FlashBlade OpenAPI spec has no structural JSON Schema `enum` anywhere (verified - against fb2.10 and fb2.27) — allowed values are documented only in free-text + against fb2.10 and fb2.27) -- allowed values are documented only in free-text `description` prose, which is not reliably machine-diffable. See tools/lib/PfbSpecTools.ps1 for the full finding. Also NOT included (deferred, see plan): endpoint/field deprecation or removal - tracking, and hardware-model (//S vs //E) capability — that is a separate axis from + tracking, and hardware-model (//S vs //E) capability -- that is a separate axis from REST version and is handled in a later phase from a different data source. Each endpoint also carries, where non-empty, readOnlyBodyProperties and diff --git a/tools/Build-PfbDeadKeyReport.ps1 b/tools/Build-PfbDeadKeyReport.ps1 index cf56b11e..ea70d30e 100644 --- a/tools/Build-PfbDeadKeyReport.ps1 +++ b/tools/Build-PfbDeadKeyReport.ps1 @@ -82,6 +82,8 @@ $inventory = @(Get-PfbCmdletParameterInventory -PublicDirectory $PublicDirectory # wrong row in a committed artifact rather than a byte-order flap. The dedup at the # declaredElsewhere projection is the fix for that case; its reasoning is recorded beside it. function Sort-PfbDeadKeyRecords { + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseApprovedVerbs', '', + Justification = 'Internal build-tooling helper in tools/; not exported by the module manifest, so no published surface carries the unapproved verb.')] param( [AllowEmptyCollection()] [object[]]$Records, diff --git a/tools/Build-PfbValueEnumMap.ps1 b/tools/Build-PfbValueEnumMap.ps1 index bcbc5e1d..d0cafa85 100644 --- a/tools/Build-PfbValueEnumMap.ps1 +++ b/tools/Build-PfbValueEnumMap.ps1 @@ -10,13 +10,13 @@ to attribute each entry its earliest-seen ("introduced in") version. The current legal value set recorded for each entry reflects the newest processed version. - This is data-extraction and validation only — it does NOT wire up ArgumentCompleters + This is data-extraction and validation only -- it does NOT wire up ArgumentCompleters and does NOT change Assert-PfbApiCapability enforcement. See Value-Enum-Extraction-Work.md for the full design rationale and non-goals. Also writes a reconciliation report (Reports/PfbValueEnumReconciliation.md) comparing this newly extracted data against every existing hand-written `ValidateSet` in - Public/ that encodes a spec-documented value enum. Report only — no Public/ cmdlet + Public/ that encodes a spec-documented value enum. Report only -- no Public/ cmdlet is edited by this script. .PARAMETER SpecsDirectory Where cached spec JSON files live. Defaults to tools/specs relative to this script. @@ -79,20 +79,20 @@ $specFiles = $specFiles | ForEach-Object { # One record per (SchemaName.PropertyName) or parameter key, tracking the earliest # version it was ever seen in (MinVersion) and the most recently processed version's -# record (LastRecord) — the latter supplies the "current legal value set" / current +# record (LastRecord) -- the latter supplies the "current legal value set" / current # parsed-vs-unparsed status, since values and prose can change release to release. # # $seen is deliberately case-INSENSITIVE (PowerShell's [ordered]@{} default) rather than # a stricter Ordinal comparer. Confirmed live: the real spec renames a schema's casing -# between versions (e.g. "SNMPAgent" in early REST versions to "SnmpAgent" by fb2.27) — +# between versions (e.g. "SNMPAgent" in early REST versions to "SnmpAgent" by fb2.27) -- # NOT a squash-mode-style same-name-different-meaning collision, just a vendor casing # convention change over time for the *same* logical schema. A case-sensitive dictionary # would keep both as separate entries, which in turn produces a manifest JSON with two -# top-level keys differing only by case — and PowerShell's ConvertFrom-Json (producing a +# top-level keys differing only by case -- and PowerShell's ConvertFrom-Json (producing a # PSCustomObject, the idiom used everywhere else in this repo, including every consumer # of this file) hard-errors on that ("Cannot convert the JSON string because it contains # keys with different casing"). So each case-insensitive-equivalent group collapses to -# one entry, but — unlike a real squash-mode merge — nothing about its VALUES gets +# one entry, but -- unlike a real squash-mode merge -- nothing about its VALUES gets # blended: .Key is re-recorded on every sighting so the final output uses whichever # version's casing was seen LAST (i.e. matches the newest/current spec), while # MinVersion still reflects the earliest sighting under any casing. @@ -172,13 +172,13 @@ Write-Host "Wrote $($entries.Count) entries ($($unparsed.Count) unparsed) from $ # Every ValidateSet found (as of this writing) whose values encode a spec-documented # value enum, excluding Invoke-PfbApiRequest.ps1's HTTP-verb ValidateSet (not spec data). # "Name" here is the field's wire name (request-body key or query-parameter name), which -# is what Get-PfbSpecValueEnums records as each entry's .name — see its header comment +# is what Get-PfbSpecValueEnums records as each entry's .name -- see its header comment # for why that differs from a parameter's components.parameters dictionary key. # "ResourceHint" is a prefix filter on the schema half of an entry's Key (e.g. # 'NetworkInterface' matches 'NetworkInterface.services' and 'NetworkInterfacePatch.services' # but not an unrelated schema that happens to share the property name 'services'). This is -# NOT a real field->cmdlet/endpoint mapping (explicitly out of scope for this phase — see -# Value-Enum-Extraction-Work.md) — it is a best-effort disambiguation to avoid a false +# NOT a real field->cmdlet/endpoint mapping (explicitly out of scope for this phase -- see +# Value-Enum-Extraction-Work.md) -- it is a best-effort disambiguation to avoid a false # "stale"/"exact-match" claim built on an unrelated schema's same-named field. A field name # common enough to appear on many resources (protocol, type) can still legitimately collide # even after hint-filtering; that is reported as 'collision', not force-resolved. @@ -188,7 +188,7 @@ $handWritten = @( [PSCustomObject]@{ File = 'Public/Bucket/New-PfbBucket.ps1'; Line = 29; Parameter = '-Versioning'; Name = 'versioning'; ResourceHint = 'Bucket'; Values = @('enabled', 'suspended', 'none') } [PSCustomObject]@{ File = 'Public/Bucket/Update-PfbBucket.ps1'; Line = 31; Parameter = '-Versioning'; Name = 'versioning'; ResourceHint = 'Bucket'; Values = @('enabled', 'suspended', 'none') } # '_multiProtocol' is the actual nested body-object schema name for this field (confirmed - # by direct spec inspection) — a literal alias, not a fuzzy resource-name guess. + # by direct spec inspection) -- a literal alias, not a fuzzy resource-name guess. [PSCustomObject]@{ File = 'Public/FileSystem/New-PfbFileSystem.ps1'; Line = 179; Parameter = '-MultiProtocolAccessControlStyle'; Name = 'access_control_style'; ResourceHint = @('FileSystem', '_multiProtocol'); Values = @('nfs', 'smb', 'shared', 'independent', 'mode-bits') } [PSCustomObject]@{ File = 'Public/FileSystem/New-PfbFileSystem.ps1'; Line = 192; Parameter = '-GroupOwnership'; Name = 'group_ownership'; ResourceHint = 'FileSystem'; Values = @('creator', 'parent-directory') } [PSCustomObject]@{ File = 'Public/FileSystem/Update-PfbFileSystem.ps1'; Line = 97; Parameter = '-RequestedPromotionState'; Name = 'requested_promotion_state'; ResourceHint = 'FileSystem'; Values = @('promoted', 'demoted') } @@ -211,7 +211,7 @@ $reconciliation = foreach ($hw in $handWritten) { # Strict prefix (not substring-contains): "NetworkInterface*" must correctly exclude # the unrelated "_networkInterfaceNeighbor*" private schemas (a real collision found - # live) — those start with an underscore, so a plain prefix check already excludes + # live) -- those start with an underscore, so a plain prefix check already excludes # them without needing a word-boundary check. Known private nested-object schemas # that don't share the resource's own name prefix are listed as explicit extra hints # above (e.g. '_multiProtocol'), not matched via a @@ -236,7 +236,7 @@ $reconciliation = foreach ($hw in $handWritten) { } elseif ($candidates.Count -eq 0) { # The field name exists elsewhere in the spec, just not under this cmdlet's own - # resource — do not claim exact-match/stale against an unrelated schema. + # resource -- do not claim exact-match/stale against an unrelated schema. $status = 'not-found-in-resource' $note = "field '$($hw.Name)' not found under any of [$($hints -join ', ')]-hinted schemas; found elsewhere: $($allMatches.Key -join '; ')" } @@ -280,7 +280,7 @@ $mdLines.Add('# Value-Enum Reconciliation Report') $mdLines.Add('') $mdLines.Add("Generated by ``tools/Build-PfbValueEnumMap.ps1`` against ``Reports/PfbValueEnumMap.json`` ($($processedVersions.Count) REST versions, $($entries.Count) entries).") $mdLines.Add('') -$mdLines.Add('Compares every hand-written `ValidateSet` in `Public/` that encodes a spec-documented value enum against the newly extracted prose data. Report only — no `Public/` cmdlet is edited by this script. See `Value-Enum-Extraction-Work.md` for the full non-goal list.') +$mdLines.Add('Compares every hand-written `ValidateSet` in `Public/` that encodes a spec-documented value enum against the newly extracted prose data. Report only -- no `Public/` cmdlet is edited by this script. See `Value-Enum-Extraction-Work.md` for the full non-goal list.') $mdLines.Add('') $mdLines.Add('| File:Line | Parameter | Hand-written values | Spec values | Status | Note |') $mdLines.Add('|---|---|---|---|---|---|') diff --git a/tools/Update-PfbApiSpecs.ps1 b/tools/Update-PfbApiSpecs.ps1 index b65a49cc..90f3b7df 100644 --- a/tools/Update-PfbApiSpecs.ps1 +++ b/tools/Update-PfbApiSpecs.ps1 @@ -79,7 +79,7 @@ foreach ($version in $targetVersions) { $spec = ConvertFrom-PfbRedocHtml -Html $page.Content if (-not $spec.openapi) { - throw "Extracted document has no 'openapi' field — extraction likely failed silently." + throw "Extracted document has no 'openapi' field -- extraction likely failed silently." } # Re-serialize pretty-printed for easier local diffing/inspection of the cache. diff --git a/tools/Update-PfbTestModuleImport.ps1 b/tools/Update-PfbTestModuleImport.ps1 index 722fd872..3343129b 100644 --- a/tools/Update-PfbTestModuleImport.ps1 +++ b/tools/Update-PfbTestModuleImport.ps1 @@ -11,10 +11,24 @@ tree (Tests/Update-PfbTestModuleImport.Tests.ps1). Only the import STATEMENT is replaced, in place, at its own indentation. Surrounding - $moduleRoot / $manifest assignments are left alone: several files go on to use them - (Tests/RemovedCmdlets.Tests.ps1 asserts against $manifest; + $moduleRoot / $manifest assignments are left alone by THIS tool: several files go on to + use them (Tests/RemovedCmdlets.Tests.ps1 asserts against $manifest; Tests/ArrayConnection.ShouldProcessTarget.Tests.ps1 passes it to Get-PfbTargetRecorder). - Deleting them would be a much larger, riskier diff for no gain. + + HISTORICAL NOTE, kept because it was acted on. This paragraph used to end "deleting them + would be a much larger, riskier diff for no gain", and the dead assignments it left + behind have since been removed -- deliberately, not in ignorance of that sentence. The + "no gain" half expired when the analyzer became a project: while 127 known-dead + assignments stood, PSUseDeclaredVarsMoreThanAssignments reported nothing but them, so a + genuinely dead variable in a NEW test file was invisible and CI could never gate on the + rule. The "riskier" half shrank once the risk was measured rather than assumed: the + deletion was driven off the analyzer's own file list and the AST, never a regex or a + line number, and the three files that defeat three different mechanical strategies + (above, plus Tests/Update-PfbTestModuleImport.Tests.ps1, whose $manifest occurrences are + all backtick-escaped fixture text) were excluded by the analyzer itself. + + So do not re-close that task on this paragraph's authority. If a future bulk change + wants those assignments back, the premise, not the conclusion, is what to re-check. WHAT GETS REPLACED IS AN AST NODE, NOT A LINE. If the import is the right-hand side of a plain assignment, the enclosing AssignmentStatementAst is the replaced node and the diff --git a/tools/lib/PfbPipelineSelectorTools.ps1 b/tools/lib/PfbPipelineSelectorTools.ps1 index 0233bd08..37e90d76 100644 --- a/tools/lib/PfbPipelineSelectorTools.ps1 +++ b/tools/lib/PfbPipelineSelectorTools.ps1 @@ -35,6 +35,8 @@ function Sort-PfbSelectorRecord { The input records, ordered. #> [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseApprovedVerbs', '', + Justification = 'Internal build-tooling helper in tools/; not exported by the module manifest, so no published surface carries the unapproved verb.')] param( [Parameter(Mandatory)][AllowEmptyCollection()][object[]]$Record, [Parameter(Mandatory)][string[]]$Property @@ -81,6 +83,8 @@ function Sort-PfbSelectorString { [string[]] #> [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseApprovedVerbs', '', + Justification = 'Internal build-tooling helper in tools/; not exported by the module manifest, so no published surface carries the unapproved verb.')] param( [Parameter(Mandatory)][AllowEmptyCollection()][AllowNull()][string[]]$Value, [switch]$Unique diff --git a/tools/lib/PfbSpecTools.ps1 b/tools/lib/PfbSpecTools.ps1 index 787ac1f3..61d7fc33 100644 --- a/tools/lib/PfbSpecTools.ps1 +++ b/tools/lib/PfbSpecTools.ps1 @@ -15,19 +15,19 @@ Redoc.hydrate(__redoc_state, container); - There is no standalone .json/.yaml URL — the page's "Download" button serializes this + There is no standalone .json/.yaml URL -- the page's "Download" button serializes this in-memory object to a client-side blob: URL, which cannot be fetched directly. These helpers extract the embedded object server-side instead. Confirmed (2025-07-08, specs fb2.10 and fb2.27): - The object is a single valid JSON value (ConvertFrom-Json handles it directly). - Paths for versioned resource endpoints are prefixed with the REST version itself, - e.g. "/api/2.27/arrays" vs "/api/2.10/arrays" — must be normalized before + e.g. "/api/2.27/arrays" vs "/api/2.10/arrays" -- must be normalized before comparing the same logical endpoint across versions. A handful of auth/meta endpoints (/api/login, /api/api_version, /api/logout, /api/login-banner, /oauth2/1.0/token) are NOT version-prefixed and are left as-is. - Path items include a vendor extension key "x-pure-authorization-resource" - alongside real HTTP-method keys — must filter to actual HTTP verbs. + alongside real HTTP-method keys -- must filter to actual HTTP verbs. - Parameters and request bodies are almost always $ref'd into components.parameters / components.schemas rather than inlined. - The spec contains NO structural JSON Schema "enum" anywhere (verified: zero @@ -36,7 +36,7 @@ free-text `description` prose ("Valid values are `none`, `enabled`, ..."). This means per-enum-value "introduced in version X" tracking is NOT derivable from structured data, and is intentionally out of scope for the generated capability - map — only endpoint, parameter, and request-body top-level property existence are + map -- only endpoint, parameter, and request-body top-level property existence are tracked. #> @@ -171,7 +171,7 @@ function Resolve-PfbRef { $refPath = $current.'$ref' if ($refPath -notlike '#/*') { - # External ref — not supported, return as-is rather than guess. + # External ref -- not supported, return as-is rather than guess. break } @@ -882,8 +882,8 @@ function Get-PfbSwaggerIndexVersions { [string]$IndexHtml ) - $matches = [regex]::Matches($IndexHtml, 'redoc/fb(\d+\.\d+)-api-reference\.html') - $versions = $matches | ForEach-Object { $_.Groups[1].Value } | Select-Object -Unique + $versionMatches = [regex]::Matches($IndexHtml, 'redoc/fb(\d+\.\d+)-api-reference\.html') + $versions = $versionMatches | ForEach-Object { $_.Groups[1].Value } | Select-Object -Unique return $versions | ForEach-Object { $parts = $_ -split '\.' diff --git a/tools/lib/PfbValueEnumTools.ps1 b/tools/lib/PfbValueEnumTools.ps1 index a7ef64fc..5c0af242 100644 --- a/tools/lib/PfbValueEnumTools.ps1 +++ b/tools/lib/PfbValueEnumTools.ps1 @@ -12,10 +12,10 @@ parses that prose instead. Two correctness rules discovered while building this against the real cached specs - (fb2.27.json), each with its own regression test — do not regress either: + (fb2.27.json), each with its own regression test -- do not regress either: 1. MANY schemas (e.g. Bucket, NfsExportPolicyRuleBase) are `allOf` compositions with - no direct `.properties` of their own — the real property and its `description` + no direct `.properties` of their own -- the real property and its `description` live behind `allOf` branches and $ref's. Reading `.description` directly off such a schema's own property node returns nothing; the walker below resolves $ref and recurses into `allOf`, exactly like Get-PfbSchemaPropertyNames in PfbSpecTools.ps1. @@ -64,7 +64,7 @@ referenced dictionary; reprocessing them here would double-count. #> -# Deliberately NOT Set-StrictMode — same reasoning as PfbSpecTools.ps1: these functions +# Deliberately NOT Set-StrictMode -- same reasoning as PfbSpecTools.ps1: these functions # walk heterogeneous PSCustomObjects from JSON where a given node legitimately may or # may not have a given property (not every schema has .properties or .allOf). @@ -101,7 +101,7 @@ function ConvertFrom-PfbValueEnumProse { enumerated values, if it is actually an enumeration. .DESCRIPTION Tries, in order: backtick-quoted values (the dominant pattern), then - double-quoted values, then bare comma-separated tokens — only for a trigger + double-quoted values, then bare comma-separated tokens -- only for a trigger sentence that didn't already parse via an earlier pattern. Sentences that match the trigger phrase but are not really an enumeration (e.g. a numeric range, or free-text prose that happens to contain the trigger words) are explicitly @@ -148,7 +148,7 @@ function ConvertFrom-PfbValueEnumProse { # "Valid values include QSFP, QSFP+, QSFP28, QSFP56, QSFP-DD, RJ-45, and -." # Deliberately conservative: only fires when the sentence has no quote characters or # backticks at all (so it can't misfire on the malformed-quote case, e.g. "include - # 'success' or failure'." — a real, confirmed-malformed example in the source spec that + # 'success' or failure'." -- a real, confirmed-malformed example in the source spec that # is left unparsed rather than force-parsed -- nor on a malformed *backtick* case, e.g. # policy_type's missing-backtick `smb-client` bug: without this exclusion, a sentence # that fails the backtick-parity guard above would fall through here and this @@ -157,7 +157,7 @@ function ConvertFrom-PfbValueEnumProse { # looks like a short comma/space-separated token list (no long runs of lowercase prose # words). if ($TriggerSentence -notmatch '[''"``]') { - # [\s\S] (not '.') so the lazy capture can span an embedded newline — real spec + # [\s\S] (not '.') so the lazy capture can span an embedded newline -- real spec # prose wraps mid-sentence (e.g. "...`all-squash`, and\n`no-root-squash`.") and # '.' does not match '\n' by default, which would otherwise force the match to # anchor past the embedded newline onto a later, spurious "are"/"include". @@ -166,7 +166,7 @@ function ConvertFrom-PfbValueEnumProse { $rawTokens = $tail.Groups[1].Value -replace '\band\b', ',' -split ',' $tokens = $rawTokens | ForEach-Object { $_.Trim() } | Where-Object { $_ } # Reject if any token contains whitespace (a real value token here, e.g. - # "QSFP28" or "-", never does) — that indicates free-text prose rather than + # "QSFP28" or "-", never does) -- that indicates free-text prose rather than # a token list, e.g. "controllers and blades from hardware list". $looksLikeTokenList = $tokens.Count -gt 0 -and -not ($tokens | Where-Object { $_ -match '\s' }) if ($looksLikeTokenList) { @@ -182,7 +182,7 @@ function Get-PfbSchemaPropertyDescriptions { <# .SYNOPSIS Returns resolved { propertyName -> description } pairs for a (possibly $ref'd / - allOf'd) schema — the description-carrying counterpart to + allOf'd) schema -- the description-carrying counterpart to Get-PfbSchemaPropertyNames in PfbSpecTools.ps1. .DESCRIPTION Resolves $ref chains and merges across "allOf" branches, same pattern as @@ -261,7 +261,7 @@ function Get-PfbSpecValueEnums { OpenAPI spec, across components.schemas properties, components.parameters, and inline (non-$ref) parameters defined directly on a spec.paths operation. .DESCRIPTION - Never collapses by bare property/parameter name — each record's Key is + Never collapses by bare property/parameter name -- each record's Key is "." for schema properties (Kind = 'schema'), the parameter's own component name (Kind = 'parameter'), or " #" for a parameter defined inline on a path operation @@ -271,7 +271,7 @@ function Get-PfbSpecValueEnums { inline-define a same-named parameter with a different value set. Every description that matches the trigger phrase produces a record, whether or - not it successfully parsed into values — callers must check .Parsed rather than + not it successfully parsed into values -- callers must check .Parsed rather than assume every returned record has a usable value list. This is deliberate: it is the mechanism by which "unparsed" prose is surfaced rather than silently dropped. .OUTPUTS @@ -279,14 +279,14 @@ function Get-PfbSpecValueEnums { Key is the collision-safe identity ("SchemaName.PropertyName", the parameter's own components.parameters dictionary key, or " #" for an - inline-parameter record) — always unique, always what downstream diffing/storage + inline-parameter record) -- always unique, always what downstream diffing/storage should key on. Name is the field's own short name as it actually appears on the wire (the schema property name, or the parameter's "name" field, e.g. - "protocol") — the more useful match target for reconciling against a cmdlet's + "protocol") -- the more useful match target for reconciling against a cmdlet's hand-written parameter, since a query parameter's components.parameters dictionary key does not have to equal its wire "name". For inline-parameter records, Key already ends in "#", so Name is always redundant with the - tail of Key by construction — kept as its own field anyway, for the same + tail of Key by construction -- kept as its own field anyway, for the same uniform-shape reason 'schema'/'parameter' records carry it. #> [CmdletBinding()] @@ -346,7 +346,7 @@ function Get-PfbSpecValueEnums { # Strip the version prefix every real path carries (e.g. # "/api/2.27/arrays/space") down to the version-stable form # ("arrays/space") that also matches the literal -Endpoint string every - # cmdlet passes to Invoke-PfbApiRequest (see PfbCmdletParamTools.ps1) — the + # cmdlet passes to Invoke-PfbApiRequest (see PfbCmdletParamTools.ps1) -- the # same normalized path MUST produce the same Key across every spec version # or the introduced-in-version diffing in Build-PfbValueEnumMap.ps1 would # never recognize the field as the same one release to release. A handful @@ -362,7 +362,7 @@ function Get-PfbSpecValueEnums { foreach ($paramNode in $operation.parameters) { # A bare $ref pointer, e.g. { "$ref": "#/components/parameters/Type" } - # — already covered by the components.parameters pass above. + # -- already covered by the components.parameters pass above. # Reprocessing it here would double-count the same definition under # two different Keys and inflate entryCount without adding real # coverage.