feat(fleet): add -FleetKey to New-PfbFleetMember with self-identification - #147
Merged
juemerson-at-purestorage merged 3 commits intoAug 26, 2026
Conversation
…tion
Joining a fleet needed the caller to hand-build the request body and to know
the joining array's own id:
New-PfbFleetMember -FleetName f -Members @{ key = $k; member = @{ id = $selfId } }
Both halves are recoverable from context. The key comes from New-PfbFleetKey,
and POST /fleets/members must be called from the array that is joining, so
that array is by definition the one the connection already points at. -FleetKey
takes the key and resolves the id with Get-PfbArray over the same connection.
-Members stays as the passthrough for what the convenience path cannot express
-- several members in one call, or a member other than the array being talked
to. The two are separate parameter sets so the engine rejects supplying both,
rather than one silently winning.
-FleetId is untouched and is not made redundant by this. The spec has
fleet_ids and fleet_names as the query-parameter selector and the key as a body
field: the selector says which fleet, the key authorises the join. A test pins
that the two compose.
The wire shape is unchanged -- a test asserts the -FleetKey body is byte-equal
to the equivalent explicit -Members body -- so this is an ergonomics layer over
the contract fixed in dmann000#38, not a change to it.
Get-PfbArray is called before ShouldProcess, so it runs under -WhatIf too. It
is a read, and without it there is no body to describe. If it yields no id the
cmdlet throws rather than POSTing a member reference with an empty id.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
-FleetKey is a typed parameter whose wire name cannot be resolved by the field/cmdlet mapper, because it lands in the request body nested under members[].key rather than as a parameter the spec names directly. So it joins the "typed but unresolved wire name" list, 51 to 52, and the dead-key report's parametersInventoried rises 2167 to 2168 with the same +1 under its "wire name unresolved" skip reason. No dead key appears or disappears. Regenerated through scripts/Assert-PfbDerivedArtifacts.ps1 -UpdateCommitted so the output is the one the CI gate compares against, then normalised to LF -- the generators emit CRLF on Windows and the committed reports are LF-only. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
The dead-key gate ceilings each skip reason, because a key the generator cannot evaluate hides a dead key just as effectively as one it evaluates and passes. -FleetKey pushes 'wire name unresolved' from 126 to 127 and reds it. This is the same case the existing 126 was set for, and the comment there already names the test: the parameter is NEW, so nothing that was evaluable stopped being evaluated, and it was never evaluable as a query key in the first place -- its value goes into the request body at members[].key, which the AST resolver does not follow into. Neither condition is a coverage regression, which is what the ceiling exists to catch. The route to the wire is evidenced rather than assumed: POST /fleets/members returns 200 naming the member the key was sent for, on all three lab arrays. The comment now states both conditions a future raise has to meet, so the next person hitting this red has to establish them rather than bumping the number to clear it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this adds
New-PfbFleetMembergains a-FleetKeyparameter, so joining a fleet no longer requires the caller to hand-build the request body and to already know the joining array's own id.Before:
After:
Both halves were recoverable from context. The key comes straight from
New-PfbFleetKey, andPOST /fleets/membersmust be called from the array that is joining — so that array is by definition the one the connection already points at.-FleetKeytakes the key and resolves the id withGet-PfbArrayover the same connection.-Membersstays exactly as it was, as the passthrough for what the convenience path cannot express: several members in one call, or a member other than the array being talked to. The two are separate parameter sets, so the engine rejects supplying both rather than one silently winning.The wire shape is unchanged. This is an ergonomics layer over the contract fixed in #38, not a change to it. A test asserts the
-FleetKeybody is byte-identical to the equivalent explicit-Membersbody, and the live probe below confirms it against real arrays.-FleetIdis not made redundant by thisWorth stating, because the two look interchangeable and are not. Per the spec for
POST /fleets/members,fleet_ids/fleet_namesare query parameters and the key is a body field insidemembers[]: the selector says which fleet, the key authorises the join. The key names no fleet, so a selector is still needed. A test pins-FleetIdand-FleetKeycomposing.One defect deliberately not carried over
An earlier unmerged attempt at this built its
ShouldProcesstarget as"${($self.name)}:${FleetName}", which renders:fleet-prodrather thanfb-a:fleet-prod—${...}delimits a variable name in PowerShell, not a subexpression. This uses$($self.name)and the live-WhatIfoutput below confirms it renders.Behaviour notes
Get-PfbArrayis called beforeShouldProcess, so it runs under-WhatIftoo. It is a read, and without it there is no body to describe. Documented on the parameter.Verification
Scoped Pester, both editions, all green.
New-PfbFleetMember(20 tests), plus the help- and ShouldProcess-coverage sweeps, the drift-confidence tests, the committed-report guards and theBuild-*artifact gates — 93 passed / 0 failed on the artifact leg, 34 passed / 0 failed on the Windows PowerShell 5.1 leg. The full suite is CI's job.Live-verified against three lab FlashBlade arrays (Purity//FB 4.8.2, REST 2.26) forming a fleet — the coordinator and both non-coordinator members. Code under test
feat/fleetmember-fleetkey@2709150, connected as a directory account:-FleetKey, real key, correct fleet-Members, same key and same self id-FleetKey, nonexistent fleet nameFleet name does not match the provided fleet key.The first two rows returning identical responses is the claim: the convenience path is not a different request. Each array's response echoed its own id with
is_local: true, soGet-PfbArrayself-identification resolved correctly per array rather than happening to work once. The third row is the control — a specific and different error rules out "the endpoint rejects everything" and shows both the key and the fleet selector were parsed and compared.-WhatIfrendered each array's own name, e.g.What if: Performing the operation "Add fleet member" on target "<array> into <fleet>".Honest limit: no array joined a fleet it was absent from. All three were already members, and evicting one would have destroyed a standing lab fixture. A 200 from an already-joined array proves the request body is well-formed and the key validates against the fleet; it is not evidence that enrollment of a new member works. That remains untested on the wire, as it was before this change.
Incidentally measured and worth knowing for anyone testing this family: fleet writes reject a local static array account with
HTTP 400 "Operation not permitted."— on the coordinator and on a member alike, with no fleet context involved.POST /fleets/fleet-keyandPOST /fleets/membersboth need a directory account.Derived artifacts
Reports/PfbDeadKeyReport.json,Reports/PfbFieldCmdletMap.jsonandReports/PfbFieldCmdletMapping.mdare regenerated.-FleetKeyis a typed parameter whose wire name the field mapper cannot resolve, because its value lands nested atmembers[].keyrather than as a parameter the spec names directly — so it joins the "typed but unresolved wire name" list (51 → 52), with the matching +1 in the dead-key report'sparametersInventoriedand itswire name unresolvedskip reason. No dead key appears or disappears.That +1 also raises the ceiling
Tests/CommittedDeadKeyReport.Tests.ps1puts on that skip reason, 126 → 127. The existing 126 was set for the same case and its comment already names the test a raise has to pass: the parameter is new, so nothing that was evaluable stopped being evaluated, and it was never evaluable as a query key in the first place. Neither is the coverage regression the ceiling exists to catch, and the route to the wire is evidenced by the live probe rather than assumed. The comment now spells out both conditions, so the next person to hit this red has to establish them rather than bump the number.Not included
No version bump and no
CHANGELOG.mdentry — the maintainer's separate decision.