fix: prepare for gophercloud 2.15.0 — json.Number rendering and clouds.yaml domains - #30
Merged
Merged
Conversation
gophercloud v2.15.0 decodes JSON numbers into `any` with UseNumber(), so every number koc reads out of a map[string]any is a json.Number rather than a float64. Three type switches only knew the float64 spelling: - powerStateLabel fell through to its default and printed nova's raw OS-EXT-STS:power_state, so `server show` showed "1" where it used to show "Running"; - numericValue returned not-a-number, so a column carrying one sorted as text and put "10" before "9" (json.Number is a named string type, so the existing string case does not match it either); - scalarString fell through to json.Marshal, which happens to be right for a well-formed number but relies on the default branch by accident. Teach all three the json.Number spelling. The change is inert against the currently vendored v2.14.0 -- nothing produces a json.Number there -- and is what keeps `server show` correct once the bump lands, so it goes in ahead of it rather than with it. Tests pin the handling directly rather than through the SDK, so they hold whichever decoder the vendored version uses, plus one end-to-end guard that decodes a real response body and fails if a future bump changes the number kind again. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EkWzWSEyrjJ1gd1v5zJNtE
Keystone qualifies two different things by domain: the user being authenticated, and the project being scoped to. gophercloud v2.14.0 and earlier folded them together in clouds.Parse -- AuthOptions.DomainName fell back through user_domain_name, project_domain_name, domain_name, and Scope was left nil for gophercloud to derive from TenantName and that one domain. v2.15.0 splits them: DomainName no longer falls back to project_domain_name, and Parse returns an explicit Scope carrying the project's domain. A clouds.yaml that names only one of the pair loses the other half. Driven against the real v2.15.0 clouds.Parse, a file with project_domain_name and no user_domain_name yields an empty user domain, which Keystone rejects as an ambiguous password grant; the mirror case leaves the project-by-name scope unqualified. Single-domain clouds write one of the two and mean it for both, so each half now falls back to the other -- what v2.14.0 did and what upstream OSC does. koc's own flags are unaffected either way: applyDomainScope runs after this and overwrites both halves, and it is only reached when a domain flag or OS_*_DOMAIN_* variable is actually set, which is why the clouds.yaml path was exposed at all. A system- or trust-scoped token is not domain-qualified and is left exactly as gophercloud built it. Inert against the vendored v2.14.0, which returns a nil Scope here, so it lands ahead of the bump rather than with it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EkWzWSEyrjJ1gd1v5zJNtE
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.
Prerequisite for #28. That bump (gophercloud 2.14.0 → 2.15.0) fails
go test ./...on master today, and carries a second, silent auth regression that no test covers. Both fixes are inert against the vendored 2.14.0, so they land ahead of the bump and keep master green through the sequence.1.
json.Numberrendering and sorting (9eb36b6)2.15.0 added
UseNumber()to three decode paths (provider_client.go,results.go,pagination/http.go) so integers too large forfloat64survive a round-trip. The side effect: every number koc reads out of amap[string]anyis now ajson.Number, not afloat64. Three type switches only knew thefloat64spelling:powerStateLabeldefault→server showprints1instead ofRunningnumericValue10before9scalarStringjson.Marshal, right only by accidentjson.Numberis a named string type, so the existingcase string:does not catch it either — the miss is silent in all three. Caught byTestRunServerShow_TableHumanized; the sorting and scalar paths had no coverage for it at all.2. clouds.yaml domain coalescing (
b27bdce)2.15.0 also rewrote
config/cloudsscope resolution, which koc uses for--os-cloud. Keystone qualifies two different things by domain — the user being authenticated and the project being scoped to. 2.14.0 folded them together:DomainNamefell back throughuser_domain_name→project_domain_name→domain_name, andScopewas left nil for gophercloud to derive. 2.15.0 splits them and returns an explicitScope.A clouds.yaml naming only one of the pair loses the other half. Driven against the real 2.15.0
clouds.Parsewith a file carryingproject_domain_nameand nouser_domain_name:An empty user domain makes Keystone reject the password grant as ambiguous. The mirror case — only
user_domain_name— leaves the project-by-name scope unqualified. Single-domain clouds write one of the two and mean it for both, soreconcileCloudDomainslets each half fall back to the other: what 2.14.0 did, and what upstream OSC does.This was reachable only through clouds.yaml: koc's
applyDomainScoperuns afterwards and overwrites both halves, but is entered only when a domain flag orOS_*_DOMAIN_*variable is actually set. System- and trust-scoped tokens are not domain-qualified and are left exactly as gophercloud built them.Tests
Written against the shapes
clouds.Parseand the SDK decoder return, not against the SDK itself, so they hold whichever version is vendored:TestPowerStateLabel_NumberKinds—json.Number,float64,intall humanize; unmapped code and non-integer pass through.TestScalarString_JSONNumber— renders the literal sent, agrees with thefloat64path.TestCompareCells_NumericAndString— fivejson.Numbercases, mixed againstfloat64andint.TestRunServerShow_PowerStateFromDecodedBody— end-to-end guard on a real decoded body, so a future bump that changes the number kind again fails here rather than in production output.TestReconcileCloudDomains(+_IDs,_SystemAndTrustUntouched,_FlagsStillWin) — both one-sided clouds.yaml shapes, both-named, project-by-ID, the 2.14.0 nil-scope case, and that an explicit koc flag still wins.Verification
Full suite green both ways: on this branch with 2.14.0 vendored, and on a local merge of #28 with 2.15.0 vendored — where together they are what turns the suite from failing to green.
gofmt,go vet ./...and the offline static build are clean.🤖 Generated with Claude Code
https://claude.ai/code/session_01EkWzWSEyrjJ1gd1v5zJNtE