Skip to content

postgres: add --json body example to create-role help#5111

Open
jamesbroadhead wants to merge 3 commits intomainfrom
jb/postgres-create-role-help
Open

postgres: add --json body example to create-role help#5111
jamesbroadhead wants to merge 3 commits intomainfrom
jb/postgres-create-role-help

Conversation

@jamesbroadhead
Copy link
Copy Markdown

Summary

databricks postgres create-role's --json flag binds to the inner Role object (CreateRoleRequest.Role, JSON-tagged "role"), so users must supply spec / name / etc. directly. Without an example this isn't obvious — the auto-generated help leaves the spec fields unflagged (// TODO: complex arg: spec in the generator), and the server's error when the body is wrong is vague:

Field 'role' is required and must contain at least one subfield with a non-default value

That fires whenever the inner Role has no recognized fields, which most commonly happens when a user wraps the body in {"role": ...} (matching the wire format the SDK marshals to). The CLI strips the unknown outer key with Warning: unknown field: role and ships an empty body. Walking out of that loop currently requires reading the SDK source.

This adds a curated override (cmd/workspace/postgres/overrides.go) that appends a concrete service-principal-role example to cmd.Long, plus a short note on the wrapping pitfall.

Help output (after)

Arguments:
  PARENT: The Branch where this Role is created. Format:
    projects/{project_id}/branches/{branch_id}

Body shape (passed via --json): fields go directly on the Role object.
Do not wrap them in '{"role": ...}' — the CLI will strip the unknown
outer key and the server will reject the empty body with "Field 'role'
is required".

Example — create a service-principal-backed role:

  databricks postgres create-role projects/<PROJECT_ID>/branches/<BRANCH_ID> \
    --role-id <SP_CLIENT_ID> \
    --json '{"spec": {"identity_type": "SERVICE_PRINCIPAL", "postgres_role": "<SP_CLIENT_ID>", "auth_method": "LAKEBASE_OAUTH_V1", "membership_roles": ["DATABRICKS_SUPERUSER"]}}'

Scope

This PR only touches create-role. The same shape gap (// TODO: complex arg: spec + opaque error) exists for create-endpoint, create-branch, create-project, and create-database. Happy to extend if the approach is right; left them out so reviewers can decide on the pattern first.

Test plan

  • go build ./cmd/workspace/postgres/...
  • databricks postgres create-role --help shows the new section (output above)
  • make fmt clean
  • Reproduced the original confusion with a service-principal payload before the change; with this PR the example would have led me straight to the working body shape

This pull request and its description were written by Isaac.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Apr 28, 2026

Approval status: pending

/libs/flags/ - needs approval

Files: libs/flags/json_flag.go
Suggested: @simonfaltum
Also eligible: @renaudhartert-db, @hectorcast-db, @parthban-db, @tanmay-db, @Divyansh-db, @tejaskochar-db, @mihaimitrea-db, @chrisst, @rauchy

General files (require maintainer)

Files: cmd/workspace/postgres/overrides.go, cmd/workspace/postgres/overrides_test.go
Based on git history:

  • @simonfaltum -- recent work in cmd/workspace/postgres/

Any maintainer (@andrewnester, @anton-107, @denik, @pietern, @shreyas-goenka, @simonfaltum, @renaudhartert-db) can approve all areas.
See OWNERS for ownership rules.

`databricks postgres create-role`'s `--json` flag binds to the inner Role
object (CreateRoleRequest.Role, JSON-tagged "role"), so users supply
`spec`/`name`/etc. directly. Without an example this is non-obvious:

- Auto-generated help leaves `// TODO: complex arg: spec` with no flag
  hint, so the only way to set spec fields is through `--json`.
- If a user wraps the body in `{"role": ...}` (matching the wire format
  the SDK marshals to), the CLI strips `role` as unknown and ships an
  empty body. The server then returns a generic
  `Field 'role' is required and must contain at least one subfield with
  a non-default value` — which is hard to act on.

Adds a curated override that appends a concrete service-principal-role
example to `cmd.Long`, plus a short note on the wrapping pitfall.

Same pattern (auto-gen TODO `spec`/`status`, opaque error on bad body)
exists for create-endpoint, create-branch, create-project, and
create-database. Holding off on those until this approach is approved.

Co-authored-by: Isaac
The previous example granted DATABRICKS_SUPERUSER, normalizing
over-privileged service-principal roles. Drop membership_roles from the
example so the default copy-paste path follows least privilege; add a
note pointing to separate SQL grants and noting when DATABRICKS_SUPERUSER
is appropriate.

Co-authored-by: Isaac
…-role

The --json flag binds to the inner Role object, so a top-level
{"role": {...}} wrapper produced an "unknown field: role" warning, an
empty body, and a confusing server error: "Field 'role' is required".

Add a PreRunE on create-role that peeks at the raw --json bytes via a
new flags.JsonFlag.Raw() accessor and rejects any object with a top-
level "role" key, returning an actionable error that points to the
correct shape. Update the help text to reflect the new behavior and
add unit-tests covering wrapped, unwrapped, empty, non-object, and
no-flag cases.

Co-authored-by: Isaac
@jamesbroadhead jamesbroadhead force-pushed the jb/postgres-create-role-help branch from 5254a5b to 4ff71dd Compare May 5, 2026 14:56
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.

1 participant