Skip to content

feat(compute): close the flavor flag gaps against upstream OSC - #26

Merged
ftarasenko merged 1 commit into
masterfrom
claude/nice-bardeen-57s738
Sep 16, 2026
Merged

ftarasenko merged 1 commit into
masterfrom
claude/nice-bardeen-57s738

Conversation

@ftarasenko

Copy link
Copy Markdown
Owner

Diffed koc flavor … flag-for-flag against python-openstackclient 10.3.0 (openstackclient/compute/v2/flavor.py, PyPI sdist).

flavor set and flavor unset already matched upstream exactly — including the absence of --private. Nova's PUT /flavors/{id} accepts only description (2.55+); is_public is fixed at creation and there is no API call that flips a flavor's visibility, so upstream has no such flag either. The gaps were all in create, list and show.

flavor create

Adds --property, --project / --project-domain and --description.

Nova cannot set extra specs or an access list in the create request, so both follow the POST as they do upstream — but a failure there is returned rather than logged, since the flavor exists and is not the one that was asked for, and an exit code is the only way a script sees that.

Three defects fixed along the way:

  • --id auto was sent verbatim. The flag help already documented it as "nova assigns a UUID", but the value went straight into the request body, so it would have created a flavor whose ID is the literal string auto. Now translated to an omitted field, matching the novaclient alias upstream still honours.
  • --project without --private is now rejected before the POST, instead of creating the flavor and then failing the grant — which left half the command applied.
  • --public / --private are now mutually exclusive, as upstream's argparse group is.

flavor list

Adds --private, --min-disk, --min-ram, --marker and --limit.

--private is a distinct is_public=false view, not a synonym for the default (which is public plus the caller's own). The three access views are mutually exclusive. --limit is a hard result cap collected through internal/cli/paging because nova treats it only as a page size.

flavor show

Adds Access Project IDs. The projects that may boot a private flavor are the whole point of one and live on a separate endpoint. A public flavor has no access list — nova 404s there — so the lookup is skipped and the field renders empty, keeping the field set stable for -c.

--rxtx-factor upper bound

Nova removed the field at 2.102, so the flag is now refused with the reason rather than letting nova 400 — but only under an explicit microversion pin. latest is resolved server-side, and koc supports clouds back to Zed where it means 2.93; reading it as "the newest microversion that exists" would refuse the flag on every cloud in the supported range that still accepts it.

That asymmetry against the existing --description lower-bound check is deliberate, and why the two now sit in separate helpers (computeSupportsMicroversion vs computePinnedAtOrAbove) with the reasoning recorded on both.

Deviation kept

koc flavor set --description "" clears the description via the raw PUT with an explicit null; upstream's if parsed_args.description: makes an empty value a silent no-op. koc's behaviour is the useful one and was already documented in the code.

Notes

docs/coverage.md is unchanged — no command was added, renamed or removed, and it tracks the command surface rather than flags.

Testing

go vet, gofmt, go test ./..., go test -race and the offline static build (-mod=vendor GOPROXY=off CGO_ENABLED=0) all pass. gofmt was checked with Go 1.27's, per AGENTS.md.

11 new tests cover the new request shapes and both microversion guards, including the negative case that --rxtx-factor still reaches nova under latest.

The built binary was also exercised end-to-end against a mock nova/keystone: every new flag, both microversion guards, and both pre-flight rejections.

golangci-lint could not be run locally — the version installed in this environment is v2.5.0 built with go1.25 and refuses the repo's go1.26 target — so CI's pinned build is the first real lint pass.

🤖 Generated with Claude Code

https://claude.ai/code/session_01HZKL3mxxCBQkj6zxDrFXhD


Generated by Claude Code

Diffed `koc flavor …` flag-for-flag against python-openstackclient 10.3.0's
openstackclient/compute/v2/flavor.py. `flavor set` and `flavor unset` already
match upstream exactly; the gaps were all in create, list and show.

flavor create gains --property, --project/--project-domain and --description.
Nova cannot set extra specs or an access list in the create request, so both
follow the POST as they do upstream — but a failure there is returned rather
than logged, since the flavor exists and is not the one that was asked for.
--project without --private is rejected before the POST instead of leaving a
created flavor behind a failed grant, and --public/--private are now mutually
exclusive.

--id auto was documented as "nova assigns a UUID" and sent verbatim, which
would have created a flavor whose ID is the literal string "auto"; it is now
translated to an omitted field, matching the novaclient alias upstream still
honours.

flavor list gains --private (a distinct is_public=false view, not a synonym for
the default), --min-disk, --min-ram, --marker and --limit. The three access
views are mutually exclusive, and --limit is a hard result cap collected
through internal/cli/paging because nova treats it only as a page size.

flavor show now renders Access Project IDs. The projects that may boot a
private flavor are the whole point of one and live on a separate endpoint; a
public flavor has no access list (nova 404s there), so the lookup is skipped
and the field stays empty, keeping the field set stable for -c.

--rxtx-factor is refused above the microversion that removed the field, but
only under an explicit pin. "latest" is resolved by nova, and koc supports
clouds back to Zed where it means 2.93 — reading it as "the newest
microversion that exists" would refuse the flag on every cloud in the
supported range that still accepts it. That asymmetry against the existing
lower-bound check is why the two now sit in separate helpers.

No command was added, renamed or removed, so docs/coverage.md is unchanged.
Exercised end-to-end against a mock nova/keystone: every new flag, both
microversion guards and both pre-flight rejections.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01HZKL3mxxCBQkj6zxDrFXhD
@ftarasenko
ftarasenko merged commit 758dab4 into master Sep 16, 2026
27 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants