Skip to content

feat(identity): add --project/--project-domain to user set - #20

Merged
ftarasenko merged 2 commits into
masterfrom
claude/lucid-hamilton-wdwo1u
Sep 14, 2026
Merged

ftarasenko merged 2 commits into
masterfrom
claude/lucid-hamilton-wdwo1u

Conversation

@ftarasenko

Copy link
Copy Markdown
Owner

Closes #19.

koc user set could not change a user's default project. The flag pair existed
on user create only, while user show printed Default Project ID all along —
settable at creation, visible forever, never changeable. Upstream
openstack user set has taken --project (and --project-domain) since forever
(python-openstackclient 10.2.1, identity/v3/user.py, SetUser), so the
workaround was to reach for openstack.

users.UpdateOpts.DefaultProjectID was already in the pinned gophercloud
v2.13.0, so this is unwired capability rather than a vendor change.

Changes

  • internal/cli/identity/user.go — register --project / --project-domain on
    user set and set DefaultProjectID. The project-domain resolution that
    runUserCreate grew inline is now a shared resolveDefaultProjectID both
    write verbs call: an empty --project short-circuits in resolveProjectID
    and the empty ID is omitempty on both opts structs, so the field stays
    untouched when the flag is absent.
  • internal/cli/identity/user_test.go — two tests through the runUserSet
    seam: the PATCH body, and a table for --project-domain overriding vs.
    falling back to the user's domain.
  • docs/coverage.md — no count change (no new leaf command); records the one
    semantic deviation below under "Naming deviations".

Deviation

Absent --project-domain, the lookup falls back to the user's own domain, where
upstream resolves the default project unscoped across all domains. The two
differ only when --domain is given and the default project lives elsewhere,
which --project-domain then states explicitly. Scoping to the user's domain is
the safer reading of a cloud-wide-ambiguous project name and keeps the two user
write verbs consistent with each other.

Verification

Offline gate on the merged tree: gofmt clean under the pinned toolchain,
go vet clean, golangci-lint run ./... 0 issues (v2.13.2, the CI pin,
checksum-verified), go test ./... green with -mod=vendor GOPROXY=off, static
build OK.

Exercised end-to-end with the built binary against a mock keystone —
koc user set --project admin admin resolves the user, resolves the project,
then PATCH /v3/users/u1 {"user":{"default_project_id":"..."}} and prints
nothing, matching upstream:

GET   /v3/users?name=admin
GET   /v3/projects?name=admin
PATCH /v3/users/u1  {"user":{"default_project_id":"p-admin"}}

Not included, and left on #19 for a separate pass: --email (missing from
user create too), --password-prompt, and the _add_user_options family.

🤖 Generated with Claude Code

https://claude.ai/code/session_019Dnh8BhczXscNe67sYomCw


Generated by Claude Code

`koc user set` could not change a user's default project: the flag pair
existed on `user create` only, while `user show` printed `Default Project
ID` all along — settable at creation, visible forever, never changeable.
Upstream `openstack user set` has taken `--project` (and `--project-domain`)
since forever (python-openstackclient `identity/v3/user.py`, `SetUser`), so
the workaround was to reach for `openstack`, which is what this binary
exists to avoid.

`users.UpdateOpts.DefaultProjectID` was already in the pinned gophercloud
v2.13.0, so this is unwired capability rather than a vendor change. The
project-domain resolution `runUserCreate` grew is now a shared
`resolveDefaultProjectID` helper that both write verbs call: an empty
--project short-circuits in `resolveProjectID` and the empty ID is
`omitempty` on both opts structs, so the field stays untouched when the
flag is absent.

Absent --project-domain the lookup falls back to the user's own domain,
where upstream resolves the project unscoped across all domains. The two
differ only when --domain is given and the default project lives
elsewhere; scoping to the user's domain is the safer reading of an
ambiguous project name and keeps the two user write verbs consistent.
Recorded under "Naming deviations" in docs/coverage.md, which needs no
count change — this adds no leaf command.

Verified end-to-end against a mock keystone: `koc user set --project admin
admin` resolves the user, resolves the project, then PATCHes
`{"user":{"default_project_id":"..."}}` and prints nothing, matching
upstream.

Closes #19

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Dnh8BhczXscNe67sYomCw
@ftarasenko
ftarasenko merged commit e05bcab into master Sep 14, 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.

identity: koc user set cannot change the default project (no --project/--project-domain)

2 participants