Skip to content

rpk/registry: add context list and delete commands#29689

Merged
c-julin merged 3 commits into
redpanda-data:devfrom
c-julin:jc/schema-context
Mar 13, 2026
Merged

rpk/registry: add context list and delete commands#29689
c-julin merged 3 commits into
redpanda-data:devfrom
c-julin:jc/schema-context

Conversation

@c-julin

@c-julin c-julin commented Feb 24, 2026

Copy link
Copy Markdown
Contributor

Add rpk registry context list and rpk registry context delete commands
for managing schema registry contexts. Also add a --schema-context
persistent flag on the registry parent command so all subcommands
(including compatibility-level) can be scoped to a specific context.

Update compatibility-level get/set to use cmd.Context() instead of
context.Background() so the schema context propagates correctly.

Includes integration tests using srfake.

Backports Required

  • none - not a bug fix
  • none - this is a backport
  • none - issue does not exist in previous branches
  • none - papercut/not impactful enough to backport
  • v25.3.x
  • v25.2.x
  • v25.1.x

Release Notes

Features

  • Add rpk registry context list and rpk registry context delete commands for managing schema registry contexts
  • Add --schema-context flag to rpk registry to scope all registry operations to a specific context

Test Plan

subject list

Test Case Flags Expected
No context, no contexts exist (none) Plain list, no CONTEXT column
No context, contexts exist --skip-context-check CONTEXT column with default/.ctx1
With --schema-context .ctx1 --skip-context-check Only subjects in .ctx1, no qualifier, no CONTEXT column
With --deleted --skip-context-check --schema-context .ctx1 Shows deleted subjects
Raw qualified subject (none) Shows :.ctx1:sub-a as-is

subject delete

Test Case Flags Args Expected
No context (none) topic-a Deletes topic-a, output shows topic-a
With --schema-context .ctx1 --skip-context-check my-subject Deletes :.ctx1:my-subject, output shows my-subject
Raw qualified (none) :.ctx1:my-subject Deletes :.ctx1:my-subject, output shows raw name
Permanent delete --permanent --skip-context-check --schema-context .ctx1 my-subject Hard-deletes

schema list

Test Case Flags Expected
No context, no contexts exist (none) Plain table, no CONTEXT column
No context, contexts exist --skip-context-check CONTEXT column with default/.ctx1
With --schema-context .ctx1 --skip-context-check Only .ctx1 schemas, no CONTEXT column
Specific subjects with context --skip-context-check --schema-context .ctx1 schema list sub-a sub-b shows both
Raw qualified subjects (none) schema list ":.ctx1:sub-a" shows raw name

schema create

Test Case Flags Args Expected
No context --schema file.avro my-subject Creates under my-subject
With --schema-context .ctx1 --skip-context-check --schema file.avro my-subject Creates under :.ctx1:my-subject, output shows my-subject
Raw qualified --schema file.avro :.ctx1:my-subject Creates under :.ctx1:my-subject

schema get

Test Case Flags Args Expected
By version, no context --schema-version latest topic-a Returns schema
By version, with context --skip-context-check --schema-context .ctx1 --schema-version 1 my-subject Looks up :.ctx1:my-subject, output shows my-subject
By version, raw qualified --schema-version 1 :.ctx1:my-subject Shows raw name
By ID, no subject --id 1 (none) Returns all usages
By ID, with context --skip-context-check --schema-context .ctx1 --id 2 (none) Filters to .ctx1
By ID + subject, with context --skip-context-check --schema-context .ctx1 --id 2 my-subject Filters to :.ctx1:my-subject
By schema file, with context --skip-context-check --schema-context .ctx1 --schema file.avro my-subject Looks up in context
--print-schema --schema-version 1 --schema-context .ctx1 my-subject Pretty-printed schema

schema delete

Test Case Flags Args Expected
No context --schema-version 1 topic-a Soft-deletes version 1
With context --skip-context-check --schema-context .ctx1 --schema-version 1 my-subject Deletes, output shows my-subject
Raw qualified --schema-version 1 :.ctx1:my-subject Deletes using raw name
Permanent --permanent --skip-context-check --schema-context .ctx1 --schema-version 1 my-subject Hard-deletes

schema references

Test Case Flags Args Expected
No context --schema-version 1 topic-a Lists references
With context --skip-context-check --schema-context .ctx1 --schema-version 1 my-subject Strips qualifier in output
Raw qualified --schema-version 1 :.ctx1:my-subject Uses raw name

schema check-compatibility

Test Case Flags Args Expected
No context --schema file.avro --schema-version latest topic-a Checks against topic-a
With context --skip-context-check --schema-context .ctx1 --schema file.avro --schema-version latest my-subject Checks against :.ctx1:my-subject
Raw qualified --schema file.avro --schema-version latest :.ctx1:my-subject Uses raw name

compatibility-level get

Test Case Flags Args Expected
Global (no args) (none) (none) Returns global level
Per-subject, with context --skip-context-check --schema-context .ctx1 my-subject Shows my-subject
Per-subject + global --skip-context-check --schema-context .ctx1 --global my-subject Both rows, global unqualified
Raw qualified (none) :.ctx1:my-subject Shows raw name

compatibility-level set

Test Case Flags Args Expected
Global --level BACKWARD (none) Sets global level
Per-subject, with context --skip-context-check --schema-context .ctx1 --level FULL my-subject Shows my-subject
Per-subject + global --skip-context-check --schema-context .ctx1 --level FULL --global my-subject Both
Raw qualified --level BACKWARD :.ctx1:my-subject Uses raw name

mode get

Test Case Flags Args Expected
Global (no args) (none) (none) Returns global mode
Per-subject, with context --skip-context-check --schema-context .ctx1 my-subject Shows my-subject
Per-subject + global --skip-context-check --schema-context .ctx1 --global my-subject Both rows
Raw qualified (none) :.ctx1:my-subject Shows raw name

mode set

Test Case Flags Args Expected
Global --mode READONLY (none) Sets global mode
Per-subject, with context --skip-context-check --schema-context .ctx1 --mode READWRITE my-subject Sets on :.ctx1:my-subject
Raw qualified --mode READONLY :.ctx1:my-subject Uses raw name

mode reset

Test Case Flags Args Expected
Per-subject, no context (none) topic-a Resets mode
Per-subject, with context --skip-context-check --schema-context .ctx1 my-subject Resets :.ctx1:my-subject, output shows my-subject
Raw qualified (none) :.ctx1:my-subject Uses raw name

context list

Test Case Flags Expected
Contexts exist (none) Lists ., .ctx1, .ctx2
Empty registry (none) Lists . (default only)
Unsupported cluster (404) (none) Error: "not supported by this cluster"
JSON format --format json [{"name":"."},{"name":".ctx1"}]

context delete

Test Case Flags Args Expected
Valid context --no-confirm .ctx1 Deletes, success message
Non-existent context --no-confirm .nope Error: "context not found"
Invalid name (no dot) --no-confirm badname Error: "must start with '.'"

Validation / Edge Cases

Test Case Input Expected
--schema-context without dot --schema-context nope Error: "must start with '.'"
--schema-context with colon --schema-context ".a:b" Error: "must not contain ':'"
Admin API flag disabled --schema-context .ctx1 (admin returns false) Error: "not enabled"
Admin API unreachable --schema-context .ctx1 (no admin) Error with wrapped cause
--skip-context-check bypasses admin --schema-context .ctx1 --skip-context-check Succeeds

@c-julin c-julin marked this pull request as ready for review March 10, 2026 16:49
@c-julin c-julin requested review from a team, kbatuigas and r-vasquez as code owners March 10, 2026 16:49
@c-julin c-julin force-pushed the jc/schema-context branch 2 times, most recently from 5d14e30 to ea25394 Compare March 11, 2026 11:33
Comment thread src/go/rpk/pkg/cli/registry/context/context.go Outdated
Comment on lines +30 to +46
type contextResponse struct {
Name string `json:"name" yaml:"name"`
}

// ListContexts calls cl.Contexts and translates a 404 into a message
// indicating that the Redpanda cluster does not support schema contexts.
func ListContexts(ctx context.Context, cl *sr.Client) ([]string, error) {
contexts, err := cl.Contexts(ctx)
if err != nil {
var re *sr.ResponseError
if errors.As(err, &re) && re.StatusCode == 404 {
return nil, fmt.Errorf("schema registry contexts are not supported by this cluster")
}
return nil, err
}
return contexts, nil
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[food for thought, not for this PR, but maybe as a follow-up in next releases]

Would be cool to list the context, including the Mode and Compatibility that has been set. There are some other places like subject list, where we could add this as well.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Its a good suggestion and ive updated it to show mode and compatability for context list, haven't gone deeper than that but something we can look in to

Comment thread src/go/rpk/pkg/cli/registry/context/context.go Outdated
Comment thread src/go/rpk/pkg/cli/registry/context/context.go Outdated
Comment thread src/go/rpk/pkg/cli/registry/context/context.go Outdated
Comment thread src/go/rpk/pkg/cli/registry/context/context.go
Comment on lines +42 to +47
contexts, err := ListContexts(cmd.Context(), cl.Client)
out.MaybeDie(err, "%v", err)

if !slices.Contains(contexts, name) {
out.Die("context %q not found", name)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does Core makes this validation?

Comment thread src/go/rpk/pkg/cli/registry/context/delete.go
Comment thread src/go/rpk/pkg/cli/registry/context/list.go Outdated
Comment on lines +60 to +62
schemaCtx, _ := cmd.Flags().GetString("schema-context")
skipCheck, _ := cmd.Flags().GetBool("skip-context-check")
showCtxCol := schemaCtx == "" && srcontext.CheckContextSupport(cmd.Context(), cl.Client, fs, p, skipCheck) == nil

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think of always displaying the Context column and having it empty when it is not enabled?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh right i think that is a bit confusing/gives the wrong impression. can be swayed but dont think its the right think to do

c-julin added a commit to c-julin/redpanda that referenced this pull request Mar 12, 2026
c-julin added 3 commits March 12, 2026 14:49
Add utility functions for working with schema registry contexts:
QualifySubject, ContextSubjectPrefix, StripContextQualifier,
ParseSubjectContext, and DisplayContext. These handle the
":{ctx}:{subject}" wire format used by context-qualified subjects.
Add --schema-context persistent flag to rpk registry that qualifies
subject names with a context prefix for all SR operations. Existing
commands (subject, schema, mode, compatibility-level) transparently
use the qualified subject format when --schema-context is set.

Add registry/context subpackage with list and delete subcommands,
ValidateContext for flag validation, and CheckContextSupport used by
list commands to show a CONTEXT column when the cluster supports
contexts. The context column is hidden when --schema-context filters
to a single context.
@c-julin c-julin force-pushed the jc/schema-context branch from d5a6e9f to 15198c4 Compare March 12, 2026 14:53

@r-vasquez r-vasquez left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@c-julin c-julin merged commit c223fdc into redpanda-data:dev Mar 13, 2026
24 of 26 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants