From 50184c9e5270a3705a56dd9e9a0d0b11f4cab679 Mon Sep 17 00:00:00 2001 From: Adam Wolfe Gordon Date: Thu, 14 May 2026 16:57:18 -0600 Subject: [PATCH 1/2] help: Format help text using markdown Use the glamour library to render detailed help text using markdown. This makes it more ergonomic to write extensive help text and gives us lots of flexibility in how it's formatted. Define custom light and dark stylesheets based on glamour's defaults, using Crossplane brand colors for common elements. Signed-off-by: Adam Wolfe Gordon --- cmd/crossplane/config/config.go | 21 +- cmd/crossplane/config/help/config.md | 20 + .../convert/compositionenvironment/cmd.go | 26 +- .../help/composition-environment.md | 31 ++ cmd/crossplane/convert/convert.go | 17 +- cmd/crossplane/convert/help/convert.md | 6 + cmd/crossplane/help.go | 393 ++++++++++++++++++ cmd/crossplane/help.md | 3 + cmd/crossplane/main.go | 17 +- cmd/crossplane/render/op/cmd.go | 94 +---- cmd/crossplane/render/op/help/render.md | 116 ++++++ cmd/crossplane/render/xr/cmd.go | 98 +---- cmd/crossplane/render/xr/help/render.md | 151 +++++++ cmd/crossplane/top/help/top.md | 26 ++ cmd/crossplane/top/top.go | 21 +- cmd/crossplane/trace/help/trace.md | 116 ++++++ cmd/crossplane/trace/trace.go | 40 +- cmd/crossplane/validate/cmd.go | 40 +- cmd/crossplane/validate/help/validate.md | 148 +++++++ cmd/crossplane/xpkg/build.go | 19 +- cmd/crossplane/xpkg/help/build.md | 65 +++ cmd/crossplane/xpkg/help/init.md | 41 ++ cmd/crossplane/xpkg/help/install.md | 60 +++ cmd/crossplane/xpkg/help/push.md | 32 ++ cmd/crossplane/xpkg/help/update.md | 27 ++ cmd/crossplane/xpkg/help/xpkg.md | 11 + cmd/crossplane/xpkg/init.go | 41 +- cmd/crossplane/xpkg/install.go | 22 +- cmd/crossplane/xpkg/push.go | 21 +- cmd/crossplane/xpkg/update.go | 17 +- cmd/crossplane/xpkg/xpkg.go | 17 +- go.mod | 16 +- go.sum | 31 +- gomod2nix.toml | 36 +- internal/style/dark.json | 157 +++++++ internal/style/light.json | 157 +++++++ internal/style/style.go | 70 ++++ 37 files changed, 1798 insertions(+), 426 deletions(-) create mode 100644 cmd/crossplane/config/help/config.md create mode 100644 cmd/crossplane/convert/compositionenvironment/help/composition-environment.md create mode 100644 cmd/crossplane/convert/help/convert.md create mode 100644 cmd/crossplane/help.go create mode 100644 cmd/crossplane/help.md create mode 100644 cmd/crossplane/render/op/help/render.md create mode 100644 cmd/crossplane/render/xr/help/render.md create mode 100644 cmd/crossplane/top/help/top.md create mode 100644 cmd/crossplane/trace/help/trace.md create mode 100644 cmd/crossplane/validate/help/validate.md create mode 100644 cmd/crossplane/xpkg/help/build.md create mode 100644 cmd/crossplane/xpkg/help/init.md create mode 100644 cmd/crossplane/xpkg/help/install.md create mode 100644 cmd/crossplane/xpkg/help/push.md create mode 100644 cmd/crossplane/xpkg/help/update.md create mode 100644 cmd/crossplane/xpkg/help/xpkg.md create mode 100644 internal/style/dark.json create mode 100644 internal/style/light.json create mode 100644 internal/style/style.go diff --git a/cmd/crossplane/config/config.go b/cmd/crossplane/config/config.go index dc8f1be..d73b969 100644 --- a/cmd/crossplane/config/config.go +++ b/cmd/crossplane/config/config.go @@ -17,6 +17,11 @@ limitations under the License. // Package config contains the `crossplane config` subcommands. package config +import _ "embed" + +//go:embed help/config.md +var helpDetail string + // ConfigPath is the resolved config file path. It is bound by main so that // subcommands can receive it as a Run() argument. Using a typed alias keeps // the binding distinct from any other string value Kong may know about. @@ -31,19 +36,5 @@ type Cmd struct { // Help returns the extended help for the config command. func (c *Cmd) Help() string { - return ` -Manage the crossplane CLI configuration file. - -The config file location is, in priority order: - 1. The --config flag. - 2. The CROSSPLANE_CONFIG environment variable. - 3. $XDG_CONFIG_HOME/crossplane/config.yaml (or ~/.config/crossplane/config.yaml). - -Examples: - # Show the current effective config. - crossplane config view - - # Enable alpha commands. - crossplane config set features.enableAlpha true -` + return helpDetail } diff --git a/cmd/crossplane/config/help/config.md b/cmd/crossplane/config/help/config.md new file mode 100644 index 0000000..91f2e07 --- /dev/null +++ b/cmd/crossplane/config/help/config.md @@ -0,0 +1,20 @@ +The `config` command manages the configuration file for the `crossplane` +CLI. The config file location is, in priority order: + +1. The `--config` flag. +2. The `CROSSPLANE_CONFIG` environment variable. +3. `$XDG_CONFIG_HOME/crossplane/config.yaml` (or `~/.config/crossplane/config.yaml`). + +## Examples + +Show the current effective config: + +```shell +crossplane config view +``` + +Enable alpha commands: + +```shell +crossplane config set features.enableAlpha true +``` diff --git a/cmd/crossplane/convert/compositionenvironment/cmd.go b/cmd/crossplane/convert/compositionenvironment/cmd.go index a5850ef..82a38cb 100644 --- a/cmd/crossplane/convert/compositionenvironment/cmd.go +++ b/cmd/crossplane/convert/compositionenvironment/cmd.go @@ -31,8 +31,13 @@ import ( "github.com/crossplane/crossplane-runtime/v2/pkg/errors" commonIO "github.com/crossplane/cli/v2/cmd/crossplane/convert/io" + + _ "embed" ) +//go:embed help/composition-environment.md +var helpDetail string + // Cmd arguments and flags for converting a Composition to use function-environment-configs. type Cmd struct { // Arguments. @@ -48,26 +53,7 @@ type Cmd struct { // Help returns help message for the migrate composition-environment command. func (c *Cmd) Help() string { - return ` -This command converts a Crossplane Composition to use function-environment-configs, if needed. - -It adds a function pipeline step using crossplane-contrib/function-environment-configs, if needed. -By default it'll reference the function as function-environment-configs, but it can be overridden -with the -f flag. - -Examples: - - # Convert an existing Composition (Pipeline mode) leveraging native - # Composition Environment to use function-environment-configs. - crossplane composition convert composition-environment composition.yaml -o composition-environment.yaml - - # Use a different functionRef and output to stdout. - crossplane composition convert composition-environment composition.yaml --function-environment-configs-ref local-function-environment-configs - - # Stdin to stdout. - cat composition.yaml | ./crossplane composition convert composition-environment - -` + return helpDetail } // AfterApply implements kong.AfterApply. diff --git a/cmd/crossplane/convert/compositionenvironment/help/composition-environment.md b/cmd/crossplane/convert/compositionenvironment/help/composition-environment.md new file mode 100644 index 0000000..8e0a206 --- /dev/null +++ b/cmd/crossplane/convert/compositionenvironment/help/composition-environment.md @@ -0,0 +1,31 @@ +The `composition convert composition-environment` command converts a Crossplane +Composition to use `function-environment-configs` in place of native Composition +Environments, which were removed in Crossplane v1.18. + +It adds a function pipeline step using +`crossplane-contrib/function-environment-configs` if needed. By default the +function is referenced as `function-environment-configs`, but this can be +overridden with `--function-environment-configs-ref`. + +## Examples + +Convert an existing pipeline mode Composition using native Composition +Environment to `function-environment-configs`: + +```shell +crossplane composition convert composition-environment composition.yaml \ + -o composition-environment.yaml +``` + +Use a different functionRef and output to stdout: + +```shell +crossplane composition convert composition-environment composition.yaml \ + --function-environment-configs-ref=local-function-environment-configs +``` + +Read a composition from stdin and output the updated composition on stdout: + +```shell +cat composition.yaml | crossplane composition convert composition-environment +``` diff --git a/cmd/crossplane/convert/convert.go b/cmd/crossplane/convert/convert.go index 35e1770..c2b6c62 100644 --- a/cmd/crossplane/convert/convert.go +++ b/cmd/crossplane/convert/convert.go @@ -20,8 +20,13 @@ package convert import ( "github.com/crossplane/cli/v2/cmd/crossplane/convert/compositionenvironment" + + _ "embed" ) +//go:embed help/convert.md +var helpDetail string + // Cmd converts a Crossplane resource to a newer version or a different kind. type Cmd struct { CompositionEnvironment compositionenvironment.Cmd `cmd:"" help:"Convert a Pipeline Composition to use function-environment-configs."` @@ -29,15 +34,5 @@ type Cmd struct { // Help returns help message for the migrate command. func (c *Cmd) Help() string { - return ` -This command converts a Crossplane resource to a newer version or a different kind. - -Currently supported conversions: - * native Composition Environment -> function-environment-configs - -Examples: - # Convert an existing Composition to use function-environment-configs instead of native Composition Environment, - # requires the composition to be in Pipeline mode already. - crossplane composition convert composition-environment composition.yaml -o composition-environment.yaml -` + return helpDetail } diff --git a/cmd/crossplane/convert/help/convert.md b/cmd/crossplane/convert/help/convert.md new file mode 100644 index 0000000..6cd5f5e --- /dev/null +++ b/cmd/crossplane/convert/help/convert.md @@ -0,0 +1,6 @@ +The `composition convert` command converts a Crossplane composition to use a +different version or migrate away from features that are no longer supported. + +The currently supported conversions are: + +- Native Composition Environment → `function-environment-configs` diff --git a/cmd/crossplane/help.go b/cmd/crossplane/help.go new file mode 100644 index 0000000..65a4db9 --- /dev/null +++ b/cmd/crossplane/help.go @@ -0,0 +1,393 @@ +/* +Copyright 2026 The Crossplane Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "bytes" + "fmt" + "go/doc" + "io" + "os" + "strings" + + "github.com/alecthomas/kong" + "github.com/charmbracelet/x/term" + + "github.com/crossplane/cli/v2/internal/style" +) + +// helpPrinter is our custom help printer for kong. It works much like the +// upstream kong help printer except we format detailed help using markdown. We +// have also removed options we don't use to simplify the code. +func helpPrinter(options kong.HelpOptions, ctx *kong.Context) error { + if ctx.Empty() { + options.Summary = false + } + w := newHelpWriter(ctx, options) + selected := ctx.Selected() + if selected == nil { + printApp(w, ctx.Model) + } else { + printCommand(w, ctx.Model, selected) + } + return w.Write(ctx.Stdout) +} + +func printApp(w *helpWriter, app *kong.Application) { + if !w.NoAppSummary { + w.Printf("Usage: %s%s", app.Name, app.Summary()) + } + printNodeDetail(w, app.Node) + cmds := app.Leaves(true) + if len(cmds) > 0 && app.HelpFlag != nil { + w.Print("") + if w.Summary { + w.Printf(`Run "%s --help" for more information.`, app.Name) + } else { + w.Printf(`Run "%s --help" for more information on a command.`, app.Name) + } + } +} + +func printCommand(w *helpWriter, app *kong.Application, cmd *kong.Command) { + if !w.NoAppSummary { + w.Printf("Usage: %s %s", app.Name, cmd.Summary()) + } + printNodeDetail(w, cmd) + if w.Summary && app.HelpFlag != nil { + w.Print("") + w.Printf(`Run "%s --help" for more information.`, cmd.FullPath()) + } +} + +func printNodeDetail(w *helpWriter, node *kong.Node) { + if node.Help != "" { + w.Print("") + w.Wrap(node.Help) + } + if w.Summary { + return + } + // Upstream kong formats detailed help with the go/doc package. We use + // markdown via the glamour library. + if node.Detail != "" { + w.Print(style.RenderMarkdown(node.Detail)) + } + if len(node.Positional) > 0 { + w.Print("Arguments:") + writePositionals(w.Indent(), node.Positional) + } + printFlags := func() { + if flags := node.AllFlags(true); len(flags) > 0 { + groupedFlags := collectFlagGroups(flags) + for _, group := range groupedFlags { + if group.Metadata.Title != "" { + w.Print("") + w.Wrap(group.Metadata.Title) + } + if group.Metadata.Description != "" { + w.Indent().Wrap(group.Metadata.Description) + w.Print("") + } + writeFlags(w.Indent(), group.Flags) + } + } + } + if !w.FlagsLast { + printFlags() + } + + cmds := node.Children + if len(cmds) > 0 { + iw := w.Indent() + groupedCmds := collectCommandGroups(cmds) + for _, group := range groupedCmds { + if group.Metadata.Title != "" { + w.Print("") + w.Wrap(group.Metadata.Title) + } + if group.Metadata.Description != "" { + w.Indent().Wrap(group.Metadata.Description) + w.Print("") + } + + writeCompactCommandList(group.Commands, iw) + } + } + if w.FlagsLast { + printFlags() + } +} + +func writeCompactCommandList(cmds []*kong.Node, iw *helpWriter) { + rows := [][2]string{} + for _, cmd := range cmds { + if cmd.Hidden { + continue + } + rows = append(rows, [2]string{cmd.Path(), cmd.Help}) + } + writeTwoColumns(iw, rows) +} + +type helpFlagGroup struct { + Metadata *kong.Group + Flags [][]*kong.Flag +} + +func collectFlagGroups(flags [][]*kong.Flag) []helpFlagGroup { + // Group keys in order of appearance. + groups := []*kong.Group{} + // Flags grouped by their group key. + flagsByGroup := map[string][][]*kong.Flag{} + + for _, levelFlags := range flags { + levelFlagsByGroup := map[string][]*kong.Flag{} + + for _, flag := range levelFlags { + key := "" + if flag.Group != nil { + key = flag.Group.Key + groupAlreadySeen := false + for _, group := range groups { + if key == group.Key { + groupAlreadySeen = true + break + } + } + if !groupAlreadySeen { + groups = append(groups, flag.Group) + } + } + + levelFlagsByGroup[key] = append(levelFlagsByGroup[key], flag) + } + + for key, flags := range levelFlagsByGroup { + flagsByGroup[key] = append(flagsByGroup[key], flags) + } + } + + out := []helpFlagGroup{} + // Ungrouped flags are always displayed first. + if ungroupedFlags, ok := flagsByGroup[""]; ok { + out = append(out, helpFlagGroup{ + Metadata: &kong.Group{Title: "Flags:"}, + Flags: ungroupedFlags, + }) + } + for _, group := range groups { + out = append(out, helpFlagGroup{Metadata: group, Flags: flagsByGroup[group.Key]}) + } + return out +} + +type helpCommandGroup struct { + Metadata *kong.Group + Commands []*kong.Node +} + +func collectCommandGroups(nodes []*kong.Node) []helpCommandGroup { + // Groups in order of appearance. + groups := []*kong.Group{} + // Nodes grouped by their group key. + nodesByGroup := map[string][]*kong.Node{} + + for _, node := range nodes { + key := "" + if group := node.ClosestGroup(); group != nil { + key = group.Key + if _, ok := nodesByGroup[key]; !ok { + groups = append(groups, group) + } + } + nodesByGroup[key] = append(nodesByGroup[key], node) + } + + out := []helpCommandGroup{} + // Ungrouped nodes are always displayed first. + if ungroupedNodes, ok := nodesByGroup[""]; ok { + out = append(out, helpCommandGroup{ + Metadata: &kong.Group{Title: "Commands:"}, + Commands: ungroupedNodes, + }) + } + for _, group := range groups { + out = append(out, helpCommandGroup{Metadata: group, Commands: nodesByGroup[group.Key]}) + } + return out +} + +type helpWriter struct { + kong.HelpOptions + + indent string + width int + lines *[]string + helpFormatter kong.HelpValueFormatter +} + +func newHelpWriter(_ *kong.Context, options kong.HelpOptions) *helpWriter { + // Don't use kong's insane width guessing algorithm. Just get the term size + // and cap at 120 to make paragraphs nice to read. + wrapWidth, _, _ := term.GetSize(os.Stdout.Fd()) + wrapWidth = min(wrapWidth, 120) + + lines := []string{} + if options.WrapUpperBound > 0 && wrapWidth > options.WrapUpperBound { + wrapWidth = options.WrapUpperBound + } + w := &helpWriter{ + indent: "", + width: wrapWidth, + lines: &lines, + helpFormatter: kong.DefaultHelpValueFormatter, + HelpOptions: options, + } + return w +} + +func (h *helpWriter) Printf(format string, args ...any) { + h.Print(fmt.Sprintf(format, args...)) +} + +func (h *helpWriter) Print(text string) { + *h.lines = append(*h.lines, strings.TrimRight(h.indent+text, " ")) +} + +// Indent returns a new helpWriter indented by two characters. +func (h *helpWriter) Indent() *helpWriter { + return &helpWriter{indent: h.indent + " ", lines: h.lines, width: h.width - 2, HelpOptions: h.HelpOptions, helpFormatter: h.helpFormatter} +} + +func (h *helpWriter) String() string { + return strings.Join(*h.lines, "\n") +} + +func (h *helpWriter) Write(w io.Writer) error { + for _, line := range *h.lines { + _, err := io.WriteString(w, line+"\n") + if err != nil { + return err + } + } + return nil +} + +func (h *helpWriter) Wrap(text string) { + w := bytes.NewBuffer(nil) + doc.ToText(w, strings.TrimSpace(text), "", " ", h.width) //nolint:staticcheck // cross-package links not possible + for line := range strings.SplitSeq(strings.TrimSpace(w.String()), "\n") { + h.Print(line) + } +} + +func writePositionals(w *helpWriter, args []*kong.Positional) { + rows := make([][2]string, 0, len(args)) + for _, arg := range args { + rows = append(rows, [2]string{arg.Summary(), w.helpFormatter(arg)}) + } + writeTwoColumns(w, rows) +} + +func writeFlags(w *helpWriter, groups [][]*kong.Flag) { + rows := [][2]string{} + haveShort := false + for _, group := range groups { + for _, flag := range group { + if flag.Short != 0 { + haveShort = true + break + } + } + } + for i, group := range groups { + if i > 0 { + rows = append(rows, [2]string{"", ""}) + } + for _, flag := range group { + if !flag.Hidden { + rows = append(rows, [2]string{formatFlag(haveShort, flag), w.helpFormatter(flag.Value)}) + } + } + } + writeTwoColumns(w, rows) +} + +const ( + defaultIndent = 2 + defaultColumnPadding = 4 +) + +func writeTwoColumns(w *helpWriter, rows [][2]string) { + maxLeft := max(375*w.width/1000, 30) + // Find size of first column. + leftSize := 0 + for _, row := range rows { + if c := len(row[0]); c > leftSize && c < maxLeft { + leftSize = c + } + } + + offsetStr := strings.Repeat(" ", leftSize+defaultColumnPadding) + + for _, row := range rows { + buf := bytes.NewBuffer(nil) + doc.ToText(buf, row[1], "", strings.Repeat(" ", defaultIndent), w.width-leftSize-defaultColumnPadding) //nolint:staticcheck // cross-package links not possible + lines := strings.Split(strings.TrimRight(buf.String(), "\n"), "\n") + + line := fmt.Sprintf("%-*s", leftSize, row[0]) + if len(row[0]) < maxLeft { + line += fmt.Sprintf("%*s%s", defaultColumnPadding, "", lines[0]) + lines = lines[1:] + } + w.Print(line) + for _, line := range lines { + w.Printf("%s%s", offsetStr, line) + } + } +} + +const negatableDefault = "_" + +// haveShort will be true if there are short flags present at all in the help. Useful for column alignment. +func formatFlag(haveShort bool, flag *kong.Flag) string { + flagString := "" + name := flag.Name + isBool := flag.IsBool() + isCounter := flag.IsCounter() + + short := "" + if flag.Short != 0 { + short = "-" + string(flag.Short) + ", " + } else if haveShort { + short = " " + } + + if isBool && flag.Tag.Negatable == negatableDefault { + name = "[no-]" + name + } else if isBool && flag.Tag.Negatable != "" { + name += "/" + flag.Tag.Negatable + } + + flagString += fmt.Sprintf("%s--%s", short, name) + + if !isBool && !isCounter { + flagString += fmt.Sprintf("=%s", flag.FormatPlaceHolder()) + } + return flagString +} diff --git a/cmd/crossplane/help.md b/cmd/crossplane/help.md new file mode 100644 index 0000000..a74f031 --- /dev/null +++ b/cmd/crossplane/help.md @@ -0,0 +1,3 @@ +A command line tool for interacting with Crossplane. + +Please report issues and feature requests at https://github.com/crossplane/cli. diff --git a/cmd/crossplane/main.go b/cmd/crossplane/main.go index ae8d2d6..c5dfd07 100644 --- a/cmd/crossplane/main.go +++ b/cmd/crossplane/main.go @@ -41,8 +41,13 @@ import ( "github.com/crossplane/cli/v2/cmd/crossplane/xpkg" "github.com/crossplane/cli/v2/internal/config" "github.com/crossplane/cli/v2/internal/maturity" + + _ "embed" ) +//go:embed help.md +var helpDescription string + var _ = kong.Must(&cli{}) type ( @@ -102,19 +107,17 @@ func main() { parser := kong.Must(&cli{}, kong.Name("crossplane"), - kong.Description("A command line tool for interacting with Crossplane."), // Binding a variable to kong context makes it available to all commands // at runtime. kong.BindTo(logger, (*logging.Logger)(nil)), kong.BindTo(configcmd.ConfigPath(cfgPath), (*configcmd.ConfigPath)(nil)), - kong.ConfigureHelp(kong.HelpOptions{ - FlagsLast: true, - Compact: true, - WrapUpperBound: 80, - NoExpandSubcommands: true, - }), + kong.Help(helpPrinter), kong.UsageOnError()) + // Set the top-level Detail to the embedded markdown so it renders via the + // markdown help printer. Done before maturity.Apply, which appends to it. + parser.Model.Detail = helpDescription + kongplete.Complete(parser, kongplete.WithPredictors(completion.Predictors()), ) diff --git a/cmd/crossplane/render/op/cmd.go b/cmd/crossplane/render/op/cmd.go index 6abc564..7780a8f 100644 --- a/cmd/crossplane/render/op/cmd.go +++ b/cmd/crossplane/render/op/cmd.go @@ -36,8 +36,13 @@ import ( "github.com/crossplane/cli/v2/cmd/crossplane/render" "github.com/crossplane/cli/v2/cmd/crossplane/render/contextfn" + + _ "embed" ) +//go:embed help/render.md +var helpDetail string + // Cmd arguments and flags for alpha render op subcommand. type Cmd struct { render.EngineFlags `prefix:""` @@ -68,94 +73,7 @@ type Cmd struct { // Help prints out the help for the alpha render op command. func (c *Cmd) Help() string { - return ` -This command shows you what resources an Operation would create or mutate by -printing them to stdout. It runs the Crossplane render engine to produce -high-fidelity output that matches what the real reconciler would produce. - -For Operations, it runs the operation function pipeline and shows what -resources the operation would mutate. - -Functions are pulled and run using Docker by default. You can add -the following annotations to each function to change how they're run: - - render.crossplane.io/runtime: "Development" - - Connect to a function that is already running, instead of using Docker. This - is useful to develop and debug new functions. The function must be listening - at localhost:9443 and running with the --insecure flag. - - render.crossplane.io/runtime-development-target: "dns:///example.org:7443" - - Connect to a function running somewhere other than localhost:9443. The - target uses gRPC target syntax. - - render.crossplane.io/runtime-docker-cleanup: "Orphan" - - Don't stop the function's Docker container after rendering. - - render.crossplane.io/runtime-docker-name: "" - - create a container with that name and also reuse it as long as it is running or can be restarted. - - render.crossplane.io/runtime-docker-pull-policy: "Always" - - Always pull the function's package, even if it already exists locally. - Other supported values are Never, or IfNotPresent. - -Use the standard DOCKER_HOST, DOCKER_API_VERSION, DOCKER_CERT_PATH, and -DOCKER_TLS_VERIFY environment variables to configure how this command connects -to the Docker daemon. - -Examples: - - # Render an Operation. - crossplane operation render operation.yaml functions.yaml - - # Pin the Crossplane version used for rendering. - crossplane operation render operation.yaml functions.yaml \ - --crossplane-version=v2.2.1 - - # Use a local crossplane binary instead of Docker. - crossplane operation render operation.yaml functions.yaml \ - --crossplane-binary=/usr/local/bin/crossplane - - # Pass context values to the function pipeline. - crossplane operation render operation.yaml functions.yaml \ - --context-values=apiextensions.crossplane.io/environment='{"key": "value"}' - - # Pass required resources functions can request. - crossplane operation render operation.yaml functions.yaml \ - --required-resources=required-resources.yaml - - # Pass OpenAPI schemas for functions that need them. - crossplane operation render operation.yaml functions.yaml \ - --required-schemas=schemas/ - - # Render a WatchOperation with a watched resource. - crossplane operation render watchoperation.yaml functions.yaml \ - --watched-resource=watched-configmap.yaml - - # Pass credentials to functions that need them. - crossplane operation render operation.yaml functions.yaml \ - --function-credentials=credentials.yaml - - # Include function results and context in output. - crossplane operation render operation.yaml functions.yaml -r -c - - # Include the full Operation with original spec and metadata. - crossplane operation render operation.yaml functions.yaml -o - - # Override function annotations for remote Docker daemon. - crossplane operation render operation.yaml functions.yaml \ - -a render.crossplane.io/runtime-docker-publish-address=0.0.0.0 \ - -a render.crossplane.io/runtime-docker-target=192.168.1.100 - - # Use development runtime with custom target. - crossplane operation render operation.yaml functions.yaml \ - -a render.crossplane.io/runtime=Development \ - -a render.crossplane.io/runtime-development-target=localhost:9444 -` + return helpDetail } // AfterApply implements kong.AfterApply. diff --git a/cmd/crossplane/render/op/help/render.md b/cmd/crossplane/render/op/help/render.md new file mode 100644 index 0000000..23a37dc --- /dev/null +++ b/cmd/crossplane/render/op/help/render.md @@ -0,0 +1,116 @@ +The `operation render` command shows you what resources an Operation would +create or mutate by running the operation locally and printing its results. It +runs the Crossplane render engine (either in a Docker container or via a local +binary) to produce high-fidelity output that matches what the real reconciler +would produce. + +> **Important:** This command runs operation functions and the Crossplane render +> engine using Docker by default, requiring a working Docker installation. See +> the function annotations and `--crossplane-binary` option below to understand +> how to render without Docker. + +## Function runtime configuration + +Operation Functions are pulled and run using Docker by default. You can add the +following annotations to each Function to change how they're run: + +| Annotation | Purpose | +| ---------- | ------- | +| `render.crossplane.io/runtime: "Development"` | Connect to a Function that is already running, instead of using Docker. This is useful to develop and debug new Functions. The Function must be listening at `localhost:9443` and running with the `--insecure` flag. | +| `render.crossplane.io/runtime-development-target: "dns:///example.org:7443"` | Connect to a Function running somewhere other than `localhost:9443`. The target uses gRPC target syntax (e.g., `dns:///example.org:7443` or simply `example.org:7443`). | +| `render.crossplane.io/runtime-docker-cleanup: "Orphan"` | Don't stop the Function's Docker container after rendering. | +| `render.crossplane.io/runtime-docker-name: ""` | Create a container with that name and reuse it as long as it is running or can be restarted. | +| `render.crossplane.io/runtime-docker-pull-policy: "Always"` | Always pull the Function's package, even if it already exists locally. Other supported values are `Never` or `IfNotPresent`. | +| `render.crossplane.io/runtime-docker-publish-address: "0.0.0.0"` | Host address that Docker should publish the Function's container port to. Defaults to `127.0.0.1` (localhost only). Use `0.0.0.0` to publish to all host network interfaces, enabling access from remote machines. | +| `render.crossplane.io/runtime-docker-target: "docker-host"` | Address that the render CLI should use to connect to the Function's Docker container. If not specified, uses the publish address. | + +Use the standard `DOCKER_HOST`, `DOCKER_API_VERSION`, `DOCKER_CERT_PATH`, and +`DOCKER_TLS_VERIFY` environment variables to configure how this command connects +to the Docker daemon. See the [Docker environment +variables](https://docs.docker.com/engine/reference/commandline/cli/#environment-variables) +reference. + +## Examples + +Render an Operation: + +```shell +crossplane operation render operation.yaml functions.yaml +``` + +Pin the Crossplane version used for rendering: + +```shell +crossplane operation render operation.yaml functions.yaml \ + --crossplane-version=v2.2.1 +``` + +Use a local crossplane binary instead of Docker: + +```shell +crossplane operation render operation.yaml functions.yaml \ + --crossplane-binary=/usr/local/bin/crossplane +``` + +Pass context values to the function pipeline: + +```shell +crossplane operation render operation.yaml functions.yaml \ + --context-values=apiextensions.crossplane.io/environment='{"key": "value"}' +``` + +Pass required resources functions can request: + +```shell +crossplane operation render operation.yaml functions.yaml \ + --required-resources=required-resources.yaml +``` + +Pass OpenAPI schemas for functions that need them: + +```shell +crossplane operation render operation.yaml functions.yaml \ + --required-schemas=schemas/ +``` + +Render a WatchOperation with a watched resource: + +```shell +crossplane operation render watchoperation.yaml functions.yaml \ + --watched-resource=watched-configmap.yaml +``` + +Pass credentials to functions that need them: + +```shell +crossplane operation render operation.yaml functions.yaml \ + --function-credentials=credentials.yaml +``` + +Include function results and context in output: + +```shell +crossplane operation render operation.yaml functions.yaml -r -c +``` + +Include the full Operation with original spec and metadata: + +```shell +crossplane operation render operation.yaml functions.yaml -o +``` + +Override function annotations for remote Docker daemon: + +```shell +crossplane operation render operation.yaml functions.yaml \ + -a render.crossplane.io/runtime-docker-publish-address=0.0.0.0 \ + -a render.crossplane.io/runtime-docker-target=192.168.1.100 +``` + +Use development runtime with custom target for all functions: + +```shell +crossplane operation render operation.yaml functions.yaml \ + -a render.crossplane.io/runtime=Development \ + -a render.crossplane.io/runtime-development-target=localhost:9444 +``` diff --git a/cmd/crossplane/render/xr/cmd.go b/cmd/crossplane/render/xr/cmd.go index 90abee6..876261e 100644 --- a/cmd/crossplane/render/xr/cmd.go +++ b/cmd/crossplane/render/xr/cmd.go @@ -39,8 +39,13 @@ import ( "github.com/crossplane/cli/v2/cmd/crossplane/render" "github.com/crossplane/cli/v2/cmd/crossplane/render/contextfn" + + _ "embed" ) +//go:embed help/render.md +var helpDetail string + // Cmd arguments and flags for the `render xr` subcommand. type Cmd struct { render.EngineFlags `prefix:""` @@ -74,98 +79,7 @@ type Cmd struct { // Help prints out the help for the render command. func (c *Cmd) Help() string { - return ` -This command shows you what composed resources Crossplane would create by -printing them to stdout. It also prints any changes that would be made to the -status of the XR. It runs the Crossplane render engine (either in a Docker -container or via a local binary) to produce high-fidelity output that matches -what the real reconciler would produce. - -Composition Functions are pulled and run using Docker by default. You can add -the following annotations to each Function to change how they're run: - - render.crossplane.io/runtime: "Development" - - Connect to a Function that is already running, instead of using Docker. This - is useful to develop and debug new Functions. The Function must be listening - at localhost:9443 and running with the --insecure flag. - - render.crossplane.io/runtime-development-target: "dns:///example.org:7443" - - Connect to a Function running somewhere other than localhost:9443. The - target uses gRPC target syntax (e.g., dns:///example.org:7443 or simply example.org:7443). - - render.crossplane.io/runtime-docker-cleanup: "Orphan" - - Don't stop the Function's Docker container after rendering. - - render.crossplane.io/runtime-docker-name: "" - - create a container with that name and also reuse it as long as it is running or can be restarted. - - render.crossplane.io/runtime-docker-pull-policy: "Always" - - Always pull the Function's package, even if it already exists locally. - Other supported values are Never, or IfNotPresent. - - render.crossplane.io/runtime-docker-publish-address: "0.0.0.0" - - Host address that Docker should publish the Function's container port to. - Defaults to 127.0.0.1 (localhost only). Use 0.0.0.0 to publish to all host - network interfaces, enabling access from remote machines. - - render.crossplane.io/runtime-docker-target: "docker-host" - - Address that the render CLI should use to connect to the Function's Docker - container. If not specified, uses the publish address. - -Use the standard DOCKER_HOST, DOCKER_API_VERSION, DOCKER_CERT_PATH, and -DOCKER_TLS_VERIFY environment variables to configure how this command connects -to the Docker daemon. - -Examples: - - # Simulate creating a new XR. - crossplane composition render xr.yaml composition.yaml functions.yaml - - # Simulate updating an XR that already exists. - crossplane composition render xr.yaml composition.yaml functions.yaml \ - --observed-resources=existing-observed-resources.yaml - - # Pin the Crossplane version used for rendering. - crossplane composition render xr.yaml composition.yaml functions.yaml \ - --crossplane-version=v2.3.0 - - # Use a local crossplane binary instead of Docker. - crossplane composition render xr.yaml composition.yaml functions.yaml \ - --crossplane-binary=/usr/local/bin/crossplane - - # Pass context values to the Function pipeline. - crossplane composition render xr.yaml composition.yaml functions.yaml \ - --context-values=apiextensions.crossplane.io/environment='{"key": "value"}' - - # Pass required resources Functions in the pipeline can request. - crossplane composition render xr.yaml composition.yaml functions.yaml \ - --required-resources=required-resources.yaml - - # Pass OpenAPI schemas for Functions that need them. - crossplane composition render xr.yaml composition.yaml functions.yaml \ - --required-schemas=schemas/ - - # Pass credentials to Functions in the pipeline that need them. - crossplane composition render xr.yaml composition.yaml functions.yaml \ - --function-credentials=credentials.yaml - - # Override function annotations for a remote Docker daemon. - DOCKER_HOST=tcp://192.168.1.100:2376 crossplane composition render xr.yaml composition.yaml functions.yaml \ - -a render.crossplane.io/runtime-docker-publish-address=0.0.0.0 \ - -a render.crossplane.io/runtime-docker-target=192.168.1.100 - - # Force all functions to use development runtime. - crossplane composition render xr.yaml composition.yaml functions.yaml \ - -a render.crossplane.io/runtime=Development \ - -a render.crossplane.io/runtime-development-target=localhost:9444 -` + return helpDetail } // AfterApply implements kong.AfterApply. diff --git a/cmd/crossplane/render/xr/help/render.md b/cmd/crossplane/render/xr/help/render.md new file mode 100644 index 0000000..ab0ed95 --- /dev/null +++ b/cmd/crossplane/render/xr/help/render.md @@ -0,0 +1,151 @@ +The `composition render` command shows you what resources a Composition would +create or mutate by running the composition locally and printing its results. It +also prints any changes that would be made to the status of the XR. It runs the +Crossplane render engine (either in a Docker container or via a local binary) to +produce high-fidelity output that matches what the real reconciler would +produce. + +By default, only the `status` field and `metadata.name` of the XR are +printed. Use `--include-full-xr` (`-x`) to include the full XR `spec` and +`metadata`. + +> **Important:** This command runs composition functions and the Crossplane +> render engine using Docker by default, requiring a working Docker +> installation. See the function annotations and `--crossplane-binary` option +> below to understand how to render without Docker. + +## Function runtime configuration + +Composition Functions are pulled and run using Docker by default. You can add +the following annotations to each Function to change how they're run: + +| Annotation | Purpose | +| ---------- | ------- | +| `render.crossplane.io/runtime: "Development"` | Connect to a Function that is already running, instead of using Docker. This is useful to develop and debug new Functions. The Function must be listening at `localhost:9443` and running with the `--insecure` flag. | +| `render.crossplane.io/runtime-development-target: "dns:///example.org:7443"` | Connect to a Function running somewhere other than `localhost:9443`. The target uses gRPC target syntax (e.g., `dns:///example.org:7443` or simply `example.org:7443`). | +| `render.crossplane.io/runtime-docker-cleanup: "Orphan"` | Don't stop the Function's Docker container after rendering. | +| `render.crossplane.io/runtime-docker-name: ""` | Create a container with that name and reuse it as long as it is running or can be restarted. | +| `render.crossplane.io/runtime-docker-pull-policy: "Always"` | Always pull the Function's package, even if it already exists locally. Other supported values are `Never` or `IfNotPresent`. | +| `render.crossplane.io/runtime-docker-publish-address: "0.0.0.0"` | Host address that Docker should publish the Function's container port to. Defaults to `127.0.0.1` (localhost only). Use `0.0.0.0` to publish to all host network interfaces, enabling access from remote machines. | +| `render.crossplane.io/runtime-docker-target: "docker-host"` | Address that the render CLI should use to connect to the Function's Docker container. If not specified, uses the publish address. | + +Use the standard `DOCKER_HOST`, `DOCKER_API_VERSION`, `DOCKER_CERT_PATH`, and +`DOCKER_TLS_VERIFY` environment variables to configure how this command connects +to the Docker daemon. See the [Docker environment +variables](https://docs.docker.com/engine/reference/commandline/cli/#environment-variables) +reference. + +## Function context + +The `--context-files` and `--context-values` flags pass data to each Function's +`context`. The context is JSON-formatted data. + +## Function results + +If a Function emits events with statuses, use `--include-function-results` +(`-r`) to print them alongside the rendered resources. + +## Observed (mock) resources + +`--observed-resources` (`-o`) lets you pass mocked managed resources to the +Function pipeline. `render` treats those inputs as if they were resources +observed in a Crossplane cluster, so Functions can reference and manipulate +them. + +The argument may be a single YAML file containing multiple resources or a +directory of YAML files. The schema of the mocked resources isn't validated and +may contain any data. + +```yaml +apiVersion: example.org/v1alpha1 +kind: ComposedResource +metadata: + name: test-render-b + annotations: + crossplane.io/composition-resource-name: resource-b +spec: + coolerField: "I'm cooler!" +``` + +## Required (extra) resources + +Required resources let a Composition request Crossplane objects on the cluster +that aren't part of the Composition. Pass them with `--required-resources` +(`-e`) — a YAML file or directory of YAML files of resources to mock. Use this +with a Function like +[function-extra-resources](https://github.com/crossplane-contrib/function-extra-resources) +or the built-in support in +[function-go-templating](https://github.com/crossplane-contrib/function-go-templating?tab=readme-ov-file#extraresources). + +## Examples + +Simulate creating a new XR: + +```shell +crossplane composition render xr.yaml composition.yaml functions.yaml +``` + +Simulate updating an XR that already exists: + +```shell +crossplane composition render xr.yaml composition.yaml functions.yaml \ + --observed-resources=existing-observed-resources.yaml +``` + +Pin the Crossplane version used for rendering: + +```shell +crossplane composition render xr.yaml composition.yaml functions.yaml \ + --crossplane-version=v2.3.0 +``` + +Use a local crossplane binary instead of Docker: + +```shell +crossplane composition render xr.yaml composition.yaml functions.yaml \ + --crossplane-binary=/usr/local/bin/crossplane +``` + +Pass context values to the Function pipeline: + +```shell +crossplane composition render xr.yaml composition.yaml functions.yaml \ + --context-values=apiextensions.crossplane.io/environment='{"key": "value"}' +``` + +Pass required resources Functions in the pipeline can request: + +```shell +crossplane composition render xr.yaml composition.yaml functions.yaml \ + --required-resources=required-resources.yaml +``` + +Pass OpenAPI schemas for Functions that need them: + +```shell +crossplane composition render xr.yaml composition.yaml functions.yaml \ + --required-schemas=schemas/ +``` + +Pass credentials to Functions in the pipeline that need them: + +```shell +crossplane composition render xr.yaml composition.yaml functions.yaml \ + --function-credentials=credentials.yaml +``` + +Override function annotations for a remote Docker daemon: + +```shell +DOCKER_HOST=tcp://192.168.1.100:2376 crossplane composition render xr.yaml composition.yaml functions.yaml \ + -a render.crossplane.io/runtime-docker-publish-address=0.0.0.0 \ + -a render.crossplane.io/runtime-docker-target=192.168.1.100 +``` + +Force all functions to use development runtime: + +```shell +crossplane composition render xr.yaml composition.yaml functions.yaml \ + -a render.crossplane.io/runtime=Development \ + -a render.crossplane.io/runtime-development-target=localhost:9444 +``` diff --git a/cmd/crossplane/top/help/top.md b/cmd/crossplane/top/help/top.md new file mode 100644 index 0000000..cfcb2fd --- /dev/null +++ b/cmd/crossplane/top/help/top.md @@ -0,0 +1,26 @@ +The `cluster top` command returns current resource utilization (CPU and memory) +by Crossplane pods. Similar to `kubectl top pods`, it requires the [Metrics +Server](https://kubernetes-sigs.github.io/metrics-server/) to be correctly +configured and working on the server. + +## Examples + +Show resource utilization for all Crossplane pods in the `crossplane-system` +namespace: + +```shell +crossplane cluster top +``` + +Show resource utilization for all Crossplane pods in the `default` namespace: + +```shell +crossplane cluster top -n default +``` + +Add a summary of resource utilization for all Crossplane pods on top of the +results: + +```shell +crossplane cluster top -s +``` diff --git a/cmd/crossplane/top/top.go b/cmd/crossplane/top/top.go index 2093667..29f61cd 100644 --- a/cmd/crossplane/top/top.go +++ b/cmd/crossplane/top/top.go @@ -35,8 +35,13 @@ import ( "github.com/crossplane/crossplane-runtime/v2/pkg/errors" "github.com/crossplane/crossplane-runtime/v2/pkg/logging" + + _ "embed" ) +//go:embed help/top.md +var helpDetail string + const ( errKubeConfig = "failed to get kubeconfig" errCreateK8sClientset = "could not create the clientset for Kubernetes" @@ -57,21 +62,7 @@ type Cmd struct { // Help returns help instructions for the top command. func (c *Cmd) Help() string { - return ` -This command returns current resources utilization (CPU and Memory) by Crossplane pods. - -Similar to kubectl top pods, it requires Metrics Server to be correctly configured and working on the server. - -Examples: - # Show resources utilization for all Crossplane pods in the default 'crossplane-system' namespace in a tabular format. - crossplane cluster top - - # Show resources utilization for all Crossplane pods in a specified namespace in a tabular format. - crossplane cluster top -n - - # Add summary of resources utilization for all Crossplane pods in the default 'crossplane-system' on top of the results. - crossplane cluster top -s -` + return helpDetail } type topMetrics struct { diff --git a/cmd/crossplane/trace/help/trace.md b/cmd/crossplane/trace/help/trace.md new file mode 100644 index 0000000..cd97412 --- /dev/null +++ b/cmd/crossplane/trace/help/trace.md @@ -0,0 +1,116 @@ +The `resource trace` command traces a Crossplane resource (Claim, Composite, or +Managed Resource) to give a detailed view of its relationships — helpful for +troubleshooting. + +The command requires a resource type and a resource name: + +```shell +crossplane resource trace +``` + +Kubernetes-style `/` input works too — for example, `crossplane +resource trace example.crossplane.io/my-xr`. + +If needed the resource kind can be specified further as +`TYPE[.VERSION][.GROUP]`, for example `mykind.example.org` or +`mykind.v1alpha1.example.org`. + +By default, `crossplane resource trace` uses the Kubernetes configuration at +`~/.kube/config`. Override with the `KUBECONFIG` environment variable. + +## Output options + +By default, `trace` prints to the terminal as a tree, truncating the `Ready` and +`Status` messages to 64 characters. + +Change the format with `-o` (`--output`): `wide`, `json`, `yaml`, or `dot` (for +a [Graphviz](https://graphviz.org/docs/layouts/dot/) graph). + +### Wide output + +Use `--output=wide` to print the full `Ready` and `Status` messages even when +they exceed 64 characters, and additional per-kind columns (for example, +composed resource names for composite resources, or image used for packages). + +### Graphviz dot output + +Use `--output=dot` to print a textual [Graphviz +dot](https://graphviz.org/docs/layouts/dot/) graph. Pipe to `dot` to render an +image: + +```shell +crossplane resource trace cluster.aws.platformref.upbound.io platform-ref-aws -o dot | dot -Tpng -o graph.png +``` + +## Print connection secrets + +Use `--show-connection-secrets` to include connection-secret names alongside the +other resources. Secret values are never printed. Output includes the secret +name and namespace. + +## Print package dependencies + +The `--show-package-dependencies` flag controls how package dependencies are +displayed: + +- `unique` (default) — include each required package only once. +- `all` — show every package that requires the same dependency. +- `none` — hide all package dependencies. + +## Print package revisions + +The `--show-package-revisions` flag controls which package revisions are shown: + +- `active` (default) — show only the active revisions. +- `all` — show all revisions, including inactive ones. +- `none` — hide all revisions. + +## Examples + +Trace a `MyKind` resource named `my-res` in the namespace `my-ns`: + +```shell +crossplane resource trace mykind my-res -n my-ns +``` + +Trace all `MyKind` resources in the namespace `my-ns`: + +```shell +crossplane resource trace mykind -n my-ns +``` + +Wide format with full errors, condition messages, and kind-specific columns: + +```shell +crossplane resource trace mykind my-res -n my-ns -o wide +``` + +Show connection secret names alongside the resources: + +```shell +crossplane resource trace mykind my-res -n my-ns --show-connection-secrets +``` + +Output a Graphviz dot graph and pipe to dot to generate a PNG: + +```shell +crossplane resource trace mykind my-res -n my-ns -o dot | dot -Tpng -o output.png +``` + +Output all retrieved resources as JSON and pipe to jq for color: + +```shell +crossplane resource trace mykind my-res -n my-ns -o json | jq +``` + +Output debug logs to stderr while piping a dot graph to dot: + +```shell +crossplane resource trace mykind my-res -n my-ns -o dot --verbose | dot -Tpng -o output.png +``` + +Watch a resource continuously until it is deleted: + +```shell +crossplane resource trace mykind my-res -n my-ns --watch +``` diff --git a/cmd/crossplane/trace/trace.go b/cmd/crossplane/trace/trace.go index 526b314..313052b 100644 --- a/cmd/crossplane/trace/trace.go +++ b/cmd/crossplane/trace/trace.go @@ -41,8 +41,13 @@ import ( "github.com/crossplane/cli/v2/cmd/crossplane/common/resource/xrm" "github.com/crossplane/cli/v2/cmd/crossplane/internal" "github.com/crossplane/cli/v2/cmd/crossplane/trace/internal/printer" + + _ "embed" ) +//go:embed help/trace.md +var helpDetail string + const ( errGetResource = "cannot get requested resource" errFmtGetResource = "cannot get requested resource: kind=%s name=%s namespace=%s (verify context, namespace, and that the resource exists)" @@ -78,40 +83,7 @@ type Cmd struct { // Help returns help message for the trace command. func (c *Cmd) Help() string { - return ` -This command trace a Crossplane resource (Claim, Composite, or Managed Resource) -to get a detailed output of its relationships, helpful for troubleshooting. - -If needed the resource kind can be also specified further, -'TYPE[.VERSION][.GROUP]', e.g. mykind.example.org or -mykind.v1alpha1.example.org. - -Examples: - # Trace a MyKind resource (mykinds.example.org/v1alpha1) named 'my-res' in the namespace 'my-ns' - crossplane resource trace mykind my-res -n my-ns - - # Trace all MyKind resources (mykinds.example.org/v1alpha1) in the namespace 'my-ns' - crossplane resource trace mykind -n my-ns - - # Output wide format, showing full errors and condition messages, and other useful info - # depending on the target type, e.g. composed resources names for composite resources or image used for packages - crossplane resource trace mykind my-res -n my-ns -o wide - - # Show connection secrets in the output - crossplane resource trace mykind my-res -n my-ns --show-connection-secrets - - # Output a graph in dot format and pipe to dot to generate a png - crossplane resource trace mykind my-res -n my-ns -o dot | dot -Tpng -o output.png - - # Output all retrieved resources to json and pipe to jq to have it coloured - crossplane resource trace mykind my-res -n my-ns -o json | jq - - # Output debug logs to stderr while redirecting a dot formatted graph to dot - crossplane resource trace mykind my-res -n my-ns -o dot --verbose | dot -Tpng -o output.png - - # Watch a resource continuously until it is deleted - crossplane resource trace mykind my-res -n my-ns --watch -` + return helpDetail } func (c *Cmd) setupKubeClient(logger logging.Logger) (clientcmd.ClientConfig, client.WithWatch, meta.RESTMapper, error) { diff --git a/cmd/crossplane/validate/cmd.go b/cmd/crossplane/validate/cmd.go index a943ab0..1220bbb 100644 --- a/cmd/crossplane/validate/cmd.go +++ b/cmd/crossplane/validate/cmd.go @@ -32,8 +32,13 @@ import ( "github.com/crossplane/crossplane-runtime/v2/pkg/version" "github.com/crossplane/cli/v2/cmd/crossplane/common/load" + + _ "embed" ) +//go:embed help/validate.md +var helpDetail string + // Cmd arguments and flags for render subcommand. type Cmd struct { // Arguments. @@ -53,40 +58,7 @@ type Cmd struct { // Help prints out the help for the validate command. func (c *Cmd) Help() string { - return ` -This command validates the provided Crossplane resources against the schemas of the provided extensions like XRDs, -CRDs, providers, functions and configurations. The output of the "crossplane composition render" command can be -piped to this validate command in order to rapidly validate on the outputs of the composition development experience. - -If providers or configurations are provided as extensions, they will be downloaded and loaded as CRDs before performing -validation. If the cache directory is not provided, it will default to "~/.crossplane/cache". -Cache directory can be cleaned before downloading schemas by setting the "clean-cache" flag. - -All validation is performed offline locally using the Kubernetes API server's validation library, so it does not require -any Crossplane instance or control plane to be running or configured. - -Examples: - - # Validate all resources in the resources.yaml file against the extensions in the extensions.yaml file - crossplane resource validate extensions.yaml resources.yaml - - # Validate all resources in the resourceDir folder against the extensions in the crossplane.yaml file and extensionsDir folder - crossplane resource validate crossplane.yaml,extensionsDir/ resourceDir/ - - # Validate all resources in the resources.yaml file against the extensions in the extensions.yaml file using a specific Crossplane image version - crossplane resource validate extensions.yaml resources.yaml --crossplane-image=xpkg.crossplane.io/crossplane/crossplane:v1.20.0 - - # Validate all resources in the resourceDir folder against the extensions in the extensionsDir folder and skip - # success logs - crossplane resource validate extensionsDir/ resourceDir/ --skip-success-results - - # Validate the output of the render command against the extensions in the extensionsDir folder - crossplane composition render xr.yaml composition.yaml func.yaml --include-full-xr | crossplane resource validate extensionsDir/ - - - # Validate all resources in the resourceDir folder against the extensions in the extensionsDir folder using provided - # cache directory and clean the cache directory before downloading schemas - crossplane resource validate extensionsDir/ resourceDir/ --cache-dir .cache --clean-cache -` + return helpDetail } // AfterApply implements kong.AfterApply. diff --git a/cmd/crossplane/validate/help/validate.md b/cmd/crossplane/validate/help/validate.md new file mode 100644 index 0000000..739eef5 --- /dev/null +++ b/cmd/crossplane/validate/help/validate.md @@ -0,0 +1,148 @@ +The `resource validate` command validates the provided Crossplane resources +against the schemas of the provided extensions (XRDs, CRDs, Providers, +Functions, and Configurations). It uses the Kubernetes API server's validation +library plus additional checks (such as unknown-field detection, a common source +of difficult-to-debug Crossplane issues). + +If Providers or Configurations are provided as extensions, they are downloaded +and loaded as CRDs before validation. If `--cache-dir` is not set, it defaults +to `~/.crossplane/cache`. Clean the cache before downloading schemas with +`--clean-cache`. + +All validation is performed offline using the Kubernetes API server's validation +library — no Crossplane instance or control plane is required. + +`crossplane resource validate` supports validating: + +- A managed or composite resource against a Provider or XRD schema. +- The output of `crossplane composition render`. +- An XRD's [Common Expression + Language](https://kubernetes.io/docs/reference/using-api/cel/) (CEL) rules. +- Resources against a directory of schemas. + +## Validate resources against a schema + +When validating against a Provider, the command downloads the Provider package +to `--cache-dir`. Access to a Kubernetes cluster or Crossplane pod is not +required — only the ability to download the Provider package. + +Create a Provider manifest: + +```yaml +apiVersion: pkg.crossplane.io/v1 +kind: Provider +metadata: + name: crossplane-contrib-provider-aws-iam +spec: + package: xpkg.crossplane.io/crossplane-contrib/provider-aws-iam:v2.0.0 +``` + +Provide a managed resource to validate: + +```yaml +apiVersion: iam.aws.m.upbound.io/v1beta1 +kind: AccessKey +metadata: + namespace: default + name: sample-access-key-0 +spec: + forProvider: + userSelector: + matchLabels: + example-name: test-user-0 +``` + +Run validate with both files: + +```shell +crossplane resource validate provider.yaml managedResource.yaml +``` + +## Validate render output + +Pipe the output of `crossplane composition render` to `validate` to check +complete Crossplane resource pipelines, including XRs, Compositions, and +Functions. Use `--include-full-xr` on `render`, and `-` (read stdin) on +`validate`: + +```shell +crossplane composition render xr.yaml composition.yaml func.yaml --include-full-xr | \ + crossplane resource validate schemas.yaml - +``` + +## Validate CEL rules + +XRDs can define [validation +rules](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/#validation-rules) +in CEL via `x-kubernetes-validations`. `validate` evaluates them: + +```yaml +apiVersion: apiextensions.crossplane.io/v1 +kind: CompositeResourceDefinition +metadata: + name: myxrs.example.crossplane.io +spec: + # ... versions[].schema.openAPIV3Schema: + # spec: + # x-kubernetes-validations: + # - rule: "self.minReplicas <= self.replicas && self.replicas <= self.maxReplicas" + # message: "replicas should be in between minReplicas and maxReplicas." +``` + +## Validate against a directory of schemas + +`validate` can also take a directory of schema YAML files. Only `.yaml` and +`.yml` files are processed; other files are ignored. + +```text +schemas/ +├── platform-ref-aws.yaml +├── providers/ +│ └── provider-aws-iam.yaml +└── xrds/ + └── xrd.yaml +``` + +```shell +crossplane resource validate schemas/ resources.yaml +``` + +## Examples + +Validate resources against extensions in extensions.yaml: + +```shell +crossplane resource validate extensions.yaml resources.yaml +``` + +Validate resources in a directory against extensions in another directory: + +```shell +crossplane resource validate crossplane.yaml,extensionsDir/ resourceDir/ +``` + +Pin the Crossplane image version used during validation: + +```shell +crossplane resource validate extensions.yaml resources.yaml \ + --crossplane-image=xpkg.crossplane.io/crossplane/crossplane:v1.20.0 +``` + +Skip success log lines (only print problems): + +```shell +crossplane resource validate extensionsDir/ resourceDir/ --skip-success-results +``` + +Validate the output of render against extensions in a directory: + +```shell +crossplane composition render xr.yaml composition.yaml func.yaml --include-full-xr | \ + crossplane resource validate extensionsDir/ - +``` + +Use a custom cache directory and clean it before downloading schemas: + +```shell +crossplane resource validate extensionsDir/ resourceDir/ --cache-dir .cache --clean-cache +``` diff --git a/cmd/crossplane/xpkg/build.go b/cmd/crossplane/xpkg/build.go index dfdd9af..1e33556 100644 --- a/cmd/crossplane/xpkg/build.go +++ b/cmd/crossplane/xpkg/build.go @@ -34,8 +34,13 @@ import ( "github.com/crossplane/crossplane-runtime/v2/pkg/xpkg/parser" "github.com/crossplane/crossplane-runtime/v2/pkg/xpkg/parser/examples" "github.com/crossplane/crossplane-runtime/v2/pkg/xpkg/parser/yaml" + + _ "embed" ) +//go:embed help/build.md +var helpBuild string + const ( errGetNameFromMeta = "failed to get package name from crossplane.yaml" errBuildPackage = "failed to build package" @@ -108,19 +113,7 @@ type buildCmd struct { } func (c *buildCmd) Help() string { - return ` -This command builds a package file from a local directory of files. - -Examples: - - # Build a package from the files in the 'package' directory. - crossplane xpkg build --package-root=package/ - - # Build a package that embeds a Provider's controller OCI image built with - # 'docker build' so that the package can also be used to run the provider. - # Provider and Function packages support embedding runtime images. - crossplane xpkg build --embed-runtime-image=cc873e13cdc1 -` + return helpBuild } // GetRuntimeBaseImageOpts returns the controller base image options. diff --git a/cmd/crossplane/xpkg/help/build.md b/cmd/crossplane/xpkg/help/build.md new file mode 100644 index 0000000..e0abe57 --- /dev/null +++ b/cmd/crossplane/xpkg/help/build.md @@ -0,0 +1,65 @@ +The `xpkg build` command builds a package file from a local directory of +files. The CLI combines a directory of YAML files and packages them as an [OCI +container image](https://opencontainers.org/), applying the annotations and +values required by the [Crossplane XPKG +specification](https://github.com/crossplane/crossplane/blob/main/contributing/specifications/xpkg.md). + +`crossplane xpkg build` supports building Configuration, Function, and Provider +package types. + +The command recursively looks in `--package-root` for files ending in `.yml` or +`.yaml` and attempts to combine them into a package. All YAML files must be +valid Kubernetes manifests with `apiVersion`, `kind`, `metadata`, and `spec` +fields. + +## Ignore files + +Use `--ignore` to provide a comma-separated list of files and directories +(relative to `--package-root`) to skip. Wildcards are supported. Directories +themselves cannot be excluded. + +```shell +crossplane xpkg build --ignore="./test/*,kind-config.yaml" +``` + +## Set the package name + +By default the package is named from a combination of `metadata.name` and a hash +of the package contents, and written to `--package-root`. Override the location +and filename with `--package-file` (`-o`): + +```shell +crossplane xpkg build -o /home/crossplane/example.xpkg +``` + +## Include examples + +Include YAML files demonstrating how to use the package with `--examples-root` +(`-e`). Defaults to `./examples`. + +## Include a runtime image + +Function and Provider packages can embed a controller container image so that +the package can also be used to run the controller. Embedding is supported for +those package kinds only. + +> **Note:** Images referenced with `--embed-runtime-image` must be in the local +> Docker cache. Use `docker pull` to download a missing image. + +Use `--embed-runtime-image-tarball` to embed a local OCI image tarball instead +of an image from the Docker cache. + +## Examples + +Build a package from the files in the 'package' directory: + +```shell +crossplane xpkg build --package-root=package/ +``` + +Build a Provider package that embeds the controller OCI image so the package can +also run the provider. + +```shell +crossplane xpkg build --embed-runtime-image=cc873e13cdc1 +``` diff --git a/cmd/crossplane/xpkg/help/init.md b/cmd/crossplane/xpkg/help/init.md new file mode 100644 index 0000000..2a4a31b --- /dev/null +++ b/cmd/crossplane/xpkg/help/init.md @@ -0,0 +1,41 @@ +The `xpkg init` command initializes a directory that you can use to build a +package. It uses a template to initialize the directory, and can use any Git +repository as a template. + +Specify either a full Git URL or a well-known name as the template. The +following well-known template names are supported: + +%s + +## NOTES.txt + +If the template contains a `NOTES.txt` file in its root, its contents are +printed to stdout after the directory is initialized. Useful for instructions on +how to use the template. + +## init.sh + +If the template contains an `init.sh` file in its root, you are prompted to view +and/or run it. Useful for scripts that personalize the template. Pass `-r` +(`--run-init-script`) to run the script without prompting. + +## Examples + +Initialize a new Go Composition Function named function-example: + +```shell +crossplane xpkg init function-example function-template-go +``` + +Initialize a new Provider named provider-example from a custom template: + +```shell +crossplane xpkg init provider-example https://github.com/crossplane/provider-template-custom +``` + +Initialize a new Go Composition Function and run its init.sh script (if any) +without prompting or displaying its contents: + +```shell +crossplane xpkg init function-example function-template-go --run-init-script +``` diff --git a/cmd/crossplane/xpkg/help/install.md b/cmd/crossplane/xpkg/help/install.md new file mode 100644 index 0000000..292e753 --- /dev/null +++ b/cmd/crossplane/xpkg/help/install.md @@ -0,0 +1,60 @@ +The `xpkg install` command installs a package in a Crossplane control plane. It +uses `~/.kube/config` to connect to the control plane; override the path with +the `KUBECONFIG` environment variable. + +Specify the package kind, fully-qualified package OCI reference, and optionally +a name for the package inside Crossplane: + +```shell +crossplane xpkg install [] +``` + +The `` is one of `configuration`, `function`, or `provider`. + +> **Important:** The package reference must be fully qualified, including the +> registry, repository, and tag (e.g., registry.example.com/package:v1.0.0). + +## Wait for package install + +By default the command returns as soon as Crossplane accepts the package. It +does not wait for the download or install to complete. To inspect download or +installation problems, run `kubectl describe `. + +Use `--wait` (`-w`) to make the command wait for the package to become `HEALTHY` +before returning. The command returns an error if the wait time expires before +the package is healthy. + +## Require manual package activation + +Pass `-m` (`--manual-activation`) to set the package's +`revisionActivationPolicy` to `Manual`, which prevents automatic upgrades of the +package. + +## Authenticate to a private registry + +To authenticate to a private package registry use `--package-pull-secrets` with +a comma-separated list of Kubernetes Secret names. + +> **Important:** The secrets must be in the same namespace as the Crossplane +> pod. + +## Customize the number of stored package revisions + +By default Crossplane keeps only the active revision and one inactive revision +in the local package cache. Increase the number of stored revisions with `-r` +(`--revision-history-limit`). + +## Examples + +Wait 1 minute for the package to finish installing before returning: + +```shell +crossplane xpkg install provider xpkg.crossplane.io/crossplane-contrib/provider-aws-eks:v0.41.0 --wait=1m +``` + +Install a Function named function-eg using a custom runtime config: + +```shell +crossplane xpkg install function xpkg.crossplane.io/crossplane/function-example:v0.1.4 function-eg \ + --runtime-config=customconfig +``` diff --git a/cmd/crossplane/xpkg/help/push.md b/cmd/crossplane/xpkg/help/push.md new file mode 100644 index 0000000..0e04cc5 --- /dev/null +++ b/cmd/crossplane/xpkg/help/push.md @@ -0,0 +1,32 @@ +The `xpkg push` command pushes a Crossplane package file to any OCI registry. A +package's OCI tag must be a semantic version. Credentials for the registry are +retrieved from `docker` configuration; pushing to a private registry may require +a prior `docker login`. + +By default the command looks in the current directory for a single `.xpkg` file +to push. To push multiple files (e.g. a multi-platform package) or a specific +`.xpkg` file, use `-f` (`--package-files`). + +> **Important:** The destination must be fully qualified, including the +> registry, repository, and tag (e.g., registry.example.com/package:v1.0.0). + +## Examples + +Push a multi-platform package: + +```shell +crossplane xpkg push -f function-amd64.xpkg,function-arm64.xpkg \ + xpkg.crossplane.io/crossplane/function-example:v1.0.0 +``` + +Push the single xpkg file in the current directory: + +```shell +crossplane xpkg push xpkg.crossplane.io/crossplane/function-example:v1.0.0 +``` + +Push to Docker Hub: + +```shell +crossplane xpkg push docker.io/crossplane/function-example:v1.0.0 +``` diff --git a/cmd/crossplane/xpkg/help/update.md b/cmd/crossplane/xpkg/help/update.md new file mode 100644 index 0000000..6a9b060 --- /dev/null +++ b/cmd/crossplane/xpkg/help/update.md @@ -0,0 +1,27 @@ +The `xpkg update` command updates a package in a Crossplane control plane. It +uses `~/.kube/config` to connect to the control plane; override the path with +the `KUBECONFIG` environment variable. + +Specify the package kind, a new fully-qualified package OCI reference, and +optionally the name of the package already installed in Crossplane: + +```shell +crossplane xpkg update [] +``` + +> **Important:** The package reference must be fully qualified, including the +> registry, repository, and tag (e.g., registry.example.com/package:v1.0.0). + +## Examples + +Update the Function named function-eg to a new version: + +```shell +crossplane xpkg update function xpkg.crossplane.io/crossplane/function-example:v0.1.5 function-eg +``` + +Update to the latest patch version of a Provider: + +```shell +crossplane xpkg update provider xpkg.crossplane.io/crossplane-contrib/provider-aws-s3:v2.0.0 +``` diff --git a/cmd/crossplane/xpkg/help/xpkg.md b/cmd/crossplane/xpkg/help/xpkg.md new file mode 100644 index 0000000..b71f436 --- /dev/null +++ b/cmd/crossplane/xpkg/help/xpkg.md @@ -0,0 +1,11 @@ +Crossplane can be extended using packages. Crossplane packages are called +*xpkgs*. Crossplane supports Configuration, Provider, and Function packages. + +A package is an opinionated OCI image that contains everything needed to extend +a Crossplane control plane with new functionality. For example, installing a +Provider package extends Crossplane with support for new kinds of managed +resource (MR). + +See [the Crossplane packages +documentation](https://docs.crossplane.io/latest/concepts/packages) for more +information. diff --git a/cmd/crossplane/xpkg/init.go b/cmd/crossplane/xpkg/init.go index 5f4d675..d2ca280 100644 --- a/cmd/crossplane/xpkg/init.go +++ b/cmd/crossplane/xpkg/init.go @@ -34,8 +34,13 @@ import ( "github.com/crossplane/crossplane-runtime/v2/pkg/errors" "github.com/crossplane/crossplane-runtime/v2/pkg/logging" + + _ "embed" ) +//go:embed help/init.md +var helpInit string + const ( notes = "NOTES.txt" initScript = "init.sh" @@ -63,44 +68,12 @@ type initCmd struct { } func (c *initCmd) Help() string { - tpl := ` -This command initializes a directory that you can use to build a package. It -uses a template to initialize the directory. It can use any Git repository as a -template. - -You can specify either a full Git URL or a well-known name as a template. The -following well-known template names are supported: - -%s - -If the template contains NOTES.txt in its root directory, it will be -printed to stdout. This is useful for providing instructions for how -to use the template. - -If the template contains init.sh in its root directory, it will be optionally -printed out and executed. This is useful for providing a script that can be -used to initialize the package automatically. Use the -r flag to run the -script without prompting. - -Examples: - - # Initialize a new Go Composition Function named function-example. - crossplane xpkg init function-example function-template-go - - # Initialize a new Provider named provider-example from a custom template. - crossplane xpkg init provider-example https://github.com/crossplane/provider-template-custom - - # Initialize a new Go Composition Function named function-example and run - # its init.sh script (if it exists) without prompting the user or displaying its contents. - crossplane xpkg init function-example function-template-go --run-init-script -` - b := strings.Builder{} for name, url := range WellKnownTemplates() { - fmt.Fprintf(&b, " - %s (%s)\n", name, url) + fmt.Fprintf(&b, "- `%s` ([%s](%s))\n", name, url, url) } - return fmt.Sprintf(tpl, b.String()) + return fmt.Sprintf(helpInit, b.String()) } func (c *initCmd) Run(k *kong.Context, logger logging.Logger) error { diff --git a/cmd/crossplane/xpkg/install.go b/cmd/crossplane/xpkg/install.go index b67b193..dcced16 100644 --- a/cmd/crossplane/xpkg/install.go +++ b/cmd/crossplane/xpkg/install.go @@ -40,10 +40,14 @@ import ( v1 "github.com/crossplane/crossplane/apis/v2/pkg/v1" "github.com/crossplane/crossplane/apis/v2/pkg/v1beta1" + _ "embed" // Load all the auth plugins for the cloud providers. _ "k8s.io/client-go/plugin/pkg/client/auth" ) +//go:embed help/install.md +var helpInstall string + const ( errPkgIdentifier = "invalid package image identifier" errKubeConfig = "failed to get kubeconfig" @@ -66,23 +70,7 @@ type installCmd struct { } func (c *installCmd) Help() string { - return ` -This command installs a package in a Crossplane control plane. It uses -~/.kube/config to connect to the control plane. You can override this using the -KUBECONFIG environment variable. - -IMPORTANT: the package must be fully qualified, including the registry, repository, and tag. - -Examples: - - # Wait 1 minute for the package to finish installing before returning. - crossplane xpkg install provider xpkg.crossplane.io/crossplane-contrib/provider-aws-eks:v0.41.0 --wait=1m - - # Install a Function named function-eg that uses a runtime config named - # customconfig. - crossplane xpkg install function xpkg.crossplane.io/crossplane/function-example:v0.1.4 function-eg \ - --runtime-config=customconfig -` + return helpInstall } // Run the package install cmd. diff --git a/cmd/crossplane/xpkg/push.go b/cmd/crossplane/xpkg/push.go index 48eeffd..42b6ddb 100644 --- a/cmd/crossplane/xpkg/push.go +++ b/cmd/crossplane/xpkg/push.go @@ -37,8 +37,13 @@ import ( "github.com/crossplane/crossplane-runtime/v2/pkg/errors" "github.com/crossplane/crossplane-runtime/v2/pkg/logging" "github.com/crossplane/crossplane-runtime/v2/pkg/xpkg" + + _ "embed" ) +//go:embed help/push.md +var helpPush string + const ( errGetwd = "failed to get working directory while searching for package" errFindPackageinWd = "failed to find a package in current working directory" @@ -68,21 +73,7 @@ type pushCmd struct { } func (c *pushCmd) Help() string { - return ` -Packages can be pushed to any OCI registry. A package's OCI tag must be a semantic -version. Credentials for the registry are automatically retrieved from xpkg login -and dockers configuration as fallback. - -IMPORTANT: the package must be fully qualified, including the registry, repository, and tag. - -Examples: - - # Push a multi-platform package. - crossplane xpkg push -f function-amd64.xpkg,function-arm64.xpkg xpkg.crossplane.io/crossplane/function-example:v1.0.0 - - # Push the xpkg file in the current directory to a different registry. - crossplane xpkg push index.docker.io/crossplane/function-example:v1.0.0 -` + return helpPush } // AfterApply sets the tag for the parent push command. diff --git a/cmd/crossplane/xpkg/update.go b/cmd/crossplane/xpkg/update.go index f1ce7d7..25356a3 100644 --- a/cmd/crossplane/xpkg/update.go +++ b/cmd/crossplane/xpkg/update.go @@ -36,9 +36,13 @@ import ( v1 "github.com/crossplane/crossplane/apis/v2/pkg/v1" "github.com/crossplane/crossplane/apis/v2/pkg/v1beta1" + _ "embed" _ "k8s.io/client-go/plugin/pkg/client/auth" // Load all the auth plugins for the cloud providers. ) +//go:embed help/update.md +var helpUpdate string + // updateCmd updates a package. type updateCmd struct { // Arguments. @@ -48,18 +52,7 @@ type updateCmd struct { } func (c *updateCmd) Help() string { - return ` -This command updates a package in a Crossplane control plane. It uses -~/.kube/config to connect to the control plane. You can override this using the -KUBECONFIG environment variable. - -IMPORTANT: the package must be fully qualified, including the registry, repository, and tag. - -Examples: - - # Update the Function named function-eg - crossplane xpkg update function xpkg.crossplane.io/crossplane/function-example:v0.1.5 function-eg -` + return helpUpdate } // Run the package update cmd. diff --git a/cmd/crossplane/xpkg/xpkg.go b/cmd/crossplane/xpkg/xpkg.go index c12a4e7..35f6e38 100644 --- a/cmd/crossplane/xpkg/xpkg.go +++ b/cmd/crossplane/xpkg/xpkg.go @@ -17,6 +17,11 @@ limitations under the License. // Package xpkg contains Crossplane packaging commands. package xpkg +import _ "embed" + +//go:embed help/xpkg.md +var helpXpkg string + // TODO(lsviben) add the rest of the commands from up (batch, xpextract). // Cmd contains commands for interacting with xpkgs. @@ -33,15 +38,5 @@ type Cmd struct { // Help prints out the help for the xpkg command. func (c *Cmd) Help() string { - return ` -Crossplane can be extended using packages. Crossplane packages are called xpkgs. -Crossplane supports configuration, provider and function packages. - -A package is an opinionated OCI image that contains everything needed to extend -a Crossplane control plane with new functionality. For example installing a -provider package extends Crossplane with support for new kinds of managed -resource (MR). - -See https://docs.crossplane.io/latest/concepts/packages for more information. -` + return helpXpkg } diff --git a/go.mod b/go.mod index 4c133a4..bc80bcd 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,8 @@ require ( github.com/Masterminds/semver/v3 v3.4.0 github.com/alecthomas/kong v1.14.0 github.com/charmbracelet/bubbletea v1.3.10 + github.com/charmbracelet/glamour v1.0.0 + github.com/charmbracelet/x/term v0.2.2 github.com/containerd/errdefs v1.0.0 github.com/crossplane/crossplane-runtime/v2 v2.3.0-rc.0.0.20260504135302-a596e1f75635 github.com/crossplane/crossplane/apis/v2 v2.0.0-20260424160951-8f231230ebb6 @@ -19,6 +21,7 @@ require ( github.com/go-git/go-git/v5 v5.18.0 github.com/google/go-cmp v0.7.0 github.com/google/go-containerregistry v0.21.2 + github.com/muesli/termenv v0.16.0 github.com/pkg/errors v0.9.1 github.com/posener/complete v1.2.3 github.com/spf13/afero v1.15.0 @@ -55,6 +58,7 @@ require ( github.com/Azure/go-autorest/tracing v0.6.1 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/ProtonMail/go-crypto v1.1.6 // indirect + github.com/alecthomas/chroma/v2 v2.20.0 // indirect github.com/antlr4-go/antlr/v4 v4.13.1 // indirect github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect github.com/aws/aws-sdk-go-v2 v1.41.4 // indirect @@ -75,16 +79,17 @@ require ( github.com/aws/smithy-go v1.24.2 // indirect github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.12.0 // indirect github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect + github.com/aymerick/douceur v0.2.0 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/blang/semver v3.5.1+incompatible // indirect github.com/blang/semver/v4 v4.0.0 // indirect github.com/cenkalti/backoff/v5 v5.0.3 // indirect github.com/cespare/xxhash/v2 v2.3.0 // indirect github.com/charmbracelet/colorprofile v0.4.1 // indirect - github.com/charmbracelet/lipgloss v1.1.0 // indirect + github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834 // indirect github.com/charmbracelet/x/ansi v0.11.6 // indirect github.com/charmbracelet/x/cellbuf v0.0.15 // indirect - github.com/charmbracelet/x/term v0.2.2 // indirect + github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf // indirect github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 // indirect github.com/clipperhouse/displaywidth v0.9.0 // indirect github.com/clipperhouse/stringish v0.1.1 // indirect @@ -100,6 +105,7 @@ require ( github.com/digitorus/timestamp v0.0.0-20250524132541-c45532741eea // indirect github.com/dimchansky/utfbom v1.1.1 // indirect github.com/distribution/reference v0.6.0 // indirect + github.com/dlclark/regexp2 v1.11.5 // indirect github.com/docker/distribution v2.8.3+incompatible // indirect github.com/docker/docker-credential-helpers v0.9.5 // indirect github.com/docker/go-units v0.5.0 // indirect @@ -152,6 +158,7 @@ require ( github.com/google/go-containerregistry/pkg/authn/k8schain v0.0.0-20230919002926-dbcd01c402b2 // indirect github.com/google/go-containerregistry/pkg/authn/kubernetes v0.0.0-20250225234217-098045d5e61f // indirect github.com/google/uuid v1.6.0 // indirect + github.com/gorilla/css v1.0.1 // indirect github.com/grpc-ecosystem/grpc-gateway/v2 v2.28.0 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect @@ -172,6 +179,7 @@ require ( github.com/mattn/go-isatty v0.0.20 // indirect github.com/mattn/go-localereader v0.0.1 // indirect github.com/mattn/go-runewidth v0.0.19 // indirect + github.com/microcosm-cc/bluemonday v1.0.27 // indirect github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect github.com/moby/sys/sequential v0.6.0 // indirect @@ -180,7 +188,7 @@ require ( github.com/modern-go/reflect2 v1.0.3-0.20250322232337-35a7c28c31ee // indirect github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect github.com/muesli/cancelreader v0.2.2 // indirect - github.com/muesli/termenv v0.16.0 // indirect + github.com/muesli/reflow v0.3.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/nozzle/throttler v0.0.0-20180817012639-2ea982251481 // indirect github.com/oklog/ulid/v2 v2.1.1 // indirect @@ -222,6 +230,8 @@ require ( github.com/x448/float16 v0.8.4 // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect + github.com/yuin/goldmark v1.7.13 // indirect + github.com/yuin/goldmark-emoji v1.0.6 // indirect go.opentelemetry.io/auto/sdk v1.2.1 // indirect go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.64.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.67.0 // indirect diff --git a/go.sum b/go.sum index 5c8d72f..7dd9c7f 100644 --- a/go.sum +++ b/go.sum @@ -73,6 +73,8 @@ github.com/ProtonMail/go-crypto v1.1.6 h1:ZcV+Ropw6Qn0AX9brlQLAUXfqLBc7Bl+f/DmNx github.com/ProtonMail/go-crypto v1.1.6/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= +github.com/alecthomas/chroma/v2 v2.20.0 h1:sfIHpxPyR07/Oylvmcai3X/exDlE8+FA820NTz+9sGw= +github.com/alecthomas/chroma/v2 v2.20.0/go.mod h1:e7tViK0xh/Nf4BYHl00ycY6rV7b8iXBksI9E359yNmA= github.com/alecthomas/kong v1.14.0 h1:gFgEUZWu2ZmZ+UhyZ1bDhuutbKN1nTtJTwh19Wsn21s= github.com/alecthomas/kong v1.14.0/go.mod h1:wrlbXem1CWqUV5Vbmss5ISYhsVPkBb1Yo7YKJghju2I= github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs= @@ -127,6 +129,10 @@ github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.12.0 h1:JFWXO6QPihC github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.12.0/go.mod h1:046/oLyFlYdAghYQE2yHXi/E//VM5Cf3/dFmA+3CZ0c= github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= +github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= +github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= +github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= +github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ= @@ -143,12 +149,18 @@ github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlv github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4= github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk= github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk= -github.com/charmbracelet/lipgloss v1.1.0 h1:vYXsiLHVkK7fp74RkV7b2kq9+zDLoEU4MZoFqR/noCY= -github.com/charmbracelet/lipgloss v1.1.0/go.mod h1:/6Q8FR2o+kj8rz4Dq0zQc3vYf7X+B0binUUBwA0aL30= +github.com/charmbracelet/glamour v1.0.0 h1:AWMLOVFHTsysl4WV8T8QgkQ0s/ZNZo7CiE4WKhk8l08= +github.com/charmbracelet/glamour v1.0.0/go.mod h1:DSdohgOBkMr2ZQNhw4LZxSGpx3SvpeujNoXrQyH2hxo= +github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834 h1:ZR7e0ro+SZZiIZD7msJyA+NjkCNNavuiPBLgerbOziE= +github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834/go.mod h1:aKC/t2arECF6rNOnaKaVU6y4t4ZeHQzqfxedE/VkVhA= github.com/charmbracelet/x/ansi v0.11.6 h1:GhV21SiDz/45W9AnV2R61xZMRri5NlLnl6CVF7ihZW8= github.com/charmbracelet/x/ansi v0.11.6/go.mod h1:2JNYLgQUsyqaiLovhU2Rv/pb8r6ydXKS3NIttu3VGZQ= github.com/charmbracelet/x/cellbuf v0.0.15 h1:ur3pZy0o6z/R7EylET877CBxaiE1Sp1GMxoFPAIztPI= github.com/charmbracelet/x/cellbuf v0.0.15/go.mod h1:J1YVbR7MUuEGIFPCaaZ96KDl5NoS0DAWkskup+mOY+Q= +github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a h1:G99klV19u0QnhiizODirwVksQB91TJKV/UaTnACcG30= +github.com/charmbracelet/x/exp/golden v0.0.0-20240806155701-69247e0abc2a/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= +github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf h1:rLG0Yb6MQSDKdB52aGX55JT1oi0P0Kuaj7wi1bLUpnI= +github.com/charmbracelet/x/exp/slice v0.0.0-20250327172914-2fdc97757edf/go.mod h1:B3UgsnsBZS/eX42BlaNiJkD1pPOUa+oF1IYC6Yd2CEU= github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 h1:krfRl01rzPzxSxyLyrChD+U+MzsBXbm0OwYYB67uF+4= @@ -208,6 +220,8 @@ github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= +github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= +github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/docker/cli v29.4.0+incompatible h1:+IjXULMetlvWJiuSI0Nbor36lcJ5BTcVpUmB21KBoVM= github.com/docker/cli v29.4.0+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= @@ -392,6 +406,8 @@ github.com/googleapis/enterprise-certificate-proxy v0.3.14 h1:yh8ncqsbUY4shRD5dA github.com/googleapis/enterprise-certificate-proxy v0.3.14/go.mod h1:vqVt9yG9480NtzREnTlmGSBmFrA+bzb0yl0TxoBQXOg= github.com/googleapis/gax-go/v2 v2.19.0 h1:fYQaUOiGwll0cGj7jmHT/0nPlcrZDFPrZRhTsoCr8hE= github.com/googleapis/gax-go/v2 v2.19.0/go.mod h1:w2ROXVdfGEVFXzmlciUU4EdjHgWvB5h2n6x/8XSTTJA= +github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= +github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho= @@ -481,8 +497,11 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= +github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= +github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= +github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.1-0.20231216201459-8508981c8b6c h1:cqn374mizHuIWj+OSJCajGr/phAmuMug9qIX3l9CflE= @@ -507,6 +526,8 @@ github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= +github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= +github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= @@ -559,6 +580,8 @@ github.com/prometheus/common v0.67.5 h1:pIgK94WWlQt1WLwAC5j2ynLaBRDiinoAb86HZHTU github.com/prometheus/common v0.67.5/go.mod h1:SjE/0MzDEEAyrdr5Gqc6G+sXI67maCxzaT3A2+HqjUw= github.com/prometheus/procfs v0.19.2 h1:zUMhqEW66Ex7OXIiDkll3tl9a1ZdilUOd/F6ZXw4Vws= github.com/prometheus/procfs v0.19.2/go.mod h1:M0aotyiemPhBCM0z5w87kL22CxfcH05ZpYlu+b4J7mw= +github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab h1:ZjX6I48eZSFetPb41dHudEyVr5v953N15TsNZXlkcWY= @@ -670,6 +693,10 @@ github.com/ysmood/leakless v0.9.0 h1:qxCG5VirSBvmi3uynXFkcnLMzkphdh3xx5FtrORwDCU github.com/ysmood/leakless v0.9.0/go.mod h1:R8iAXPRaG97QJwqxs74RdwzcRHT1SWCGTNqY8q0JvMQ= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +github.com/yuin/goldmark v1.7.13 h1:GPddIs617DnBLFFVJFgpo1aBfe/4xcvMc3SB5t/D0pA= +github.com/yuin/goldmark v1.7.13/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= +github.com/yuin/goldmark-emoji v1.0.6 h1:QWfF2FYaXwL74tfGOW5izeiZepUDroDJfWubQI9HTHs= +github.com/yuin/goldmark-emoji v1.0.6/go.mod h1:ukxJDKFpdFb5x0a5HqbdlcKtebh086iJpI31LTKmWuA= github.com/zalando/go-keyring v0.2.3 h1:v9CUu9phlABObO4LPWycf+zwMG7nlbb3t/B5wa97yms= github.com/zalando/go-keyring v0.2.3/go.mod h1:HL4k+OXQfJUWaMnqyuSOc0drfGPX2b51Du6K+MRgZMk= go.etcd.io/etcd/api/v3 v3.6.8 h1:gqb1VN92TAI6G2FiBvWcqKtHiIjr4SU2GdXxTwyexbM= diff --git a/gomod2nix.toml b/gomod2nix.toml index f01ddbf..844fd86 100644 --- a/gomod2nix.toml +++ b/gomod2nix.toml @@ -1,5 +1,5 @@ schema = 3 -cachePackages = ["cel.dev/expr", "cloud.google.com/go/compute/metadata", "dario.cat/mergo", "github.com/Azure/azure-sdk-for-go/services/preview/containerregistry/runtime/2019-08-15-preview/containerregistry", "github.com/Azure/azure-sdk-for-go/version", "github.com/Azure/go-autorest/autorest", "github.com/Azure/go-autorest/autorest/adal", "github.com/Azure/go-autorest/autorest/azure", "github.com/Azure/go-autorest/autorest/azure/auth", "github.com/Azure/go-autorest/autorest/azure/cli", "github.com/Azure/go-autorest/autorest/date", "github.com/Azure/go-autorest/logger", "github.com/Azure/go-autorest/tracing", "github.com/Masterminds/semver/v3", "github.com/ProtonMail/go-crypto/bitcurves", "github.com/ProtonMail/go-crypto/brainpool", "github.com/ProtonMail/go-crypto/eax", "github.com/ProtonMail/go-crypto/ocb", "github.com/ProtonMail/go-crypto/openpgp", "github.com/ProtonMail/go-crypto/openpgp/aes/keywrap", "github.com/ProtonMail/go-crypto/openpgp/armor", "github.com/ProtonMail/go-crypto/openpgp/ecdh", "github.com/ProtonMail/go-crypto/openpgp/ecdsa", "github.com/ProtonMail/go-crypto/openpgp/ed25519", "github.com/ProtonMail/go-crypto/openpgp/ed448", "github.com/ProtonMail/go-crypto/openpgp/eddsa", "github.com/ProtonMail/go-crypto/openpgp/elgamal", "github.com/ProtonMail/go-crypto/openpgp/errors", "github.com/ProtonMail/go-crypto/openpgp/packet", "github.com/ProtonMail/go-crypto/openpgp/s2k", "github.com/ProtonMail/go-crypto/openpgp/x25519", "github.com/ProtonMail/go-crypto/openpgp/x448", "github.com/alecthomas/kong", "github.com/antlr4-go/antlr/v4", "github.com/asaskevich/govalidator", "github.com/aws/aws-sdk-go-v2/aws", "github.com/aws/aws-sdk-go-v2/aws/defaults", "github.com/aws/aws-sdk-go-v2/aws/middleware", "github.com/aws/aws-sdk-go-v2/aws/protocol/query", "github.com/aws/aws-sdk-go-v2/aws/protocol/restjson", "github.com/aws/aws-sdk-go-v2/aws/protocol/xml", "github.com/aws/aws-sdk-go-v2/aws/ratelimit", "github.com/aws/aws-sdk-go-v2/aws/retry", "github.com/aws/aws-sdk-go-v2/aws/signer/v4", "github.com/aws/aws-sdk-go-v2/aws/transport/http", "github.com/aws/aws-sdk-go-v2/config", "github.com/aws/aws-sdk-go-v2/credentials", "github.com/aws/aws-sdk-go-v2/credentials/ec2rolecreds", "github.com/aws/aws-sdk-go-v2/credentials/endpointcreds", "github.com/aws/aws-sdk-go-v2/credentials/logincreds", "github.com/aws/aws-sdk-go-v2/credentials/processcreds", "github.com/aws/aws-sdk-go-v2/credentials/ssocreds", "github.com/aws/aws-sdk-go-v2/credentials/stscreds", "github.com/aws/aws-sdk-go-v2/feature/ec2/imds", "github.com/aws/aws-sdk-go-v2/service/ecr", "github.com/aws/aws-sdk-go-v2/service/ecr/types", "github.com/aws/aws-sdk-go-v2/service/ecrpublic", "github.com/aws/aws-sdk-go-v2/service/ecrpublic/types", "github.com/aws/aws-sdk-go-v2/service/signin", "github.com/aws/aws-sdk-go-v2/service/signin/types", "github.com/aws/aws-sdk-go-v2/service/sso", "github.com/aws/aws-sdk-go-v2/service/sso/types", "github.com/aws/aws-sdk-go-v2/service/ssooidc", "github.com/aws/aws-sdk-go-v2/service/ssooidc/types", "github.com/aws/aws-sdk-go-v2/service/sts", "github.com/aws/aws-sdk-go-v2/service/sts/types", "github.com/aws/smithy-go", "github.com/aws/smithy-go/auth", "github.com/aws/smithy-go/auth/bearer", "github.com/aws/smithy-go/context", "github.com/aws/smithy-go/document", "github.com/aws/smithy-go/encoding", "github.com/aws/smithy-go/encoding/httpbinding", "github.com/aws/smithy-go/encoding/json", "github.com/aws/smithy-go/encoding/xml", "github.com/aws/smithy-go/endpoints", "github.com/aws/smithy-go/endpoints/private/rulesfn", "github.com/aws/smithy-go/io", "github.com/aws/smithy-go/logging", "github.com/aws/smithy-go/metrics", "github.com/aws/smithy-go/middleware", "github.com/aws/smithy-go/private/requestcompression", "github.com/aws/smithy-go/ptr", "github.com/aws/smithy-go/rand", "github.com/aws/smithy-go/time", "github.com/aws/smithy-go/tracing", "github.com/aws/smithy-go/transport/http", "github.com/aws/smithy-go/waiter", "github.com/awslabs/amazon-ecr-credential-helper/ecr-login", "github.com/awslabs/amazon-ecr-credential-helper/ecr-login/api", "github.com/awslabs/amazon-ecr-credential-helper/ecr-login/cache", "github.com/awslabs/amazon-ecr-credential-helper/ecr-login/config", "github.com/awslabs/amazon-ecr-credential-helper/ecr-login/version", "github.com/aymanbagabas/go-osc52/v2", "github.com/beorn7/perks/quantile", "github.com/blang/semver", "github.com/blang/semver/v4", "github.com/cenkalti/backoff/v5", "github.com/cespare/xxhash/v2", "github.com/charmbracelet/bubbletea", "github.com/charmbracelet/colorprofile", "github.com/charmbracelet/lipgloss", "github.com/charmbracelet/x/ansi", "github.com/charmbracelet/x/ansi/parser", "github.com/charmbracelet/x/cellbuf", "github.com/charmbracelet/x/term", "github.com/chrismellard/docker-credential-acr-env/pkg/credhelper", "github.com/chrismellard/docker-credential-acr-env/pkg/registry", "github.com/chrismellard/docker-credential-acr-env/pkg/token", "github.com/clipperhouse/displaywidth", "github.com/clipperhouse/stringish", "github.com/clipperhouse/uax29/v2/graphemes", "github.com/cloudflare/circl/dh/x25519", "github.com/cloudflare/circl/dh/x448", "github.com/cloudflare/circl/ecc/goldilocks", "github.com/cloudflare/circl/math", "github.com/cloudflare/circl/math/fp25519", "github.com/cloudflare/circl/math/fp448", "github.com/cloudflare/circl/math/mlsbset", "github.com/cloudflare/circl/sign", "github.com/cloudflare/circl/sign/ed25519", "github.com/cloudflare/circl/sign/ed448", "github.com/containerd/errdefs", "github.com/containerd/errdefs/pkg/errhttp", "github.com/containerd/stargz-snapshotter/estargz", "github.com/containerd/stargz-snapshotter/estargz/errorutil", "github.com/coreos/go-oidc/v3/oidc", "github.com/crossplane/crossplane-runtime/v2/pkg/errors", "github.com/crossplane/crossplane-runtime/v2/pkg/fieldpath", "github.com/crossplane/crossplane-runtime/v2/pkg/logging", "github.com/crossplane/crossplane-runtime/v2/pkg/meta", "github.com/crossplane/crossplane-runtime/v2/pkg/resource", "github.com/crossplane/crossplane-runtime/v2/pkg/resource/unstructured", "github.com/crossplane/crossplane-runtime/v2/pkg/resource/unstructured/claim", "github.com/crossplane/crossplane-runtime/v2/pkg/resource/unstructured/composed", "github.com/crossplane/crossplane-runtime/v2/pkg/resource/unstructured/composite", "github.com/crossplane/crossplane-runtime/v2/pkg/resource/unstructured/reference", "github.com/crossplane/crossplane-runtime/v2/pkg/test", "github.com/crossplane/crossplane-runtime/v2/pkg/version", "github.com/crossplane/crossplane-runtime/v2/pkg/xcrd", "github.com/crossplane/crossplane-runtime/v2/pkg/xpkg", "github.com/crossplane/crossplane-runtime/v2/pkg/xpkg/parser", "github.com/crossplane/crossplane-runtime/v2/pkg/xpkg/parser/examples", "github.com/crossplane/crossplane-runtime/v2/pkg/xpkg/parser/yaml", "github.com/crossplane/crossplane-runtime/v2/pkg/xpkg/signature", "github.com/crossplane/crossplane/apis/v2/apiextensions/v1", "github.com/crossplane/crossplane/apis/v2/apiextensions/v1alpha1", "github.com/crossplane/crossplane/apis/v2/apiextensions/v1beta1", "github.com/crossplane/crossplane/apis/v2/apiextensions/v2", "github.com/crossplane/crossplane/apis/v2/core/v2", "github.com/crossplane/crossplane/apis/v2/ops/v1alpha1", "github.com/crossplane/crossplane/apis/v2/pkg", "github.com/crossplane/crossplane/apis/v2/pkg/meta/v1", "github.com/crossplane/crossplane/apis/v2/pkg/meta/v1alpha1", "github.com/crossplane/crossplane/apis/v2/pkg/meta/v1beta1", "github.com/crossplane/crossplane/apis/v2/pkg/v1", "github.com/crossplane/crossplane/apis/v2/pkg/v1beta1", "github.com/crossplane/function-sdk-go/errors", "github.com/crossplane/function-sdk-go/proto/v1", "github.com/crossplane/function-sdk-go/resource", "github.com/crossplane/function-sdk-go/resource/composed", "github.com/crossplane/function-sdk-go/resource/composite", "github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer", "github.com/cyphar/filepath-securejoin", "github.com/davecgh/go-spew/spew", "github.com/digitorus/pkcs7", "github.com/digitorus/timestamp", "github.com/dimchansky/utfbom", "github.com/distribution/reference", "github.com/docker/cli/cli/config", "github.com/docker/cli/cli/config/configfile", "github.com/docker/cli/cli/config/credentials", "github.com/docker/cli/cli/config/memorystore", "github.com/docker/cli/cli/config/types", "github.com/docker/distribution/registry/client/auth/challenge", "github.com/docker/docker-credential-helpers/client", "github.com/docker/docker-credential-helpers/credentials", "github.com/docker/docker/api", "github.com/docker/docker/api/types", "github.com/docker/docker/api/types/blkiodev", "github.com/docker/docker/api/types/build", "github.com/docker/docker/api/types/checkpoint", "github.com/docker/docker/api/types/common", "github.com/docker/docker/api/types/container", "github.com/docker/docker/api/types/events", "github.com/docker/docker/api/types/filters", "github.com/docker/docker/api/types/image", "github.com/docker/docker/api/types/mount", "github.com/docker/docker/api/types/network", "github.com/docker/docker/api/types/registry", "github.com/docker/docker/api/types/storage", "github.com/docker/docker/api/types/strslice", "github.com/docker/docker/api/types/swarm", "github.com/docker/docker/api/types/swarm/runtime", "github.com/docker/docker/api/types/system", "github.com/docker/docker/api/types/time", "github.com/docker/docker/api/types/versions", "github.com/docker/docker/api/types/volume", "github.com/docker/docker/client", "github.com/docker/docker/pkg/stdcopy", "github.com/docker/go-connections/nat", "github.com/docker/go-connections/sockets", "github.com/docker/go-connections/tlsconfig", "github.com/docker/go-units", "github.com/dustin/go-humanize", "github.com/emicklei/dot", "github.com/emicklei/go-restful/v3", "github.com/emicklei/go-restful/v3/log", "github.com/emirpasic/gods/containers", "github.com/emirpasic/gods/lists", "github.com/emirpasic/gods/lists/arraylist", "github.com/emirpasic/gods/trees", "github.com/emirpasic/gods/trees/binaryheap", "github.com/emirpasic/gods/utils", "github.com/evanphx/json-patch/v5", "github.com/felixge/httpsnoop", "github.com/fsnotify/fsnotify", "github.com/fxamacker/cbor/v2", "github.com/go-chi/chi/v5", "github.com/go-chi/chi/v5/middleware", "github.com/go-git/gcfg", "github.com/go-git/gcfg/scanner", "github.com/go-git/gcfg/token", "github.com/go-git/gcfg/types", "github.com/go-git/go-billy/v5", "github.com/go-git/go-billy/v5/helper/chroot", "github.com/go-git/go-billy/v5/helper/polyfill", "github.com/go-git/go-billy/v5/osfs", "github.com/go-git/go-billy/v5/util", "github.com/go-git/go-git/v5", "github.com/go-git/go-git/v5/config", "github.com/go-git/go-git/v5/plumbing", "github.com/go-git/go-git/v5/plumbing/cache", "github.com/go-git/go-git/v5/plumbing/color", "github.com/go-git/go-git/v5/plumbing/filemode", "github.com/go-git/go-git/v5/plumbing/format/config", "github.com/go-git/go-git/v5/plumbing/format/diff", "github.com/go-git/go-git/v5/plumbing/format/gitignore", "github.com/go-git/go-git/v5/plumbing/format/idxfile", "github.com/go-git/go-git/v5/plumbing/format/index", "github.com/go-git/go-git/v5/plumbing/format/objfile", "github.com/go-git/go-git/v5/plumbing/format/packfile", "github.com/go-git/go-git/v5/plumbing/format/pktline", "github.com/go-git/go-git/v5/plumbing/hash", "github.com/go-git/go-git/v5/plumbing/object", "github.com/go-git/go-git/v5/plumbing/protocol/packp", "github.com/go-git/go-git/v5/plumbing/protocol/packp/capability", "github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband", "github.com/go-git/go-git/v5/plumbing/revlist", "github.com/go-git/go-git/v5/plumbing/storer", "github.com/go-git/go-git/v5/plumbing/transport", "github.com/go-git/go-git/v5/plumbing/transport/client", "github.com/go-git/go-git/v5/plumbing/transport/file", "github.com/go-git/go-git/v5/plumbing/transport/git", "github.com/go-git/go-git/v5/plumbing/transport/http", "github.com/go-git/go-git/v5/plumbing/transport/server", "github.com/go-git/go-git/v5/plumbing/transport/ssh", "github.com/go-git/go-git/v5/storage", "github.com/go-git/go-git/v5/storage/filesystem", "github.com/go-git/go-git/v5/storage/filesystem/dotgit", "github.com/go-git/go-git/v5/storage/memory", "github.com/go-git/go-git/v5/utils/binary", "github.com/go-git/go-git/v5/utils/diff", "github.com/go-git/go-git/v5/utils/ioutil", "github.com/go-git/go-git/v5/utils/merkletrie", "github.com/go-git/go-git/v5/utils/merkletrie/filesystem", "github.com/go-git/go-git/v5/utils/merkletrie/index", "github.com/go-git/go-git/v5/utils/merkletrie/noder", "github.com/go-git/go-git/v5/utils/sync", "github.com/go-git/go-git/v5/utils/trace", "github.com/go-jose/go-jose/v4", "github.com/go-jose/go-jose/v4/cipher", "github.com/go-jose/go-jose/v4/json", "github.com/go-json-experiment/json", "github.com/go-json-experiment/json/jsontext", "github.com/go-logr/logr", "github.com/go-logr/logr/funcr", "github.com/go-logr/logr/slogr", "github.com/go-logr/stdr", "github.com/go-logr/zapr", "github.com/go-openapi/analysis", "github.com/go-openapi/errors", "github.com/go-openapi/jsonpointer", "github.com/go-openapi/jsonreference", "github.com/go-openapi/loads", "github.com/go-openapi/runtime", "github.com/go-openapi/runtime/client", "github.com/go-openapi/runtime/logger", "github.com/go-openapi/runtime/middleware", "github.com/go-openapi/runtime/middleware/denco", "github.com/go-openapi/runtime/middleware/header", "github.com/go-openapi/runtime/middleware/untyped", "github.com/go-openapi/runtime/security", "github.com/go-openapi/runtime/yamlpc", "github.com/go-openapi/spec", "github.com/go-openapi/strfmt", "github.com/go-openapi/swag", "github.com/go-openapi/swag/cmdutils", "github.com/go-openapi/swag/conv", "github.com/go-openapi/swag/fileutils", "github.com/go-openapi/swag/jsonname", "github.com/go-openapi/swag/jsonutils", "github.com/go-openapi/swag/jsonutils/adapters", "github.com/go-openapi/swag/jsonutils/adapters/ifaces", "github.com/go-openapi/swag/jsonutils/adapters/stdlib/json", "github.com/go-openapi/swag/loading", "github.com/go-openapi/swag/mangling", "github.com/go-openapi/swag/netutils", "github.com/go-openapi/swag/stringutils", "github.com/go-openapi/swag/typeutils", "github.com/go-openapi/swag/yamlutils", "github.com/go-openapi/validate", "github.com/go-viper/mapstructure/v2", "github.com/golang-jwt/jwt/v4", "github.com/golang/groupcache/lru", "github.com/golang/snappy", "github.com/google/btree", "github.com/google/cel-go/cel", "github.com/google/cel-go/checker", "github.com/google/cel-go/checker/decls", "github.com/google/cel-go/common", "github.com/google/cel-go/common/ast", "github.com/google/cel-go/common/containers", "github.com/google/cel-go/common/debug", "github.com/google/cel-go/common/decls", "github.com/google/cel-go/common/env", "github.com/google/cel-go/common/functions", "github.com/google/cel-go/common/operators", "github.com/google/cel-go/common/overloads", "github.com/google/cel-go/common/runes", "github.com/google/cel-go/common/stdlib", "github.com/google/cel-go/common/types", "github.com/google/cel-go/common/types/pb", "github.com/google/cel-go/common/types/ref", "github.com/google/cel-go/common/types/traits", "github.com/google/cel-go/ext", "github.com/google/cel-go/interpreter", "github.com/google/cel-go/interpreter/functions", "github.com/google/cel-go/parser", "github.com/google/cel-go/parser/gen", "github.com/google/certificate-transparency-go", "github.com/google/certificate-transparency-go/asn1", "github.com/google/certificate-transparency-go/client", "github.com/google/certificate-transparency-go/client/configpb", "github.com/google/certificate-transparency-go/ctutil", "github.com/google/certificate-transparency-go/gossip/minimal/x509ext", "github.com/google/certificate-transparency-go/jsonclient", "github.com/google/certificate-transparency-go/loglist3", "github.com/google/certificate-transparency-go/tls", "github.com/google/certificate-transparency-go/x509", "github.com/google/certificate-transparency-go/x509/pkix", "github.com/google/certificate-transparency-go/x509util", "github.com/google/gnostic-models/compiler", "github.com/google/gnostic-models/extensions", "github.com/google/gnostic-models/jsonschema", "github.com/google/gnostic-models/openapiv2", "github.com/google/gnostic-models/openapiv3", "github.com/google/go-cmp/cmp", "github.com/google/go-cmp/cmp/cmpopts", "github.com/google/go-containerregistry/pkg/authn", "github.com/google/go-containerregistry/pkg/authn/k8schain", "github.com/google/go-containerregistry/pkg/authn/kubernetes", "github.com/google/go-containerregistry/pkg/compression", "github.com/google/go-containerregistry/pkg/crane", "github.com/google/go-containerregistry/pkg/legacy", "github.com/google/go-containerregistry/pkg/legacy/tarball", "github.com/google/go-containerregistry/pkg/logs", "github.com/google/go-containerregistry/pkg/name", "github.com/google/go-containerregistry/pkg/v1", "github.com/google/go-containerregistry/pkg/v1/daemon", "github.com/google/go-containerregistry/pkg/v1/empty", "github.com/google/go-containerregistry/pkg/v1/google", "github.com/google/go-containerregistry/pkg/v1/layout", "github.com/google/go-containerregistry/pkg/v1/match", "github.com/google/go-containerregistry/pkg/v1/mutate", "github.com/google/go-containerregistry/pkg/v1/partial", "github.com/google/go-containerregistry/pkg/v1/random", "github.com/google/go-containerregistry/pkg/v1/remote", "github.com/google/go-containerregistry/pkg/v1/remote/transport", "github.com/google/go-containerregistry/pkg/v1/static", "github.com/google/go-containerregistry/pkg/v1/stream", "github.com/google/go-containerregistry/pkg/v1/tarball", "github.com/google/go-containerregistry/pkg/v1/types", "github.com/google/uuid", "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options", "github.com/grpc-ecosystem/grpc-gateway/v2/runtime", "github.com/grpc-ecosystem/grpc-gateway/v2/utilities", "github.com/hashicorp/errwrap", "github.com/hashicorp/go-cleanhttp", "github.com/hashicorp/go-multierror", "github.com/hashicorp/go-retryablehttp", "github.com/in-toto/attestation/go/v1", "github.com/in-toto/in-toto-golang/in_toto", "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common", "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.1", "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2", "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v1", "github.com/jbenet/go-context/io", "github.com/jedisct1/go-minisign", "github.com/json-iterator/go", "github.com/kevinburke/ssh_config", "github.com/klauspost/compress", "github.com/klauspost/compress/fse", "github.com/klauspost/compress/huff0", "github.com/klauspost/compress/zstd", "github.com/letsencrypt/boulder/core", "github.com/letsencrypt/boulder/core/proto", "github.com/letsencrypt/boulder/goodkey", "github.com/letsencrypt/boulder/identifier", "github.com/letsencrypt/boulder/probs", "github.com/letsencrypt/boulder/revocation", "github.com/liggitt/tabwriter", "github.com/lucasb-eyer/go-colorful", "github.com/mattn/go-isatty", "github.com/mattn/go-runewidth", "github.com/mitchellh/go-homedir", "github.com/moby/docker-image-spec/specs-go/v1", "github.com/moby/term", "github.com/modern-go/concurrent", "github.com/modern-go/reflect2", "github.com/muesli/ansi", "github.com/muesli/ansi/compressor", "github.com/muesli/cancelreader", "github.com/muesli/termenv", "github.com/munnerz/goautoneg", "github.com/nozzle/throttler", "github.com/oklog/ulid/v2", "github.com/opencontainers/go-digest", "github.com/opencontainers/image-spec/specs-go", "github.com/opencontainers/image-spec/specs-go/v1", "github.com/pjbgf/sha1cd", "github.com/pjbgf/sha1cd/ubc", "github.com/pkg/browser", "github.com/pkg/errors", "github.com/pmezard/go-difflib/difflib", "github.com/posener/complete", "github.com/posener/complete/cmd", "github.com/posener/complete/cmd/install", "github.com/prometheus/client_golang/prometheus", "github.com/prometheus/client_golang/prometheus/collectors", "github.com/prometheus/client_golang/prometheus/promhttp", "github.com/prometheus/client_model/go", "github.com/prometheus/common/expfmt", "github.com/prometheus/common/model", "github.com/prometheus/procfs", "github.com/rivo/uniseg", "github.com/riywo/loginshell", "github.com/sassoftware/relic/lib/pkcs7", "github.com/sassoftware/relic/lib/x509tools", "github.com/secure-systems-lab/go-securesystemslib/cjson", "github.com/secure-systems-lab/go-securesystemslib/dsse", "github.com/secure-systems-lab/go-securesystemslib/encrypted", "github.com/secure-systems-lab/go-securesystemslib/signerverifier", "github.com/sergi/go-diff/diffmatchpatch", "github.com/shibumi/go-pathspec", "github.com/sigstore/cosign/v3/pkg/blob", "github.com/sigstore/cosign/v3/pkg/cosign", "github.com/sigstore/cosign/v3/pkg/cosign/attestation", "github.com/sigstore/cosign/v3/pkg/cosign/bundle", "github.com/sigstore/cosign/v3/pkg/cosign/env", "github.com/sigstore/cosign/v3/pkg/cosign/fulcioverifier/ctutil", "github.com/sigstore/cosign/v3/pkg/oci", "github.com/sigstore/cosign/v3/pkg/oci/empty", "github.com/sigstore/cosign/v3/pkg/oci/layout", "github.com/sigstore/cosign/v3/pkg/oci/remote", "github.com/sigstore/cosign/v3/pkg/oci/signed", "github.com/sigstore/cosign/v3/pkg/oci/static", "github.com/sigstore/cosign/v3/pkg/types", "github.com/sigstore/protobuf-specs/gen/pb-go/bundle/v1", "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1", "github.com/sigstore/protobuf-specs/gen/pb-go/dsse", "github.com/sigstore/protobuf-specs/gen/pb-go/rekor/v1", "github.com/sigstore/protobuf-specs/gen/pb-go/trustroot/v1", "github.com/sigstore/rekor-tiles/v2/pkg/client", "github.com/sigstore/rekor-tiles/v2/pkg/client/write", "github.com/sigstore/rekor-tiles/v2/pkg/generated/protobuf", "github.com/sigstore/rekor-tiles/v2/pkg/note", "github.com/sigstore/rekor-tiles/v2/pkg/types/verifier", "github.com/sigstore/rekor-tiles/v2/pkg/verify", "github.com/sigstore/rekor/pkg/client", "github.com/sigstore/rekor/pkg/generated/client", "github.com/sigstore/rekor/pkg/generated/client/entries", "github.com/sigstore/rekor/pkg/generated/client/index", "github.com/sigstore/rekor/pkg/generated/client/pubkey", "github.com/sigstore/rekor/pkg/generated/client/tlog", "github.com/sigstore/rekor/pkg/generated/models", "github.com/sigstore/rekor/pkg/log", "github.com/sigstore/rekor/pkg/pki", "github.com/sigstore/rekor/pkg/pki/identity", "github.com/sigstore/rekor/pkg/pki/minisign", "github.com/sigstore/rekor/pkg/pki/pgp", "github.com/sigstore/rekor/pkg/pki/pkcs7", "github.com/sigstore/rekor/pkg/pki/pkitypes", "github.com/sigstore/rekor/pkg/pki/ssh", "github.com/sigstore/rekor/pkg/pki/tuf", "github.com/sigstore/rekor/pkg/pki/x509", "github.com/sigstore/rekor/pkg/tle", "github.com/sigstore/rekor/pkg/types", "github.com/sigstore/rekor/pkg/types/dsse", "github.com/sigstore/rekor/pkg/types/dsse/v0.0.1", "github.com/sigstore/rekor/pkg/types/hashedrekord", "github.com/sigstore/rekor/pkg/types/hashedrekord/v0.0.1", "github.com/sigstore/rekor/pkg/types/intoto", "github.com/sigstore/rekor/pkg/types/intoto/v0.0.1", "github.com/sigstore/rekor/pkg/types/intoto/v0.0.2", "github.com/sigstore/rekor/pkg/types/rekord", "github.com/sigstore/rekor/pkg/types/rekord/v0.0.1", "github.com/sigstore/rekor/pkg/util", "github.com/sigstore/rekor/pkg/verify", "github.com/sigstore/sigstore-go/pkg/bundle", "github.com/sigstore/sigstore-go/pkg/fulcio/certificate", "github.com/sigstore/sigstore-go/pkg/root", "github.com/sigstore/sigstore-go/pkg/sign", "github.com/sigstore/sigstore-go/pkg/tlog", "github.com/sigstore/sigstore-go/pkg/tuf", "github.com/sigstore/sigstore-go/pkg/util", "github.com/sigstore/sigstore-go/pkg/verify", "github.com/sigstore/sigstore/pkg/cryptoutils", "github.com/sigstore/sigstore/pkg/cryptoutils/goodkey", "github.com/sigstore/sigstore/pkg/fulcioroots", "github.com/sigstore/sigstore/pkg/oauth", "github.com/sigstore/sigstore/pkg/oauthflow", "github.com/sigstore/sigstore/pkg/signature", "github.com/sigstore/sigstore/pkg/signature/dsse", "github.com/sigstore/sigstore/pkg/signature/options", "github.com/sigstore/sigstore/pkg/signature/payload", "github.com/sigstore/sigstore/pkg/tuf", "github.com/sigstore/timestamp-authority/v2/pkg/verification", "github.com/sirupsen/logrus", "github.com/skeema/knownhosts", "github.com/spf13/afero", "github.com/spf13/afero/mem", "github.com/spf13/cobra", "github.com/spf13/pflag", "github.com/syndtr/goleveldb/leveldb", "github.com/syndtr/goleveldb/leveldb/cache", "github.com/syndtr/goleveldb/leveldb/comparer", "github.com/syndtr/goleveldb/leveldb/errors", "github.com/syndtr/goleveldb/leveldb/filter", "github.com/syndtr/goleveldb/leveldb/iterator", "github.com/syndtr/goleveldb/leveldb/journal", "github.com/syndtr/goleveldb/leveldb/memdb", "github.com/syndtr/goleveldb/leveldb/opt", "github.com/syndtr/goleveldb/leveldb/storage", "github.com/syndtr/goleveldb/leveldb/table", "github.com/syndtr/goleveldb/leveldb/util", "github.com/theupdateframework/go-tuf", "github.com/theupdateframework/go-tuf/client", "github.com/theupdateframework/go-tuf/client/leveldbstore", "github.com/theupdateframework/go-tuf/data", "github.com/theupdateframework/go-tuf/pkg/keys", "github.com/theupdateframework/go-tuf/pkg/targets", "github.com/theupdateframework/go-tuf/sign", "github.com/theupdateframework/go-tuf/util", "github.com/theupdateframework/go-tuf/v2/metadata", "github.com/theupdateframework/go-tuf/v2/metadata/config", "github.com/theupdateframework/go-tuf/v2/metadata/fetcher", "github.com/theupdateframework/go-tuf/v2/metadata/trustedmetadata", "github.com/theupdateframework/go-tuf/v2/metadata/updater", "github.com/theupdateframework/go-tuf/verify", "github.com/titanous/rocacheck", "github.com/transparency-dev/formats/log", "github.com/transparency-dev/merkle", "github.com/transparency-dev/merkle/compact", "github.com/transparency-dev/merkle/proof", "github.com/transparency-dev/merkle/rfc6962", "github.com/vbatts/tar-split/archive/tar", "github.com/willabides/kongplete", "github.com/x448/float16", "github.com/xanzy/ssh-agent", "github.com/xo/terminfo", "go.opentelemetry.io/auto/sdk", "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp", "go.opentelemetry.io/otel", "go.opentelemetry.io/otel/attribute", "go.opentelemetry.io/otel/baggage", "go.opentelemetry.io/otel/codes", "go.opentelemetry.io/otel/metric", "go.opentelemetry.io/otel/metric/embedded", "go.opentelemetry.io/otel/metric/noop", "go.opentelemetry.io/otel/propagation", "go.opentelemetry.io/otel/semconv/v1.37.0", "go.opentelemetry.io/otel/semconv/v1.40.0", "go.opentelemetry.io/otel/semconv/v1.40.0/httpconv", "go.opentelemetry.io/otel/trace", "go.opentelemetry.io/otel/trace/embedded", "go.opentelemetry.io/otel/trace/noop", "go.uber.org/multierr", "go.uber.org/zap", "go.uber.org/zap/buffer", "go.uber.org/zap/zapcore", "go.yaml.in/yaml/v2", "go.yaml.in/yaml/v3", "golang.org/x/crypto/argon2", "golang.org/x/crypto/blake2b", "golang.org/x/crypto/blowfish", "golang.org/x/crypto/cast5", "golang.org/x/crypto/chacha20", "golang.org/x/crypto/cryptobyte", "golang.org/x/crypto/cryptobyte/asn1", "golang.org/x/crypto/curve25519", "golang.org/x/crypto/ed25519", "golang.org/x/crypto/hkdf", "golang.org/x/crypto/nacl/secretbox", "golang.org/x/crypto/ocsp", "golang.org/x/crypto/openpgp", "golang.org/x/crypto/openpgp/armor", "golang.org/x/crypto/openpgp/elgamal", "golang.org/x/crypto/openpgp/errors", "golang.org/x/crypto/openpgp/packet", "golang.org/x/crypto/openpgp/s2k", "golang.org/x/crypto/pbkdf2", "golang.org/x/crypto/pkcs12", "golang.org/x/crypto/salsa20/salsa", "golang.org/x/crypto/scrypt", "golang.org/x/crypto/sha3", "golang.org/x/crypto/ssh", "golang.org/x/crypto/ssh/agent", "golang.org/x/crypto/ssh/knownhosts", "golang.org/x/crypto/ssh/terminal", "golang.org/x/exp/slices", "golang.org/x/mod/semver", "golang.org/x/mod/sumdb/note", "golang.org/x/net/context", "golang.org/x/net/http/httpguts", "golang.org/x/net/http2", "golang.org/x/net/http2/hpack", "golang.org/x/net/idna", "golang.org/x/net/proxy", "golang.org/x/net/trace", "golang.org/x/oauth2", "golang.org/x/oauth2/authhandler", "golang.org/x/oauth2/google", "golang.org/x/oauth2/google/externalaccount", "golang.org/x/oauth2/jws", "golang.org/x/oauth2/jwt", "golang.org/x/sync/errgroup", "golang.org/x/sync/singleflight", "golang.org/x/sys/cpu", "golang.org/x/sys/execabs", "golang.org/x/sys/unix", "golang.org/x/term", "golang.org/x/text/feature/plural", "golang.org/x/text/language", "golang.org/x/text/message", "golang.org/x/text/message/catalog", "golang.org/x/text/runes", "golang.org/x/text/secure/bidirule", "golang.org/x/text/transform", "golang.org/x/text/unicode/bidi", "golang.org/x/text/unicode/norm", "golang.org/x/time/rate", "gomodules.xyz/jsonpatch/v2", "google.golang.org/genproto/googleapis/api", "google.golang.org/genproto/googleapis/api/annotations", "google.golang.org/genproto/googleapis/api/expr/v1alpha1", "google.golang.org/genproto/googleapis/api/httpbody", "google.golang.org/genproto/googleapis/rpc/status", "google.golang.org/grpc", "google.golang.org/grpc/attributes", "google.golang.org/grpc/backoff", "google.golang.org/grpc/balancer", "google.golang.org/grpc/balancer/base", "google.golang.org/grpc/balancer/endpointsharding", "google.golang.org/grpc/balancer/grpclb/state", "google.golang.org/grpc/balancer/pickfirst", "google.golang.org/grpc/balancer/roundrobin", "google.golang.org/grpc/binarylog/grpc_binarylog_v1", "google.golang.org/grpc/channelz", "google.golang.org/grpc/codes", "google.golang.org/grpc/connectivity", "google.golang.org/grpc/credentials", "google.golang.org/grpc/credentials/insecure", "google.golang.org/grpc/encoding", "google.golang.org/grpc/encoding/proto", "google.golang.org/grpc/experimental/stats", "google.golang.org/grpc/grpclog", "google.golang.org/grpc/health/grpc_health_v1", "google.golang.org/grpc/keepalive", "google.golang.org/grpc/mem", "google.golang.org/grpc/metadata", "google.golang.org/grpc/peer", "google.golang.org/grpc/resolver", "google.golang.org/grpc/resolver/dns", "google.golang.org/grpc/serviceconfig", "google.golang.org/grpc/stats", "google.golang.org/grpc/status", "google.golang.org/grpc/tap", "google.golang.org/protobuf/encoding/protodelim", "google.golang.org/protobuf/encoding/protojson", "google.golang.org/protobuf/encoding/prototext", "google.golang.org/protobuf/encoding/protowire", "google.golang.org/protobuf/proto", "google.golang.org/protobuf/protoadapt", "google.golang.org/protobuf/reflect/protodesc", "google.golang.org/protobuf/reflect/protoreflect", "google.golang.org/protobuf/reflect/protoregistry", "google.golang.org/protobuf/runtime/protoiface", "google.golang.org/protobuf/runtime/protoimpl", "google.golang.org/protobuf/testing/protocmp", "google.golang.org/protobuf/types/descriptorpb", "google.golang.org/protobuf/types/dynamicpb", "google.golang.org/protobuf/types/gofeaturespb", "google.golang.org/protobuf/types/known/anypb", "google.golang.org/protobuf/types/known/durationpb", "google.golang.org/protobuf/types/known/emptypb", "google.golang.org/protobuf/types/known/fieldmaskpb", "google.golang.org/protobuf/types/known/structpb", "google.golang.org/protobuf/types/known/timestamppb", "google.golang.org/protobuf/types/known/wrapperspb", "gopkg.in/evanphx/json-patch.v4", "gopkg.in/inf.v0", "gopkg.in/warnings.v0", "gopkg.in/yaml.v3", "k8s.io/api/admission/v1", "k8s.io/api/admission/v1beta1", "k8s.io/api/admissionregistration/v1", "k8s.io/api/admissionregistration/v1alpha1", "k8s.io/api/admissionregistration/v1beta1", "k8s.io/api/apidiscovery/v2", "k8s.io/api/apidiscovery/v2beta1", "k8s.io/api/apiserverinternal/v1alpha1", "k8s.io/api/apps/v1", "k8s.io/api/apps/v1beta1", "k8s.io/api/apps/v1beta2", "k8s.io/api/authentication/v1", "k8s.io/api/authentication/v1alpha1", "k8s.io/api/authentication/v1beta1", "k8s.io/api/authorization/v1", "k8s.io/api/authorization/v1beta1", "k8s.io/api/autoscaling/v1", "k8s.io/api/autoscaling/v2", "k8s.io/api/autoscaling/v2beta1", "k8s.io/api/autoscaling/v2beta2", "k8s.io/api/batch/v1", "k8s.io/api/batch/v1beta1", "k8s.io/api/certificates/v1", "k8s.io/api/certificates/v1alpha1", "k8s.io/api/certificates/v1beta1", "k8s.io/api/coordination/v1", "k8s.io/api/coordination/v1alpha2", "k8s.io/api/coordination/v1beta1", "k8s.io/api/core/v1", "k8s.io/api/discovery/v1", "k8s.io/api/discovery/v1beta1", "k8s.io/api/events/v1", "k8s.io/api/events/v1beta1", "k8s.io/api/extensions/v1beta1", "k8s.io/api/flowcontrol/v1", "k8s.io/api/flowcontrol/v1beta1", "k8s.io/api/flowcontrol/v1beta2", "k8s.io/api/flowcontrol/v1beta3", "k8s.io/api/networking/v1", "k8s.io/api/networking/v1beta1", "k8s.io/api/node/v1", "k8s.io/api/node/v1alpha1", "k8s.io/api/node/v1beta1", "k8s.io/api/policy/v1", "k8s.io/api/policy/v1beta1", "k8s.io/api/rbac/v1", "k8s.io/api/rbac/v1alpha1", "k8s.io/api/rbac/v1beta1", "k8s.io/api/resource/v1", "k8s.io/api/resource/v1alpha3", "k8s.io/api/resource/v1beta1", "k8s.io/api/resource/v1beta2", "k8s.io/api/scheduling/v1", "k8s.io/api/scheduling/v1alpha1", "k8s.io/api/scheduling/v1beta1", "k8s.io/api/storage/v1", "k8s.io/api/storage/v1alpha1", "k8s.io/api/storage/v1beta1", "k8s.io/api/storagemigration/v1beta1", "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions", "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1", "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1", "k8s.io/apiextensions-apiserver/pkg/apiserver/schema", "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel", "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/model", "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/defaulting", "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/objectmeta", "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/pruning", "k8s.io/apiextensions-apiserver/pkg/apiserver/validation", "k8s.io/apiextensions-apiserver/pkg/features", "k8s.io/apimachinery/pkg/api/equality", "k8s.io/apimachinery/pkg/api/errors", "k8s.io/apimachinery/pkg/api/meta", "k8s.io/apimachinery/pkg/api/meta/testrestmapper", "k8s.io/apimachinery/pkg/api/operation", "k8s.io/apimachinery/pkg/api/resource", "k8s.io/apimachinery/pkg/api/safe", "k8s.io/apimachinery/pkg/api/validate", "k8s.io/apimachinery/pkg/api/validate/constraints", "k8s.io/apimachinery/pkg/api/validate/content", "k8s.io/apimachinery/pkg/api/validation", "k8s.io/apimachinery/pkg/api/validation/path", "k8s.io/apimachinery/pkg/apis/meta/v1", "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured", "k8s.io/apimachinery/pkg/apis/meta/v1/validation", "k8s.io/apimachinery/pkg/apis/meta/v1beta1", "k8s.io/apimachinery/pkg/conversion", "k8s.io/apimachinery/pkg/conversion/queryparams", "k8s.io/apimachinery/pkg/fields", "k8s.io/apimachinery/pkg/labels", "k8s.io/apimachinery/pkg/runtime", "k8s.io/apimachinery/pkg/runtime/schema", "k8s.io/apimachinery/pkg/runtime/serializer", "k8s.io/apimachinery/pkg/runtime/serializer/cbor", "k8s.io/apimachinery/pkg/runtime/serializer/cbor/direct", "k8s.io/apimachinery/pkg/runtime/serializer/json", "k8s.io/apimachinery/pkg/runtime/serializer/protobuf", "k8s.io/apimachinery/pkg/runtime/serializer/recognizer", "k8s.io/apimachinery/pkg/runtime/serializer/streaming", "k8s.io/apimachinery/pkg/runtime/serializer/versioning", "k8s.io/apimachinery/pkg/selection", "k8s.io/apimachinery/pkg/types", "k8s.io/apimachinery/pkg/util/cache", "k8s.io/apimachinery/pkg/util/diff", "k8s.io/apimachinery/pkg/util/dump", "k8s.io/apimachinery/pkg/util/duration", "k8s.io/apimachinery/pkg/util/errors", "k8s.io/apimachinery/pkg/util/framer", "k8s.io/apimachinery/pkg/util/intstr", "k8s.io/apimachinery/pkg/util/json", "k8s.io/apimachinery/pkg/util/managedfields", "k8s.io/apimachinery/pkg/util/mergepatch", "k8s.io/apimachinery/pkg/util/naming", "k8s.io/apimachinery/pkg/util/net", "k8s.io/apimachinery/pkg/util/rand", "k8s.io/apimachinery/pkg/util/runtime", "k8s.io/apimachinery/pkg/util/sets", "k8s.io/apimachinery/pkg/util/strategicpatch", "k8s.io/apimachinery/pkg/util/uuid", "k8s.io/apimachinery/pkg/util/validation", "k8s.io/apimachinery/pkg/util/validation/field", "k8s.io/apimachinery/pkg/util/version", "k8s.io/apimachinery/pkg/util/wait", "k8s.io/apimachinery/pkg/util/yaml", "k8s.io/apimachinery/pkg/version", "k8s.io/apimachinery/pkg/watch", "k8s.io/apimachinery/third_party/forked/golang/json", "k8s.io/apimachinery/third_party/forked/golang/reflect", "k8s.io/apiserver/pkg/apis/cel", "k8s.io/apiserver/pkg/authentication/serviceaccount", "k8s.io/apiserver/pkg/authentication/user", "k8s.io/apiserver/pkg/authorization/authorizer", "k8s.io/apiserver/pkg/cel", "k8s.io/apiserver/pkg/cel/common", "k8s.io/apiserver/pkg/cel/environment", "k8s.io/apiserver/pkg/cel/library", "k8s.io/apiserver/pkg/cel/metrics", "k8s.io/apiserver/pkg/cel/openapi", "k8s.io/apiserver/pkg/features", "k8s.io/apiserver/pkg/util/compatibility", "k8s.io/apiserver/pkg/util/feature", "k8s.io/apiserver/pkg/warning", "k8s.io/cli-runtime/pkg/printers", "k8s.io/client-go/applyconfigurations/admissionregistration/v1", "k8s.io/client-go/applyconfigurations/admissionregistration/v1alpha1", "k8s.io/client-go/applyconfigurations/admissionregistration/v1beta1", "k8s.io/client-go/applyconfigurations/apiserverinternal/v1alpha1", "k8s.io/client-go/applyconfigurations/apps/v1", "k8s.io/client-go/applyconfigurations/apps/v1beta1", "k8s.io/client-go/applyconfigurations/apps/v1beta2", "k8s.io/client-go/applyconfigurations/autoscaling/v1", "k8s.io/client-go/applyconfigurations/autoscaling/v2", "k8s.io/client-go/applyconfigurations/autoscaling/v2beta1", "k8s.io/client-go/applyconfigurations/autoscaling/v2beta2", "k8s.io/client-go/applyconfigurations/batch/v1", "k8s.io/client-go/applyconfigurations/batch/v1beta1", "k8s.io/client-go/applyconfigurations/certificates/v1", "k8s.io/client-go/applyconfigurations/certificates/v1alpha1", "k8s.io/client-go/applyconfigurations/certificates/v1beta1", "k8s.io/client-go/applyconfigurations/coordination/v1", "k8s.io/client-go/applyconfigurations/coordination/v1alpha2", "k8s.io/client-go/applyconfigurations/coordination/v1beta1", "k8s.io/client-go/applyconfigurations/core/v1", "k8s.io/client-go/applyconfigurations/discovery/v1", "k8s.io/client-go/applyconfigurations/discovery/v1beta1", "k8s.io/client-go/applyconfigurations/events/v1", "k8s.io/client-go/applyconfigurations/events/v1beta1", "k8s.io/client-go/applyconfigurations/extensions/v1beta1", "k8s.io/client-go/applyconfigurations/flowcontrol/v1", "k8s.io/client-go/applyconfigurations/flowcontrol/v1beta1", "k8s.io/client-go/applyconfigurations/flowcontrol/v1beta2", "k8s.io/client-go/applyconfigurations/flowcontrol/v1beta3", "k8s.io/client-go/applyconfigurations/meta/v1", "k8s.io/client-go/applyconfigurations/networking/v1", "k8s.io/client-go/applyconfigurations/networking/v1beta1", "k8s.io/client-go/applyconfigurations/node/v1", "k8s.io/client-go/applyconfigurations/node/v1alpha1", "k8s.io/client-go/applyconfigurations/node/v1beta1", "k8s.io/client-go/applyconfigurations/policy/v1", "k8s.io/client-go/applyconfigurations/policy/v1beta1", "k8s.io/client-go/applyconfigurations/rbac/v1", "k8s.io/client-go/applyconfigurations/rbac/v1alpha1", "k8s.io/client-go/applyconfigurations/rbac/v1beta1", "k8s.io/client-go/applyconfigurations/resource/v1", "k8s.io/client-go/applyconfigurations/resource/v1alpha3", "k8s.io/client-go/applyconfigurations/resource/v1beta1", "k8s.io/client-go/applyconfigurations/resource/v1beta2", "k8s.io/client-go/applyconfigurations/scheduling/v1", "k8s.io/client-go/applyconfigurations/scheduling/v1alpha1", "k8s.io/client-go/applyconfigurations/scheduling/v1beta1", "k8s.io/client-go/applyconfigurations/storage/v1", "k8s.io/client-go/applyconfigurations/storage/v1alpha1", "k8s.io/client-go/applyconfigurations/storage/v1beta1", "k8s.io/client-go/applyconfigurations/storagemigration/v1beta1", "k8s.io/client-go/discovery", "k8s.io/client-go/discovery/cached/memory", "k8s.io/client-go/dynamic", "k8s.io/client-go/features", "k8s.io/client-go/gentype", "k8s.io/client-go/informers", "k8s.io/client-go/informers/admissionregistration", "k8s.io/client-go/informers/admissionregistration/v1", "k8s.io/client-go/informers/admissionregistration/v1alpha1", "k8s.io/client-go/informers/admissionregistration/v1beta1", "k8s.io/client-go/informers/apiserverinternal", "k8s.io/client-go/informers/apiserverinternal/v1alpha1", "k8s.io/client-go/informers/apps", "k8s.io/client-go/informers/apps/v1", "k8s.io/client-go/informers/apps/v1beta1", "k8s.io/client-go/informers/apps/v1beta2", "k8s.io/client-go/informers/autoscaling", "k8s.io/client-go/informers/autoscaling/v1", "k8s.io/client-go/informers/autoscaling/v2", "k8s.io/client-go/informers/autoscaling/v2beta1", "k8s.io/client-go/informers/autoscaling/v2beta2", "k8s.io/client-go/informers/batch", "k8s.io/client-go/informers/batch/v1", "k8s.io/client-go/informers/batch/v1beta1", "k8s.io/client-go/informers/certificates", "k8s.io/client-go/informers/certificates/v1", "k8s.io/client-go/informers/certificates/v1alpha1", "k8s.io/client-go/informers/certificates/v1beta1", "k8s.io/client-go/informers/coordination", "k8s.io/client-go/informers/coordination/v1", "k8s.io/client-go/informers/coordination/v1alpha2", "k8s.io/client-go/informers/coordination/v1beta1", "k8s.io/client-go/informers/core", "k8s.io/client-go/informers/core/v1", "k8s.io/client-go/informers/discovery", "k8s.io/client-go/informers/discovery/v1", "k8s.io/client-go/informers/discovery/v1beta1", "k8s.io/client-go/informers/events", "k8s.io/client-go/informers/events/v1", "k8s.io/client-go/informers/events/v1beta1", "k8s.io/client-go/informers/extensions", "k8s.io/client-go/informers/extensions/v1beta1", "k8s.io/client-go/informers/flowcontrol", "k8s.io/client-go/informers/flowcontrol/v1", "k8s.io/client-go/informers/flowcontrol/v1beta1", "k8s.io/client-go/informers/flowcontrol/v1beta2", "k8s.io/client-go/informers/flowcontrol/v1beta3", "k8s.io/client-go/informers/networking", "k8s.io/client-go/informers/networking/v1", "k8s.io/client-go/informers/networking/v1beta1", "k8s.io/client-go/informers/node", "k8s.io/client-go/informers/node/v1", "k8s.io/client-go/informers/node/v1alpha1", "k8s.io/client-go/informers/node/v1beta1", "k8s.io/client-go/informers/policy", "k8s.io/client-go/informers/policy/v1", "k8s.io/client-go/informers/policy/v1beta1", "k8s.io/client-go/informers/rbac", "k8s.io/client-go/informers/rbac/v1", "k8s.io/client-go/informers/rbac/v1alpha1", "k8s.io/client-go/informers/rbac/v1beta1", "k8s.io/client-go/informers/resource", "k8s.io/client-go/informers/resource/v1", "k8s.io/client-go/informers/resource/v1alpha3", "k8s.io/client-go/informers/resource/v1beta1", "k8s.io/client-go/informers/resource/v1beta2", "k8s.io/client-go/informers/scheduling", "k8s.io/client-go/informers/scheduling/v1", "k8s.io/client-go/informers/scheduling/v1alpha1", "k8s.io/client-go/informers/scheduling/v1beta1", "k8s.io/client-go/informers/storage", "k8s.io/client-go/informers/storage/v1", "k8s.io/client-go/informers/storage/v1alpha1", "k8s.io/client-go/informers/storage/v1beta1", "k8s.io/client-go/informers/storagemigration", "k8s.io/client-go/informers/storagemigration/v1beta1", "k8s.io/client-go/kubernetes", "k8s.io/client-go/kubernetes/scheme", "k8s.io/client-go/kubernetes/typed/admissionregistration/v1", "k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1", "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1", "k8s.io/client-go/kubernetes/typed/apiserverinternal/v1alpha1", "k8s.io/client-go/kubernetes/typed/apps/v1", "k8s.io/client-go/kubernetes/typed/apps/v1beta1", "k8s.io/client-go/kubernetes/typed/apps/v1beta2", "k8s.io/client-go/kubernetes/typed/authentication/v1", "k8s.io/client-go/kubernetes/typed/authentication/v1alpha1", "k8s.io/client-go/kubernetes/typed/authentication/v1beta1", "k8s.io/client-go/kubernetes/typed/authorization/v1", "k8s.io/client-go/kubernetes/typed/authorization/v1beta1", "k8s.io/client-go/kubernetes/typed/autoscaling/v1", "k8s.io/client-go/kubernetes/typed/autoscaling/v2", "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1", "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2", "k8s.io/client-go/kubernetes/typed/batch/v1", "k8s.io/client-go/kubernetes/typed/batch/v1beta1", "k8s.io/client-go/kubernetes/typed/certificates/v1", "k8s.io/client-go/kubernetes/typed/certificates/v1alpha1", "k8s.io/client-go/kubernetes/typed/certificates/v1beta1", "k8s.io/client-go/kubernetes/typed/coordination/v1", "k8s.io/client-go/kubernetes/typed/coordination/v1alpha2", "k8s.io/client-go/kubernetes/typed/coordination/v1beta1", "k8s.io/client-go/kubernetes/typed/core/v1", "k8s.io/client-go/kubernetes/typed/discovery/v1", "k8s.io/client-go/kubernetes/typed/discovery/v1beta1", "k8s.io/client-go/kubernetes/typed/events/v1", "k8s.io/client-go/kubernetes/typed/events/v1beta1", "k8s.io/client-go/kubernetes/typed/extensions/v1beta1", "k8s.io/client-go/kubernetes/typed/flowcontrol/v1", "k8s.io/client-go/kubernetes/typed/flowcontrol/v1beta1", "k8s.io/client-go/kubernetes/typed/flowcontrol/v1beta2", "k8s.io/client-go/kubernetes/typed/flowcontrol/v1beta3", "k8s.io/client-go/kubernetes/typed/networking/v1", "k8s.io/client-go/kubernetes/typed/networking/v1beta1", "k8s.io/client-go/kubernetes/typed/node/v1", "k8s.io/client-go/kubernetes/typed/node/v1alpha1", "k8s.io/client-go/kubernetes/typed/node/v1beta1", "k8s.io/client-go/kubernetes/typed/policy/v1", "k8s.io/client-go/kubernetes/typed/policy/v1beta1", "k8s.io/client-go/kubernetes/typed/rbac/v1", "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1", "k8s.io/client-go/kubernetes/typed/rbac/v1beta1", "k8s.io/client-go/kubernetes/typed/resource/v1", "k8s.io/client-go/kubernetes/typed/resource/v1alpha3", "k8s.io/client-go/kubernetes/typed/resource/v1beta1", "k8s.io/client-go/kubernetes/typed/resource/v1beta2", "k8s.io/client-go/kubernetes/typed/scheduling/v1", "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1", "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1", "k8s.io/client-go/kubernetes/typed/storage/v1", "k8s.io/client-go/kubernetes/typed/storage/v1alpha1", "k8s.io/client-go/kubernetes/typed/storage/v1beta1", "k8s.io/client-go/kubernetes/typed/storagemigration/v1beta1", "k8s.io/client-go/listers", "k8s.io/client-go/listers/admissionregistration/v1", "k8s.io/client-go/listers/admissionregistration/v1alpha1", "k8s.io/client-go/listers/admissionregistration/v1beta1", "k8s.io/client-go/listers/apiserverinternal/v1alpha1", "k8s.io/client-go/listers/apps/v1", "k8s.io/client-go/listers/apps/v1beta1", "k8s.io/client-go/listers/apps/v1beta2", "k8s.io/client-go/listers/autoscaling/v1", "k8s.io/client-go/listers/autoscaling/v2", "k8s.io/client-go/listers/autoscaling/v2beta1", "k8s.io/client-go/listers/autoscaling/v2beta2", "k8s.io/client-go/listers/batch/v1", "k8s.io/client-go/listers/batch/v1beta1", "k8s.io/client-go/listers/certificates/v1", "k8s.io/client-go/listers/certificates/v1alpha1", "k8s.io/client-go/listers/certificates/v1beta1", "k8s.io/client-go/listers/coordination/v1", "k8s.io/client-go/listers/coordination/v1alpha2", "k8s.io/client-go/listers/coordination/v1beta1", "k8s.io/client-go/listers/core/v1", "k8s.io/client-go/listers/discovery/v1", "k8s.io/client-go/listers/discovery/v1beta1", "k8s.io/client-go/listers/events/v1", "k8s.io/client-go/listers/events/v1beta1", "k8s.io/client-go/listers/extensions/v1beta1", "k8s.io/client-go/listers/flowcontrol/v1", "k8s.io/client-go/listers/flowcontrol/v1beta1", "k8s.io/client-go/listers/flowcontrol/v1beta2", "k8s.io/client-go/listers/flowcontrol/v1beta3", "k8s.io/client-go/listers/networking/v1", "k8s.io/client-go/listers/networking/v1beta1", "k8s.io/client-go/listers/node/v1", "k8s.io/client-go/listers/node/v1alpha1", "k8s.io/client-go/listers/node/v1beta1", "k8s.io/client-go/listers/policy/v1", "k8s.io/client-go/listers/policy/v1beta1", "k8s.io/client-go/listers/rbac/v1", "k8s.io/client-go/listers/rbac/v1alpha1", "k8s.io/client-go/listers/rbac/v1beta1", "k8s.io/client-go/listers/resource/v1", "k8s.io/client-go/listers/resource/v1alpha3", "k8s.io/client-go/listers/resource/v1beta1", "k8s.io/client-go/listers/resource/v1beta2", "k8s.io/client-go/listers/scheduling/v1", "k8s.io/client-go/listers/scheduling/v1alpha1", "k8s.io/client-go/listers/scheduling/v1beta1", "k8s.io/client-go/listers/storage/v1", "k8s.io/client-go/listers/storage/v1alpha1", "k8s.io/client-go/listers/storage/v1beta1", "k8s.io/client-go/listers/storagemigration/v1beta1", "k8s.io/client-go/metadata", "k8s.io/client-go/openapi", "k8s.io/client-go/openapi/cached", "k8s.io/client-go/pkg/apis/clientauthentication", "k8s.io/client-go/pkg/apis/clientauthentication/install", "k8s.io/client-go/pkg/apis/clientauthentication/v1", "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1", "k8s.io/client-go/pkg/version", "k8s.io/client-go/plugin/pkg/client/auth", "k8s.io/client-go/plugin/pkg/client/auth/azure", "k8s.io/client-go/plugin/pkg/client/auth/exec", "k8s.io/client-go/plugin/pkg/client/auth/gcp", "k8s.io/client-go/plugin/pkg/client/auth/oidc", "k8s.io/client-go/rest", "k8s.io/client-go/rest/watch", "k8s.io/client-go/restmapper", "k8s.io/client-go/testing", "k8s.io/client-go/third_party/forked/golang/template", "k8s.io/client-go/tools/auth", "k8s.io/client-go/tools/cache", "k8s.io/client-go/tools/cache/synctrack", "k8s.io/client-go/tools/clientcmd", "k8s.io/client-go/tools/clientcmd/api", "k8s.io/client-go/tools/clientcmd/api/latest", "k8s.io/client-go/tools/clientcmd/api/v1", "k8s.io/client-go/tools/events", "k8s.io/client-go/tools/leaderelection", "k8s.io/client-go/tools/leaderelection/resourcelock", "k8s.io/client-go/tools/metrics", "k8s.io/client-go/tools/pager", "k8s.io/client-go/tools/record", "k8s.io/client-go/tools/record/util", "k8s.io/client-go/tools/reference", "k8s.io/client-go/transport", "k8s.io/client-go/util/apply", "k8s.io/client-go/util/cert", "k8s.io/client-go/util/connrotation", "k8s.io/client-go/util/consistencydetector", "k8s.io/client-go/util/flowcontrol", "k8s.io/client-go/util/homedir", "k8s.io/client-go/util/jsonpath", "k8s.io/client-go/util/keyutil", "k8s.io/client-go/util/retry", "k8s.io/client-go/util/watchlist", "k8s.io/client-go/util/workqueue", "k8s.io/component-base/cli/flag", "k8s.io/component-base/compatibility", "k8s.io/component-base/featuregate", "k8s.io/component-base/metrics", "k8s.io/component-base/metrics/legacyregistry", "k8s.io/component-base/metrics/prometheus/compatversion", "k8s.io/component-base/metrics/prometheus/feature", "k8s.io/component-base/metrics/prometheusextension", "k8s.io/component-base/version", "k8s.io/component-base/zpages/features", "k8s.io/klog/v2", "k8s.io/kube-openapi/pkg/cached", "k8s.io/kube-openapi/pkg/common", "k8s.io/kube-openapi/pkg/handler3", "k8s.io/kube-openapi/pkg/schemaconv", "k8s.io/kube-openapi/pkg/spec3", "k8s.io/kube-openapi/pkg/util", "k8s.io/kube-openapi/pkg/util/proto", "k8s.io/kube-openapi/pkg/validation/errors", "k8s.io/kube-openapi/pkg/validation/spec", "k8s.io/kube-openapi/pkg/validation/strfmt", "k8s.io/kube-openapi/pkg/validation/strfmt/bson", "k8s.io/kube-openapi/pkg/validation/validate", "k8s.io/metrics/pkg/apis/metrics", "k8s.io/metrics/pkg/apis/metrics/v1alpha1", "k8s.io/metrics/pkg/apis/metrics/v1beta1", "k8s.io/metrics/pkg/client/clientset/versioned", "k8s.io/metrics/pkg/client/clientset/versioned/scheme", "k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1alpha1", "k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1", "k8s.io/utils/buffer", "k8s.io/utils/clock", "k8s.io/utils/lru", "k8s.io/utils/net", "k8s.io/utils/ptr", "k8s.io/utils/trace", "sigs.k8s.io/controller-runtime", "sigs.k8s.io/controller-runtime/pkg/builder", "sigs.k8s.io/controller-runtime/pkg/cache", "sigs.k8s.io/controller-runtime/pkg/certwatcher", "sigs.k8s.io/controller-runtime/pkg/certwatcher/metrics", "sigs.k8s.io/controller-runtime/pkg/client", "sigs.k8s.io/controller-runtime/pkg/client/apiutil", "sigs.k8s.io/controller-runtime/pkg/client/config", "sigs.k8s.io/controller-runtime/pkg/cluster", "sigs.k8s.io/controller-runtime/pkg/config", "sigs.k8s.io/controller-runtime/pkg/controller", "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil", "sigs.k8s.io/controller-runtime/pkg/controller/priorityqueue", "sigs.k8s.io/controller-runtime/pkg/conversion", "sigs.k8s.io/controller-runtime/pkg/event", "sigs.k8s.io/controller-runtime/pkg/handler", "sigs.k8s.io/controller-runtime/pkg/healthz", "sigs.k8s.io/controller-runtime/pkg/leaderelection", "sigs.k8s.io/controller-runtime/pkg/log", "sigs.k8s.io/controller-runtime/pkg/log/zap", "sigs.k8s.io/controller-runtime/pkg/manager", "sigs.k8s.io/controller-runtime/pkg/manager/signals", "sigs.k8s.io/controller-runtime/pkg/metrics", "sigs.k8s.io/controller-runtime/pkg/metrics/server", "sigs.k8s.io/controller-runtime/pkg/predicate", "sigs.k8s.io/controller-runtime/pkg/reconcile", "sigs.k8s.io/controller-runtime/pkg/recorder", "sigs.k8s.io/controller-runtime/pkg/scheme", "sigs.k8s.io/controller-runtime/pkg/source", "sigs.k8s.io/controller-runtime/pkg/webhook", "sigs.k8s.io/controller-runtime/pkg/webhook/admission", "sigs.k8s.io/controller-runtime/pkg/webhook/admission/metrics", "sigs.k8s.io/controller-runtime/pkg/webhook/conversion", "sigs.k8s.io/controller-runtime/pkg/webhook/conversion/metrics", "sigs.k8s.io/json", "sigs.k8s.io/randfill", "sigs.k8s.io/randfill/bytesource", "sigs.k8s.io/structured-merge-diff/v6/fieldpath", "sigs.k8s.io/structured-merge-diff/v6/merge", "sigs.k8s.io/structured-merge-diff/v6/schema", "sigs.k8s.io/structured-merge-diff/v6/typed", "sigs.k8s.io/structured-merge-diff/v6/value", "sigs.k8s.io/yaml", "sigs.k8s.io/yaml/kyaml"] +cachePackages = ["cel.dev/expr", "cloud.google.com/go/compute/metadata", "dario.cat/mergo", "github.com/Azure/azure-sdk-for-go/services/preview/containerregistry/runtime/2019-08-15-preview/containerregistry", "github.com/Azure/azure-sdk-for-go/version", "github.com/Azure/go-autorest/autorest", "github.com/Azure/go-autorest/autorest/adal", "github.com/Azure/go-autorest/autorest/azure", "github.com/Azure/go-autorest/autorest/azure/auth", "github.com/Azure/go-autorest/autorest/azure/cli", "github.com/Azure/go-autorest/autorest/date", "github.com/Azure/go-autorest/logger", "github.com/Azure/go-autorest/tracing", "github.com/Masterminds/semver/v3", "github.com/ProtonMail/go-crypto/bitcurves", "github.com/ProtonMail/go-crypto/brainpool", "github.com/ProtonMail/go-crypto/eax", "github.com/ProtonMail/go-crypto/ocb", "github.com/ProtonMail/go-crypto/openpgp", "github.com/ProtonMail/go-crypto/openpgp/aes/keywrap", "github.com/ProtonMail/go-crypto/openpgp/armor", "github.com/ProtonMail/go-crypto/openpgp/ecdh", "github.com/ProtonMail/go-crypto/openpgp/ecdsa", "github.com/ProtonMail/go-crypto/openpgp/ed25519", "github.com/ProtonMail/go-crypto/openpgp/ed448", "github.com/ProtonMail/go-crypto/openpgp/eddsa", "github.com/ProtonMail/go-crypto/openpgp/elgamal", "github.com/ProtonMail/go-crypto/openpgp/errors", "github.com/ProtonMail/go-crypto/openpgp/packet", "github.com/ProtonMail/go-crypto/openpgp/s2k", "github.com/ProtonMail/go-crypto/openpgp/x25519", "github.com/ProtonMail/go-crypto/openpgp/x448", "github.com/alecthomas/chroma/v2", "github.com/alecthomas/chroma/v2/formatters", "github.com/alecthomas/chroma/v2/formatters/html", "github.com/alecthomas/chroma/v2/formatters/svg", "github.com/alecthomas/chroma/v2/lexers", "github.com/alecthomas/chroma/v2/quick", "github.com/alecthomas/chroma/v2/styles", "github.com/alecthomas/kong", "github.com/antlr4-go/antlr/v4", "github.com/asaskevich/govalidator", "github.com/aws/aws-sdk-go-v2/aws", "github.com/aws/aws-sdk-go-v2/aws/defaults", "github.com/aws/aws-sdk-go-v2/aws/middleware", "github.com/aws/aws-sdk-go-v2/aws/protocol/query", "github.com/aws/aws-sdk-go-v2/aws/protocol/restjson", "github.com/aws/aws-sdk-go-v2/aws/protocol/xml", "github.com/aws/aws-sdk-go-v2/aws/ratelimit", "github.com/aws/aws-sdk-go-v2/aws/retry", "github.com/aws/aws-sdk-go-v2/aws/signer/v4", "github.com/aws/aws-sdk-go-v2/aws/transport/http", "github.com/aws/aws-sdk-go-v2/config", "github.com/aws/aws-sdk-go-v2/credentials", "github.com/aws/aws-sdk-go-v2/credentials/ec2rolecreds", "github.com/aws/aws-sdk-go-v2/credentials/endpointcreds", "github.com/aws/aws-sdk-go-v2/credentials/logincreds", "github.com/aws/aws-sdk-go-v2/credentials/processcreds", "github.com/aws/aws-sdk-go-v2/credentials/ssocreds", "github.com/aws/aws-sdk-go-v2/credentials/stscreds", "github.com/aws/aws-sdk-go-v2/feature/ec2/imds", "github.com/aws/aws-sdk-go-v2/service/ecr", "github.com/aws/aws-sdk-go-v2/service/ecr/types", "github.com/aws/aws-sdk-go-v2/service/ecrpublic", "github.com/aws/aws-sdk-go-v2/service/ecrpublic/types", "github.com/aws/aws-sdk-go-v2/service/signin", "github.com/aws/aws-sdk-go-v2/service/signin/types", "github.com/aws/aws-sdk-go-v2/service/sso", "github.com/aws/aws-sdk-go-v2/service/sso/types", "github.com/aws/aws-sdk-go-v2/service/ssooidc", "github.com/aws/aws-sdk-go-v2/service/ssooidc/types", "github.com/aws/aws-sdk-go-v2/service/sts", "github.com/aws/aws-sdk-go-v2/service/sts/types", "github.com/aws/smithy-go", "github.com/aws/smithy-go/auth", "github.com/aws/smithy-go/auth/bearer", "github.com/aws/smithy-go/context", "github.com/aws/smithy-go/document", "github.com/aws/smithy-go/encoding", "github.com/aws/smithy-go/encoding/httpbinding", "github.com/aws/smithy-go/encoding/json", "github.com/aws/smithy-go/encoding/xml", "github.com/aws/smithy-go/endpoints", "github.com/aws/smithy-go/endpoints/private/rulesfn", "github.com/aws/smithy-go/io", "github.com/aws/smithy-go/logging", "github.com/aws/smithy-go/metrics", "github.com/aws/smithy-go/middleware", "github.com/aws/smithy-go/private/requestcompression", "github.com/aws/smithy-go/ptr", "github.com/aws/smithy-go/rand", "github.com/aws/smithy-go/time", "github.com/aws/smithy-go/tracing", "github.com/aws/smithy-go/transport/http", "github.com/aws/smithy-go/waiter", "github.com/awslabs/amazon-ecr-credential-helper/ecr-login", "github.com/awslabs/amazon-ecr-credential-helper/ecr-login/api", "github.com/awslabs/amazon-ecr-credential-helper/ecr-login/cache", "github.com/awslabs/amazon-ecr-credential-helper/ecr-login/config", "github.com/awslabs/amazon-ecr-credential-helper/ecr-login/version", "github.com/aymanbagabas/go-osc52/v2", "github.com/aymerick/douceur/css", "github.com/aymerick/douceur/parser", "github.com/beorn7/perks/quantile", "github.com/blang/semver", "github.com/blang/semver/v4", "github.com/cenkalti/backoff/v5", "github.com/cespare/xxhash/v2", "github.com/charmbracelet/bubbletea", "github.com/charmbracelet/colorprofile", "github.com/charmbracelet/glamour", "github.com/charmbracelet/glamour/ansi", "github.com/charmbracelet/glamour/styles", "github.com/charmbracelet/lipgloss", "github.com/charmbracelet/lipgloss/table", "github.com/charmbracelet/x/ansi", "github.com/charmbracelet/x/ansi/parser", "github.com/charmbracelet/x/cellbuf", "github.com/charmbracelet/x/exp/slice", "github.com/charmbracelet/x/term", "github.com/chrismellard/docker-credential-acr-env/pkg/credhelper", "github.com/chrismellard/docker-credential-acr-env/pkg/registry", "github.com/chrismellard/docker-credential-acr-env/pkg/token", "github.com/clipperhouse/displaywidth", "github.com/clipperhouse/stringish", "github.com/clipperhouse/uax29/v2/graphemes", "github.com/cloudflare/circl/dh/x25519", "github.com/cloudflare/circl/dh/x448", "github.com/cloudflare/circl/ecc/goldilocks", "github.com/cloudflare/circl/math", "github.com/cloudflare/circl/math/fp25519", "github.com/cloudflare/circl/math/fp448", "github.com/cloudflare/circl/math/mlsbset", "github.com/cloudflare/circl/sign", "github.com/cloudflare/circl/sign/ed25519", "github.com/cloudflare/circl/sign/ed448", "github.com/containerd/errdefs", "github.com/containerd/errdefs/pkg/errhttp", "github.com/containerd/stargz-snapshotter/estargz", "github.com/containerd/stargz-snapshotter/estargz/errorutil", "github.com/coreos/go-oidc/v3/oidc", "github.com/crossplane/crossplane-runtime/v2/pkg/errors", "github.com/crossplane/crossplane-runtime/v2/pkg/fieldpath", "github.com/crossplane/crossplane-runtime/v2/pkg/logging", "github.com/crossplane/crossplane-runtime/v2/pkg/meta", "github.com/crossplane/crossplane-runtime/v2/pkg/resource", "github.com/crossplane/crossplane-runtime/v2/pkg/resource/unstructured", "github.com/crossplane/crossplane-runtime/v2/pkg/resource/unstructured/claim", "github.com/crossplane/crossplane-runtime/v2/pkg/resource/unstructured/composed", "github.com/crossplane/crossplane-runtime/v2/pkg/resource/unstructured/composite", "github.com/crossplane/crossplane-runtime/v2/pkg/resource/unstructured/reference", "github.com/crossplane/crossplane-runtime/v2/pkg/test", "github.com/crossplane/crossplane-runtime/v2/pkg/version", "github.com/crossplane/crossplane-runtime/v2/pkg/xcrd", "github.com/crossplane/crossplane-runtime/v2/pkg/xpkg", "github.com/crossplane/crossplane-runtime/v2/pkg/xpkg/parser", "github.com/crossplane/crossplane-runtime/v2/pkg/xpkg/parser/examples", "github.com/crossplane/crossplane-runtime/v2/pkg/xpkg/parser/yaml", "github.com/crossplane/crossplane-runtime/v2/pkg/xpkg/signature", "github.com/crossplane/crossplane/apis/v2/apiextensions/v1", "github.com/crossplane/crossplane/apis/v2/apiextensions/v1alpha1", "github.com/crossplane/crossplane/apis/v2/apiextensions/v1beta1", "github.com/crossplane/crossplane/apis/v2/apiextensions/v2", "github.com/crossplane/crossplane/apis/v2/core/v2", "github.com/crossplane/crossplane/apis/v2/ops/v1alpha1", "github.com/crossplane/crossplane/apis/v2/pkg", "github.com/crossplane/crossplane/apis/v2/pkg/meta/v1", "github.com/crossplane/crossplane/apis/v2/pkg/meta/v1alpha1", "github.com/crossplane/crossplane/apis/v2/pkg/meta/v1beta1", "github.com/crossplane/crossplane/apis/v2/pkg/v1", "github.com/crossplane/crossplane/apis/v2/pkg/v1beta1", "github.com/crossplane/function-sdk-go/errors", "github.com/crossplane/function-sdk-go/proto/v1", "github.com/crossplane/function-sdk-go/resource", "github.com/crossplane/function-sdk-go/resource/composed", "github.com/crossplane/function-sdk-go/resource/composite", "github.com/cyberphone/json-canonicalization/go/src/webpki.org/jsoncanonicalizer", "github.com/cyphar/filepath-securejoin", "github.com/davecgh/go-spew/spew", "github.com/digitorus/pkcs7", "github.com/digitorus/timestamp", "github.com/dimchansky/utfbom", "github.com/distribution/reference", "github.com/dlclark/regexp2", "github.com/dlclark/regexp2/syntax", "github.com/docker/cli/cli/config", "github.com/docker/cli/cli/config/configfile", "github.com/docker/cli/cli/config/credentials", "github.com/docker/cli/cli/config/memorystore", "github.com/docker/cli/cli/config/types", "github.com/docker/distribution/registry/client/auth/challenge", "github.com/docker/docker-credential-helpers/client", "github.com/docker/docker-credential-helpers/credentials", "github.com/docker/docker/api", "github.com/docker/docker/api/types", "github.com/docker/docker/api/types/blkiodev", "github.com/docker/docker/api/types/build", "github.com/docker/docker/api/types/checkpoint", "github.com/docker/docker/api/types/common", "github.com/docker/docker/api/types/container", "github.com/docker/docker/api/types/events", "github.com/docker/docker/api/types/filters", "github.com/docker/docker/api/types/image", "github.com/docker/docker/api/types/mount", "github.com/docker/docker/api/types/network", "github.com/docker/docker/api/types/registry", "github.com/docker/docker/api/types/storage", "github.com/docker/docker/api/types/strslice", "github.com/docker/docker/api/types/swarm", "github.com/docker/docker/api/types/swarm/runtime", "github.com/docker/docker/api/types/system", "github.com/docker/docker/api/types/time", "github.com/docker/docker/api/types/versions", "github.com/docker/docker/api/types/volume", "github.com/docker/docker/client", "github.com/docker/docker/pkg/stdcopy", "github.com/docker/go-connections/nat", "github.com/docker/go-connections/sockets", "github.com/docker/go-connections/tlsconfig", "github.com/docker/go-units", "github.com/dustin/go-humanize", "github.com/emicklei/dot", "github.com/emicklei/go-restful/v3", "github.com/emicklei/go-restful/v3/log", "github.com/emirpasic/gods/containers", "github.com/emirpasic/gods/lists", "github.com/emirpasic/gods/lists/arraylist", "github.com/emirpasic/gods/trees", "github.com/emirpasic/gods/trees/binaryheap", "github.com/emirpasic/gods/utils", "github.com/evanphx/json-patch/v5", "github.com/felixge/httpsnoop", "github.com/fsnotify/fsnotify", "github.com/fxamacker/cbor/v2", "github.com/go-chi/chi/v5", "github.com/go-chi/chi/v5/middleware", "github.com/go-git/gcfg", "github.com/go-git/gcfg/scanner", "github.com/go-git/gcfg/token", "github.com/go-git/gcfg/types", "github.com/go-git/go-billy/v5", "github.com/go-git/go-billy/v5/helper/chroot", "github.com/go-git/go-billy/v5/helper/polyfill", "github.com/go-git/go-billy/v5/osfs", "github.com/go-git/go-billy/v5/util", "github.com/go-git/go-git/v5", "github.com/go-git/go-git/v5/config", "github.com/go-git/go-git/v5/plumbing", "github.com/go-git/go-git/v5/plumbing/cache", "github.com/go-git/go-git/v5/plumbing/color", "github.com/go-git/go-git/v5/plumbing/filemode", "github.com/go-git/go-git/v5/plumbing/format/config", "github.com/go-git/go-git/v5/plumbing/format/diff", "github.com/go-git/go-git/v5/plumbing/format/gitignore", "github.com/go-git/go-git/v5/plumbing/format/idxfile", "github.com/go-git/go-git/v5/plumbing/format/index", "github.com/go-git/go-git/v5/plumbing/format/objfile", "github.com/go-git/go-git/v5/plumbing/format/packfile", "github.com/go-git/go-git/v5/plumbing/format/pktline", "github.com/go-git/go-git/v5/plumbing/hash", "github.com/go-git/go-git/v5/plumbing/object", "github.com/go-git/go-git/v5/plumbing/protocol/packp", "github.com/go-git/go-git/v5/plumbing/protocol/packp/capability", "github.com/go-git/go-git/v5/plumbing/protocol/packp/sideband", "github.com/go-git/go-git/v5/plumbing/revlist", "github.com/go-git/go-git/v5/plumbing/storer", "github.com/go-git/go-git/v5/plumbing/transport", "github.com/go-git/go-git/v5/plumbing/transport/client", "github.com/go-git/go-git/v5/plumbing/transport/file", "github.com/go-git/go-git/v5/plumbing/transport/git", "github.com/go-git/go-git/v5/plumbing/transport/http", "github.com/go-git/go-git/v5/plumbing/transport/server", "github.com/go-git/go-git/v5/plumbing/transport/ssh", "github.com/go-git/go-git/v5/storage", "github.com/go-git/go-git/v5/storage/filesystem", "github.com/go-git/go-git/v5/storage/filesystem/dotgit", "github.com/go-git/go-git/v5/storage/memory", "github.com/go-git/go-git/v5/utils/binary", "github.com/go-git/go-git/v5/utils/diff", "github.com/go-git/go-git/v5/utils/ioutil", "github.com/go-git/go-git/v5/utils/merkletrie", "github.com/go-git/go-git/v5/utils/merkletrie/filesystem", "github.com/go-git/go-git/v5/utils/merkletrie/index", "github.com/go-git/go-git/v5/utils/merkletrie/noder", "github.com/go-git/go-git/v5/utils/sync", "github.com/go-git/go-git/v5/utils/trace", "github.com/go-jose/go-jose/v4", "github.com/go-jose/go-jose/v4/cipher", "github.com/go-jose/go-jose/v4/json", "github.com/go-json-experiment/json", "github.com/go-json-experiment/json/jsontext", "github.com/go-logr/logr", "github.com/go-logr/logr/funcr", "github.com/go-logr/logr/slogr", "github.com/go-logr/stdr", "github.com/go-logr/zapr", "github.com/go-openapi/analysis", "github.com/go-openapi/errors", "github.com/go-openapi/jsonpointer", "github.com/go-openapi/jsonreference", "github.com/go-openapi/loads", "github.com/go-openapi/runtime", "github.com/go-openapi/runtime/client", "github.com/go-openapi/runtime/logger", "github.com/go-openapi/runtime/middleware", "github.com/go-openapi/runtime/middleware/denco", "github.com/go-openapi/runtime/middleware/header", "github.com/go-openapi/runtime/middleware/untyped", "github.com/go-openapi/runtime/security", "github.com/go-openapi/runtime/yamlpc", "github.com/go-openapi/spec", "github.com/go-openapi/strfmt", "github.com/go-openapi/swag", "github.com/go-openapi/swag/cmdutils", "github.com/go-openapi/swag/conv", "github.com/go-openapi/swag/fileutils", "github.com/go-openapi/swag/jsonname", "github.com/go-openapi/swag/jsonutils", "github.com/go-openapi/swag/jsonutils/adapters", "github.com/go-openapi/swag/jsonutils/adapters/ifaces", "github.com/go-openapi/swag/jsonutils/adapters/stdlib/json", "github.com/go-openapi/swag/loading", "github.com/go-openapi/swag/mangling", "github.com/go-openapi/swag/netutils", "github.com/go-openapi/swag/stringutils", "github.com/go-openapi/swag/typeutils", "github.com/go-openapi/swag/yamlutils", "github.com/go-openapi/validate", "github.com/go-viper/mapstructure/v2", "github.com/golang-jwt/jwt/v4", "github.com/golang/groupcache/lru", "github.com/golang/snappy", "github.com/google/btree", "github.com/google/cel-go/cel", "github.com/google/cel-go/checker", "github.com/google/cel-go/checker/decls", "github.com/google/cel-go/common", "github.com/google/cel-go/common/ast", "github.com/google/cel-go/common/containers", "github.com/google/cel-go/common/debug", "github.com/google/cel-go/common/decls", "github.com/google/cel-go/common/env", "github.com/google/cel-go/common/functions", "github.com/google/cel-go/common/operators", "github.com/google/cel-go/common/overloads", "github.com/google/cel-go/common/runes", "github.com/google/cel-go/common/stdlib", "github.com/google/cel-go/common/types", "github.com/google/cel-go/common/types/pb", "github.com/google/cel-go/common/types/ref", "github.com/google/cel-go/common/types/traits", "github.com/google/cel-go/ext", "github.com/google/cel-go/interpreter", "github.com/google/cel-go/interpreter/functions", "github.com/google/cel-go/parser", "github.com/google/cel-go/parser/gen", "github.com/google/certificate-transparency-go", "github.com/google/certificate-transparency-go/asn1", "github.com/google/certificate-transparency-go/client", "github.com/google/certificate-transparency-go/client/configpb", "github.com/google/certificate-transparency-go/ctutil", "github.com/google/certificate-transparency-go/gossip/minimal/x509ext", "github.com/google/certificate-transparency-go/jsonclient", "github.com/google/certificate-transparency-go/loglist3", "github.com/google/certificate-transparency-go/tls", "github.com/google/certificate-transparency-go/x509", "github.com/google/certificate-transparency-go/x509/pkix", "github.com/google/certificate-transparency-go/x509util", "github.com/google/gnostic-models/compiler", "github.com/google/gnostic-models/extensions", "github.com/google/gnostic-models/jsonschema", "github.com/google/gnostic-models/openapiv2", "github.com/google/gnostic-models/openapiv3", "github.com/google/go-cmp/cmp", "github.com/google/go-cmp/cmp/cmpopts", "github.com/google/go-containerregistry/pkg/authn", "github.com/google/go-containerregistry/pkg/authn/k8schain", "github.com/google/go-containerregistry/pkg/authn/kubernetes", "github.com/google/go-containerregistry/pkg/compression", "github.com/google/go-containerregistry/pkg/crane", "github.com/google/go-containerregistry/pkg/legacy", "github.com/google/go-containerregistry/pkg/legacy/tarball", "github.com/google/go-containerregistry/pkg/logs", "github.com/google/go-containerregistry/pkg/name", "github.com/google/go-containerregistry/pkg/v1", "github.com/google/go-containerregistry/pkg/v1/daemon", "github.com/google/go-containerregistry/pkg/v1/empty", "github.com/google/go-containerregistry/pkg/v1/google", "github.com/google/go-containerregistry/pkg/v1/layout", "github.com/google/go-containerregistry/pkg/v1/match", "github.com/google/go-containerregistry/pkg/v1/mutate", "github.com/google/go-containerregistry/pkg/v1/partial", "github.com/google/go-containerregistry/pkg/v1/random", "github.com/google/go-containerregistry/pkg/v1/remote", "github.com/google/go-containerregistry/pkg/v1/remote/transport", "github.com/google/go-containerregistry/pkg/v1/static", "github.com/google/go-containerregistry/pkg/v1/stream", "github.com/google/go-containerregistry/pkg/v1/tarball", "github.com/google/go-containerregistry/pkg/v1/types", "github.com/google/uuid", "github.com/gorilla/css/scanner", "github.com/grpc-ecosystem/grpc-gateway/v2/protoc-gen-openapiv2/options", "github.com/grpc-ecosystem/grpc-gateway/v2/runtime", "github.com/grpc-ecosystem/grpc-gateway/v2/utilities", "github.com/hashicorp/errwrap", "github.com/hashicorp/go-cleanhttp", "github.com/hashicorp/go-multierror", "github.com/hashicorp/go-retryablehttp", "github.com/in-toto/attestation/go/v1", "github.com/in-toto/in-toto-golang/in_toto", "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/common", "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.1", "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2", "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v1", "github.com/jbenet/go-context/io", "github.com/jedisct1/go-minisign", "github.com/json-iterator/go", "github.com/kevinburke/ssh_config", "github.com/klauspost/compress", "github.com/klauspost/compress/fse", "github.com/klauspost/compress/huff0", "github.com/klauspost/compress/zstd", "github.com/letsencrypt/boulder/core", "github.com/letsencrypt/boulder/core/proto", "github.com/letsencrypt/boulder/goodkey", "github.com/letsencrypt/boulder/identifier", "github.com/letsencrypt/boulder/probs", "github.com/letsencrypt/boulder/revocation", "github.com/liggitt/tabwriter", "github.com/lucasb-eyer/go-colorful", "github.com/mattn/go-isatty", "github.com/mattn/go-runewidth", "github.com/microcosm-cc/bluemonday", "github.com/microcosm-cc/bluemonday/css", "github.com/mitchellh/go-homedir", "github.com/moby/docker-image-spec/specs-go/v1", "github.com/moby/term", "github.com/modern-go/concurrent", "github.com/modern-go/reflect2", "github.com/muesli/ansi", "github.com/muesli/ansi/compressor", "github.com/muesli/cancelreader", "github.com/muesli/reflow/ansi", "github.com/muesli/reflow/indent", "github.com/muesli/reflow/padding", "github.com/muesli/reflow/wordwrap", "github.com/muesli/termenv", "github.com/munnerz/goautoneg", "github.com/nozzle/throttler", "github.com/oklog/ulid/v2", "github.com/opencontainers/go-digest", "github.com/opencontainers/image-spec/specs-go", "github.com/opencontainers/image-spec/specs-go/v1", "github.com/pjbgf/sha1cd", "github.com/pjbgf/sha1cd/ubc", "github.com/pkg/browser", "github.com/pkg/errors", "github.com/pmezard/go-difflib/difflib", "github.com/posener/complete", "github.com/posener/complete/cmd", "github.com/posener/complete/cmd/install", "github.com/prometheus/client_golang/prometheus", "github.com/prometheus/client_golang/prometheus/collectors", "github.com/prometheus/client_golang/prometheus/promhttp", "github.com/prometheus/client_model/go", "github.com/prometheus/common/expfmt", "github.com/prometheus/common/model", "github.com/prometheus/procfs", "github.com/rivo/uniseg", "github.com/riywo/loginshell", "github.com/sassoftware/relic/lib/pkcs7", "github.com/sassoftware/relic/lib/x509tools", "github.com/secure-systems-lab/go-securesystemslib/cjson", "github.com/secure-systems-lab/go-securesystemslib/dsse", "github.com/secure-systems-lab/go-securesystemslib/encrypted", "github.com/secure-systems-lab/go-securesystemslib/signerverifier", "github.com/sergi/go-diff/diffmatchpatch", "github.com/shibumi/go-pathspec", "github.com/sigstore/cosign/v3/pkg/blob", "github.com/sigstore/cosign/v3/pkg/cosign", "github.com/sigstore/cosign/v3/pkg/cosign/attestation", "github.com/sigstore/cosign/v3/pkg/cosign/bundle", "github.com/sigstore/cosign/v3/pkg/cosign/env", "github.com/sigstore/cosign/v3/pkg/cosign/fulcioverifier/ctutil", "github.com/sigstore/cosign/v3/pkg/oci", "github.com/sigstore/cosign/v3/pkg/oci/empty", "github.com/sigstore/cosign/v3/pkg/oci/layout", "github.com/sigstore/cosign/v3/pkg/oci/remote", "github.com/sigstore/cosign/v3/pkg/oci/signed", "github.com/sigstore/cosign/v3/pkg/oci/static", "github.com/sigstore/cosign/v3/pkg/types", "github.com/sigstore/protobuf-specs/gen/pb-go/bundle/v1", "github.com/sigstore/protobuf-specs/gen/pb-go/common/v1", "github.com/sigstore/protobuf-specs/gen/pb-go/dsse", "github.com/sigstore/protobuf-specs/gen/pb-go/rekor/v1", "github.com/sigstore/protobuf-specs/gen/pb-go/trustroot/v1", "github.com/sigstore/rekor-tiles/v2/pkg/client", "github.com/sigstore/rekor-tiles/v2/pkg/client/write", "github.com/sigstore/rekor-tiles/v2/pkg/generated/protobuf", "github.com/sigstore/rekor-tiles/v2/pkg/note", "github.com/sigstore/rekor-tiles/v2/pkg/types/verifier", "github.com/sigstore/rekor-tiles/v2/pkg/verify", "github.com/sigstore/rekor/pkg/client", "github.com/sigstore/rekor/pkg/generated/client", "github.com/sigstore/rekor/pkg/generated/client/entries", "github.com/sigstore/rekor/pkg/generated/client/index", "github.com/sigstore/rekor/pkg/generated/client/pubkey", "github.com/sigstore/rekor/pkg/generated/client/tlog", "github.com/sigstore/rekor/pkg/generated/models", "github.com/sigstore/rekor/pkg/log", "github.com/sigstore/rekor/pkg/pki", "github.com/sigstore/rekor/pkg/pki/identity", "github.com/sigstore/rekor/pkg/pki/minisign", "github.com/sigstore/rekor/pkg/pki/pgp", "github.com/sigstore/rekor/pkg/pki/pkcs7", "github.com/sigstore/rekor/pkg/pki/pkitypes", "github.com/sigstore/rekor/pkg/pki/ssh", "github.com/sigstore/rekor/pkg/pki/tuf", "github.com/sigstore/rekor/pkg/pki/x509", "github.com/sigstore/rekor/pkg/tle", "github.com/sigstore/rekor/pkg/types", "github.com/sigstore/rekor/pkg/types/dsse", "github.com/sigstore/rekor/pkg/types/dsse/v0.0.1", "github.com/sigstore/rekor/pkg/types/hashedrekord", "github.com/sigstore/rekor/pkg/types/hashedrekord/v0.0.1", "github.com/sigstore/rekor/pkg/types/intoto", "github.com/sigstore/rekor/pkg/types/intoto/v0.0.1", "github.com/sigstore/rekor/pkg/types/intoto/v0.0.2", "github.com/sigstore/rekor/pkg/types/rekord", "github.com/sigstore/rekor/pkg/types/rekord/v0.0.1", "github.com/sigstore/rekor/pkg/util", "github.com/sigstore/rekor/pkg/verify", "github.com/sigstore/sigstore-go/pkg/bundle", "github.com/sigstore/sigstore-go/pkg/fulcio/certificate", "github.com/sigstore/sigstore-go/pkg/root", "github.com/sigstore/sigstore-go/pkg/sign", "github.com/sigstore/sigstore-go/pkg/tlog", "github.com/sigstore/sigstore-go/pkg/tuf", "github.com/sigstore/sigstore-go/pkg/util", "github.com/sigstore/sigstore-go/pkg/verify", "github.com/sigstore/sigstore/pkg/cryptoutils", "github.com/sigstore/sigstore/pkg/cryptoutils/goodkey", "github.com/sigstore/sigstore/pkg/fulcioroots", "github.com/sigstore/sigstore/pkg/oauth", "github.com/sigstore/sigstore/pkg/oauthflow", "github.com/sigstore/sigstore/pkg/signature", "github.com/sigstore/sigstore/pkg/signature/dsse", "github.com/sigstore/sigstore/pkg/signature/options", "github.com/sigstore/sigstore/pkg/signature/payload", "github.com/sigstore/sigstore/pkg/tuf", "github.com/sigstore/timestamp-authority/v2/pkg/verification", "github.com/sirupsen/logrus", "github.com/skeema/knownhosts", "github.com/spf13/afero", "github.com/spf13/afero/mem", "github.com/spf13/cobra", "github.com/spf13/pflag", "github.com/syndtr/goleveldb/leveldb", "github.com/syndtr/goleveldb/leveldb/cache", "github.com/syndtr/goleveldb/leveldb/comparer", "github.com/syndtr/goleveldb/leveldb/errors", "github.com/syndtr/goleveldb/leveldb/filter", "github.com/syndtr/goleveldb/leveldb/iterator", "github.com/syndtr/goleveldb/leveldb/journal", "github.com/syndtr/goleveldb/leveldb/memdb", "github.com/syndtr/goleveldb/leveldb/opt", "github.com/syndtr/goleveldb/leveldb/storage", "github.com/syndtr/goleveldb/leveldb/table", "github.com/syndtr/goleveldb/leveldb/util", "github.com/theupdateframework/go-tuf", "github.com/theupdateframework/go-tuf/client", "github.com/theupdateframework/go-tuf/client/leveldbstore", "github.com/theupdateframework/go-tuf/data", "github.com/theupdateframework/go-tuf/pkg/keys", "github.com/theupdateframework/go-tuf/pkg/targets", "github.com/theupdateframework/go-tuf/sign", "github.com/theupdateframework/go-tuf/util", "github.com/theupdateframework/go-tuf/v2/metadata", "github.com/theupdateframework/go-tuf/v2/metadata/config", "github.com/theupdateframework/go-tuf/v2/metadata/fetcher", "github.com/theupdateframework/go-tuf/v2/metadata/trustedmetadata", "github.com/theupdateframework/go-tuf/v2/metadata/updater", "github.com/theupdateframework/go-tuf/verify", "github.com/titanous/rocacheck", "github.com/transparency-dev/formats/log", "github.com/transparency-dev/merkle", "github.com/transparency-dev/merkle/compact", "github.com/transparency-dev/merkle/proof", "github.com/transparency-dev/merkle/rfc6962", "github.com/vbatts/tar-split/archive/tar", "github.com/willabides/kongplete", "github.com/x448/float16", "github.com/xanzy/ssh-agent", "github.com/xo/terminfo", "github.com/yuin/goldmark", "github.com/yuin/goldmark-emoji", "github.com/yuin/goldmark-emoji/ast", "github.com/yuin/goldmark-emoji/definition", "github.com/yuin/goldmark/ast", "github.com/yuin/goldmark/extension", "github.com/yuin/goldmark/extension/ast", "github.com/yuin/goldmark/parser", "github.com/yuin/goldmark/renderer", "github.com/yuin/goldmark/renderer/html", "github.com/yuin/goldmark/text", "github.com/yuin/goldmark/util", "go.opentelemetry.io/auto/sdk", "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp", "go.opentelemetry.io/otel", "go.opentelemetry.io/otel/attribute", "go.opentelemetry.io/otel/baggage", "go.opentelemetry.io/otel/codes", "go.opentelemetry.io/otel/metric", "go.opentelemetry.io/otel/metric/embedded", "go.opentelemetry.io/otel/metric/noop", "go.opentelemetry.io/otel/propagation", "go.opentelemetry.io/otel/semconv/v1.37.0", "go.opentelemetry.io/otel/semconv/v1.40.0", "go.opentelemetry.io/otel/semconv/v1.40.0/httpconv", "go.opentelemetry.io/otel/trace", "go.opentelemetry.io/otel/trace/embedded", "go.opentelemetry.io/otel/trace/noop", "go.uber.org/multierr", "go.uber.org/zap", "go.uber.org/zap/buffer", "go.uber.org/zap/zapcore", "go.yaml.in/yaml/v2", "go.yaml.in/yaml/v3", "golang.org/x/crypto/argon2", "golang.org/x/crypto/blake2b", "golang.org/x/crypto/blowfish", "golang.org/x/crypto/cast5", "golang.org/x/crypto/chacha20", "golang.org/x/crypto/cryptobyte", "golang.org/x/crypto/cryptobyte/asn1", "golang.org/x/crypto/curve25519", "golang.org/x/crypto/ed25519", "golang.org/x/crypto/hkdf", "golang.org/x/crypto/nacl/secretbox", "golang.org/x/crypto/ocsp", "golang.org/x/crypto/openpgp", "golang.org/x/crypto/openpgp/armor", "golang.org/x/crypto/openpgp/elgamal", "golang.org/x/crypto/openpgp/errors", "golang.org/x/crypto/openpgp/packet", "golang.org/x/crypto/openpgp/s2k", "golang.org/x/crypto/pbkdf2", "golang.org/x/crypto/pkcs12", "golang.org/x/crypto/salsa20/salsa", "golang.org/x/crypto/scrypt", "golang.org/x/crypto/sha3", "golang.org/x/crypto/ssh", "golang.org/x/crypto/ssh/agent", "golang.org/x/crypto/ssh/knownhosts", "golang.org/x/crypto/ssh/terminal", "golang.org/x/exp/slices", "golang.org/x/mod/semver", "golang.org/x/mod/sumdb/note", "golang.org/x/net/context", "golang.org/x/net/html", "golang.org/x/net/html/atom", "golang.org/x/net/http/httpguts", "golang.org/x/net/http2", "golang.org/x/net/http2/hpack", "golang.org/x/net/idna", "golang.org/x/net/proxy", "golang.org/x/net/trace", "golang.org/x/oauth2", "golang.org/x/oauth2/authhandler", "golang.org/x/oauth2/google", "golang.org/x/oauth2/google/externalaccount", "golang.org/x/oauth2/jws", "golang.org/x/oauth2/jwt", "golang.org/x/sync/errgroup", "golang.org/x/sync/singleflight", "golang.org/x/sys/cpu", "golang.org/x/sys/execabs", "golang.org/x/sys/unix", "golang.org/x/term", "golang.org/x/text/cases", "golang.org/x/text/feature/plural", "golang.org/x/text/language", "golang.org/x/text/message", "golang.org/x/text/message/catalog", "golang.org/x/text/runes", "golang.org/x/text/secure/bidirule", "golang.org/x/text/transform", "golang.org/x/text/unicode/bidi", "golang.org/x/text/unicode/norm", "golang.org/x/time/rate", "gomodules.xyz/jsonpatch/v2", "google.golang.org/genproto/googleapis/api", "google.golang.org/genproto/googleapis/api/annotations", "google.golang.org/genproto/googleapis/api/expr/v1alpha1", "google.golang.org/genproto/googleapis/api/httpbody", "google.golang.org/genproto/googleapis/rpc/status", "google.golang.org/grpc", "google.golang.org/grpc/attributes", "google.golang.org/grpc/backoff", "google.golang.org/grpc/balancer", "google.golang.org/grpc/balancer/base", "google.golang.org/grpc/balancer/endpointsharding", "google.golang.org/grpc/balancer/grpclb/state", "google.golang.org/grpc/balancer/pickfirst", "google.golang.org/grpc/balancer/roundrobin", "google.golang.org/grpc/binarylog/grpc_binarylog_v1", "google.golang.org/grpc/channelz", "google.golang.org/grpc/codes", "google.golang.org/grpc/connectivity", "google.golang.org/grpc/credentials", "google.golang.org/grpc/credentials/insecure", "google.golang.org/grpc/encoding", "google.golang.org/grpc/encoding/proto", "google.golang.org/grpc/experimental/stats", "google.golang.org/grpc/grpclog", "google.golang.org/grpc/health/grpc_health_v1", "google.golang.org/grpc/keepalive", "google.golang.org/grpc/mem", "google.golang.org/grpc/metadata", "google.golang.org/grpc/peer", "google.golang.org/grpc/resolver", "google.golang.org/grpc/resolver/dns", "google.golang.org/grpc/serviceconfig", "google.golang.org/grpc/stats", "google.golang.org/grpc/status", "google.golang.org/grpc/tap", "google.golang.org/protobuf/encoding/protodelim", "google.golang.org/protobuf/encoding/protojson", "google.golang.org/protobuf/encoding/prototext", "google.golang.org/protobuf/encoding/protowire", "google.golang.org/protobuf/proto", "google.golang.org/protobuf/protoadapt", "google.golang.org/protobuf/reflect/protodesc", "google.golang.org/protobuf/reflect/protoreflect", "google.golang.org/protobuf/reflect/protoregistry", "google.golang.org/protobuf/runtime/protoiface", "google.golang.org/protobuf/runtime/protoimpl", "google.golang.org/protobuf/testing/protocmp", "google.golang.org/protobuf/types/descriptorpb", "google.golang.org/protobuf/types/dynamicpb", "google.golang.org/protobuf/types/gofeaturespb", "google.golang.org/protobuf/types/known/anypb", "google.golang.org/protobuf/types/known/durationpb", "google.golang.org/protobuf/types/known/emptypb", "google.golang.org/protobuf/types/known/fieldmaskpb", "google.golang.org/protobuf/types/known/structpb", "google.golang.org/protobuf/types/known/timestamppb", "google.golang.org/protobuf/types/known/wrapperspb", "gopkg.in/evanphx/json-patch.v4", "gopkg.in/inf.v0", "gopkg.in/warnings.v0", "gopkg.in/yaml.v3", "k8s.io/api/admission/v1", "k8s.io/api/admission/v1beta1", "k8s.io/api/admissionregistration/v1", "k8s.io/api/admissionregistration/v1alpha1", "k8s.io/api/admissionregistration/v1beta1", "k8s.io/api/apidiscovery/v2", "k8s.io/api/apidiscovery/v2beta1", "k8s.io/api/apiserverinternal/v1alpha1", "k8s.io/api/apps/v1", "k8s.io/api/apps/v1beta1", "k8s.io/api/apps/v1beta2", "k8s.io/api/authentication/v1", "k8s.io/api/authentication/v1alpha1", "k8s.io/api/authentication/v1beta1", "k8s.io/api/authorization/v1", "k8s.io/api/authorization/v1beta1", "k8s.io/api/autoscaling/v1", "k8s.io/api/autoscaling/v2", "k8s.io/api/autoscaling/v2beta1", "k8s.io/api/autoscaling/v2beta2", "k8s.io/api/batch/v1", "k8s.io/api/batch/v1beta1", "k8s.io/api/certificates/v1", "k8s.io/api/certificates/v1alpha1", "k8s.io/api/certificates/v1beta1", "k8s.io/api/coordination/v1", "k8s.io/api/coordination/v1alpha2", "k8s.io/api/coordination/v1beta1", "k8s.io/api/core/v1", "k8s.io/api/discovery/v1", "k8s.io/api/discovery/v1beta1", "k8s.io/api/events/v1", "k8s.io/api/events/v1beta1", "k8s.io/api/extensions/v1beta1", "k8s.io/api/flowcontrol/v1", "k8s.io/api/flowcontrol/v1beta1", "k8s.io/api/flowcontrol/v1beta2", "k8s.io/api/flowcontrol/v1beta3", "k8s.io/api/networking/v1", "k8s.io/api/networking/v1beta1", "k8s.io/api/node/v1", "k8s.io/api/node/v1alpha1", "k8s.io/api/node/v1beta1", "k8s.io/api/policy/v1", "k8s.io/api/policy/v1beta1", "k8s.io/api/rbac/v1", "k8s.io/api/rbac/v1alpha1", "k8s.io/api/rbac/v1beta1", "k8s.io/api/resource/v1", "k8s.io/api/resource/v1alpha3", "k8s.io/api/resource/v1beta1", "k8s.io/api/resource/v1beta2", "k8s.io/api/scheduling/v1", "k8s.io/api/scheduling/v1alpha1", "k8s.io/api/scheduling/v1beta1", "k8s.io/api/storage/v1", "k8s.io/api/storage/v1alpha1", "k8s.io/api/storage/v1beta1", "k8s.io/api/storagemigration/v1beta1", "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions", "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1", "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1", "k8s.io/apiextensions-apiserver/pkg/apiserver/schema", "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel", "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/cel/model", "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/defaulting", "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/objectmeta", "k8s.io/apiextensions-apiserver/pkg/apiserver/schema/pruning", "k8s.io/apiextensions-apiserver/pkg/apiserver/validation", "k8s.io/apiextensions-apiserver/pkg/features", "k8s.io/apimachinery/pkg/api/equality", "k8s.io/apimachinery/pkg/api/errors", "k8s.io/apimachinery/pkg/api/meta", "k8s.io/apimachinery/pkg/api/meta/testrestmapper", "k8s.io/apimachinery/pkg/api/operation", "k8s.io/apimachinery/pkg/api/resource", "k8s.io/apimachinery/pkg/api/safe", "k8s.io/apimachinery/pkg/api/validate", "k8s.io/apimachinery/pkg/api/validate/constraints", "k8s.io/apimachinery/pkg/api/validate/content", "k8s.io/apimachinery/pkg/api/validation", "k8s.io/apimachinery/pkg/api/validation/path", "k8s.io/apimachinery/pkg/apis/meta/v1", "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured", "k8s.io/apimachinery/pkg/apis/meta/v1/validation", "k8s.io/apimachinery/pkg/apis/meta/v1beta1", "k8s.io/apimachinery/pkg/conversion", "k8s.io/apimachinery/pkg/conversion/queryparams", "k8s.io/apimachinery/pkg/fields", "k8s.io/apimachinery/pkg/labels", "k8s.io/apimachinery/pkg/runtime", "k8s.io/apimachinery/pkg/runtime/schema", "k8s.io/apimachinery/pkg/runtime/serializer", "k8s.io/apimachinery/pkg/runtime/serializer/cbor", "k8s.io/apimachinery/pkg/runtime/serializer/cbor/direct", "k8s.io/apimachinery/pkg/runtime/serializer/json", "k8s.io/apimachinery/pkg/runtime/serializer/protobuf", "k8s.io/apimachinery/pkg/runtime/serializer/recognizer", "k8s.io/apimachinery/pkg/runtime/serializer/streaming", "k8s.io/apimachinery/pkg/runtime/serializer/versioning", "k8s.io/apimachinery/pkg/selection", "k8s.io/apimachinery/pkg/types", "k8s.io/apimachinery/pkg/util/cache", "k8s.io/apimachinery/pkg/util/diff", "k8s.io/apimachinery/pkg/util/dump", "k8s.io/apimachinery/pkg/util/duration", "k8s.io/apimachinery/pkg/util/errors", "k8s.io/apimachinery/pkg/util/framer", "k8s.io/apimachinery/pkg/util/intstr", "k8s.io/apimachinery/pkg/util/json", "k8s.io/apimachinery/pkg/util/managedfields", "k8s.io/apimachinery/pkg/util/mergepatch", "k8s.io/apimachinery/pkg/util/naming", "k8s.io/apimachinery/pkg/util/net", "k8s.io/apimachinery/pkg/util/rand", "k8s.io/apimachinery/pkg/util/runtime", "k8s.io/apimachinery/pkg/util/sets", "k8s.io/apimachinery/pkg/util/strategicpatch", "k8s.io/apimachinery/pkg/util/uuid", "k8s.io/apimachinery/pkg/util/validation", "k8s.io/apimachinery/pkg/util/validation/field", "k8s.io/apimachinery/pkg/util/version", "k8s.io/apimachinery/pkg/util/wait", "k8s.io/apimachinery/pkg/util/yaml", "k8s.io/apimachinery/pkg/version", "k8s.io/apimachinery/pkg/watch", "k8s.io/apimachinery/third_party/forked/golang/json", "k8s.io/apimachinery/third_party/forked/golang/reflect", "k8s.io/apiserver/pkg/apis/cel", "k8s.io/apiserver/pkg/authentication/serviceaccount", "k8s.io/apiserver/pkg/authentication/user", "k8s.io/apiserver/pkg/authorization/authorizer", "k8s.io/apiserver/pkg/cel", "k8s.io/apiserver/pkg/cel/common", "k8s.io/apiserver/pkg/cel/environment", "k8s.io/apiserver/pkg/cel/library", "k8s.io/apiserver/pkg/cel/metrics", "k8s.io/apiserver/pkg/cel/openapi", "k8s.io/apiserver/pkg/features", "k8s.io/apiserver/pkg/util/compatibility", "k8s.io/apiserver/pkg/util/feature", "k8s.io/apiserver/pkg/warning", "k8s.io/cli-runtime/pkg/printers", "k8s.io/client-go/applyconfigurations/admissionregistration/v1", "k8s.io/client-go/applyconfigurations/admissionregistration/v1alpha1", "k8s.io/client-go/applyconfigurations/admissionregistration/v1beta1", "k8s.io/client-go/applyconfigurations/apiserverinternal/v1alpha1", "k8s.io/client-go/applyconfigurations/apps/v1", "k8s.io/client-go/applyconfigurations/apps/v1beta1", "k8s.io/client-go/applyconfigurations/apps/v1beta2", "k8s.io/client-go/applyconfigurations/autoscaling/v1", "k8s.io/client-go/applyconfigurations/autoscaling/v2", "k8s.io/client-go/applyconfigurations/autoscaling/v2beta1", "k8s.io/client-go/applyconfigurations/autoscaling/v2beta2", "k8s.io/client-go/applyconfigurations/batch/v1", "k8s.io/client-go/applyconfigurations/batch/v1beta1", "k8s.io/client-go/applyconfigurations/certificates/v1", "k8s.io/client-go/applyconfigurations/certificates/v1alpha1", "k8s.io/client-go/applyconfigurations/certificates/v1beta1", "k8s.io/client-go/applyconfigurations/coordination/v1", "k8s.io/client-go/applyconfigurations/coordination/v1alpha2", "k8s.io/client-go/applyconfigurations/coordination/v1beta1", "k8s.io/client-go/applyconfigurations/core/v1", "k8s.io/client-go/applyconfigurations/discovery/v1", "k8s.io/client-go/applyconfigurations/discovery/v1beta1", "k8s.io/client-go/applyconfigurations/events/v1", "k8s.io/client-go/applyconfigurations/events/v1beta1", "k8s.io/client-go/applyconfigurations/extensions/v1beta1", "k8s.io/client-go/applyconfigurations/flowcontrol/v1", "k8s.io/client-go/applyconfigurations/flowcontrol/v1beta1", "k8s.io/client-go/applyconfigurations/flowcontrol/v1beta2", "k8s.io/client-go/applyconfigurations/flowcontrol/v1beta3", "k8s.io/client-go/applyconfigurations/meta/v1", "k8s.io/client-go/applyconfigurations/networking/v1", "k8s.io/client-go/applyconfigurations/networking/v1beta1", "k8s.io/client-go/applyconfigurations/node/v1", "k8s.io/client-go/applyconfigurations/node/v1alpha1", "k8s.io/client-go/applyconfigurations/node/v1beta1", "k8s.io/client-go/applyconfigurations/policy/v1", "k8s.io/client-go/applyconfigurations/policy/v1beta1", "k8s.io/client-go/applyconfigurations/rbac/v1", "k8s.io/client-go/applyconfigurations/rbac/v1alpha1", "k8s.io/client-go/applyconfigurations/rbac/v1beta1", "k8s.io/client-go/applyconfigurations/resource/v1", "k8s.io/client-go/applyconfigurations/resource/v1alpha3", "k8s.io/client-go/applyconfigurations/resource/v1beta1", "k8s.io/client-go/applyconfigurations/resource/v1beta2", "k8s.io/client-go/applyconfigurations/scheduling/v1", "k8s.io/client-go/applyconfigurations/scheduling/v1alpha1", "k8s.io/client-go/applyconfigurations/scheduling/v1beta1", "k8s.io/client-go/applyconfigurations/storage/v1", "k8s.io/client-go/applyconfigurations/storage/v1alpha1", "k8s.io/client-go/applyconfigurations/storage/v1beta1", "k8s.io/client-go/applyconfigurations/storagemigration/v1beta1", "k8s.io/client-go/discovery", "k8s.io/client-go/discovery/cached/memory", "k8s.io/client-go/dynamic", "k8s.io/client-go/features", "k8s.io/client-go/gentype", "k8s.io/client-go/informers", "k8s.io/client-go/informers/admissionregistration", "k8s.io/client-go/informers/admissionregistration/v1", "k8s.io/client-go/informers/admissionregistration/v1alpha1", "k8s.io/client-go/informers/admissionregistration/v1beta1", "k8s.io/client-go/informers/apiserverinternal", "k8s.io/client-go/informers/apiserverinternal/v1alpha1", "k8s.io/client-go/informers/apps", "k8s.io/client-go/informers/apps/v1", "k8s.io/client-go/informers/apps/v1beta1", "k8s.io/client-go/informers/apps/v1beta2", "k8s.io/client-go/informers/autoscaling", "k8s.io/client-go/informers/autoscaling/v1", "k8s.io/client-go/informers/autoscaling/v2", "k8s.io/client-go/informers/autoscaling/v2beta1", "k8s.io/client-go/informers/autoscaling/v2beta2", "k8s.io/client-go/informers/batch", "k8s.io/client-go/informers/batch/v1", "k8s.io/client-go/informers/batch/v1beta1", "k8s.io/client-go/informers/certificates", "k8s.io/client-go/informers/certificates/v1", "k8s.io/client-go/informers/certificates/v1alpha1", "k8s.io/client-go/informers/certificates/v1beta1", "k8s.io/client-go/informers/coordination", "k8s.io/client-go/informers/coordination/v1", "k8s.io/client-go/informers/coordination/v1alpha2", "k8s.io/client-go/informers/coordination/v1beta1", "k8s.io/client-go/informers/core", "k8s.io/client-go/informers/core/v1", "k8s.io/client-go/informers/discovery", "k8s.io/client-go/informers/discovery/v1", "k8s.io/client-go/informers/discovery/v1beta1", "k8s.io/client-go/informers/events", "k8s.io/client-go/informers/events/v1", "k8s.io/client-go/informers/events/v1beta1", "k8s.io/client-go/informers/extensions", "k8s.io/client-go/informers/extensions/v1beta1", "k8s.io/client-go/informers/flowcontrol", "k8s.io/client-go/informers/flowcontrol/v1", "k8s.io/client-go/informers/flowcontrol/v1beta1", "k8s.io/client-go/informers/flowcontrol/v1beta2", "k8s.io/client-go/informers/flowcontrol/v1beta3", "k8s.io/client-go/informers/networking", "k8s.io/client-go/informers/networking/v1", "k8s.io/client-go/informers/networking/v1beta1", "k8s.io/client-go/informers/node", "k8s.io/client-go/informers/node/v1", "k8s.io/client-go/informers/node/v1alpha1", "k8s.io/client-go/informers/node/v1beta1", "k8s.io/client-go/informers/policy", "k8s.io/client-go/informers/policy/v1", "k8s.io/client-go/informers/policy/v1beta1", "k8s.io/client-go/informers/rbac", "k8s.io/client-go/informers/rbac/v1", "k8s.io/client-go/informers/rbac/v1alpha1", "k8s.io/client-go/informers/rbac/v1beta1", "k8s.io/client-go/informers/resource", "k8s.io/client-go/informers/resource/v1", "k8s.io/client-go/informers/resource/v1alpha3", "k8s.io/client-go/informers/resource/v1beta1", "k8s.io/client-go/informers/resource/v1beta2", "k8s.io/client-go/informers/scheduling", "k8s.io/client-go/informers/scheduling/v1", "k8s.io/client-go/informers/scheduling/v1alpha1", "k8s.io/client-go/informers/scheduling/v1beta1", "k8s.io/client-go/informers/storage", "k8s.io/client-go/informers/storage/v1", "k8s.io/client-go/informers/storage/v1alpha1", "k8s.io/client-go/informers/storage/v1beta1", "k8s.io/client-go/informers/storagemigration", "k8s.io/client-go/informers/storagemigration/v1beta1", "k8s.io/client-go/kubernetes", "k8s.io/client-go/kubernetes/scheme", "k8s.io/client-go/kubernetes/typed/admissionregistration/v1", "k8s.io/client-go/kubernetes/typed/admissionregistration/v1alpha1", "k8s.io/client-go/kubernetes/typed/admissionregistration/v1beta1", "k8s.io/client-go/kubernetes/typed/apiserverinternal/v1alpha1", "k8s.io/client-go/kubernetes/typed/apps/v1", "k8s.io/client-go/kubernetes/typed/apps/v1beta1", "k8s.io/client-go/kubernetes/typed/apps/v1beta2", "k8s.io/client-go/kubernetes/typed/authentication/v1", "k8s.io/client-go/kubernetes/typed/authentication/v1alpha1", "k8s.io/client-go/kubernetes/typed/authentication/v1beta1", "k8s.io/client-go/kubernetes/typed/authorization/v1", "k8s.io/client-go/kubernetes/typed/authorization/v1beta1", "k8s.io/client-go/kubernetes/typed/autoscaling/v1", "k8s.io/client-go/kubernetes/typed/autoscaling/v2", "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta1", "k8s.io/client-go/kubernetes/typed/autoscaling/v2beta2", "k8s.io/client-go/kubernetes/typed/batch/v1", "k8s.io/client-go/kubernetes/typed/batch/v1beta1", "k8s.io/client-go/kubernetes/typed/certificates/v1", "k8s.io/client-go/kubernetes/typed/certificates/v1alpha1", "k8s.io/client-go/kubernetes/typed/certificates/v1beta1", "k8s.io/client-go/kubernetes/typed/coordination/v1", "k8s.io/client-go/kubernetes/typed/coordination/v1alpha2", "k8s.io/client-go/kubernetes/typed/coordination/v1beta1", "k8s.io/client-go/kubernetes/typed/core/v1", "k8s.io/client-go/kubernetes/typed/discovery/v1", "k8s.io/client-go/kubernetes/typed/discovery/v1beta1", "k8s.io/client-go/kubernetes/typed/events/v1", "k8s.io/client-go/kubernetes/typed/events/v1beta1", "k8s.io/client-go/kubernetes/typed/extensions/v1beta1", "k8s.io/client-go/kubernetes/typed/flowcontrol/v1", "k8s.io/client-go/kubernetes/typed/flowcontrol/v1beta1", "k8s.io/client-go/kubernetes/typed/flowcontrol/v1beta2", "k8s.io/client-go/kubernetes/typed/flowcontrol/v1beta3", "k8s.io/client-go/kubernetes/typed/networking/v1", "k8s.io/client-go/kubernetes/typed/networking/v1beta1", "k8s.io/client-go/kubernetes/typed/node/v1", "k8s.io/client-go/kubernetes/typed/node/v1alpha1", "k8s.io/client-go/kubernetes/typed/node/v1beta1", "k8s.io/client-go/kubernetes/typed/policy/v1", "k8s.io/client-go/kubernetes/typed/policy/v1beta1", "k8s.io/client-go/kubernetes/typed/rbac/v1", "k8s.io/client-go/kubernetes/typed/rbac/v1alpha1", "k8s.io/client-go/kubernetes/typed/rbac/v1beta1", "k8s.io/client-go/kubernetes/typed/resource/v1", "k8s.io/client-go/kubernetes/typed/resource/v1alpha3", "k8s.io/client-go/kubernetes/typed/resource/v1beta1", "k8s.io/client-go/kubernetes/typed/resource/v1beta2", "k8s.io/client-go/kubernetes/typed/scheduling/v1", "k8s.io/client-go/kubernetes/typed/scheduling/v1alpha1", "k8s.io/client-go/kubernetes/typed/scheduling/v1beta1", "k8s.io/client-go/kubernetes/typed/storage/v1", "k8s.io/client-go/kubernetes/typed/storage/v1alpha1", "k8s.io/client-go/kubernetes/typed/storage/v1beta1", "k8s.io/client-go/kubernetes/typed/storagemigration/v1beta1", "k8s.io/client-go/listers", "k8s.io/client-go/listers/admissionregistration/v1", "k8s.io/client-go/listers/admissionregistration/v1alpha1", "k8s.io/client-go/listers/admissionregistration/v1beta1", "k8s.io/client-go/listers/apiserverinternal/v1alpha1", "k8s.io/client-go/listers/apps/v1", "k8s.io/client-go/listers/apps/v1beta1", "k8s.io/client-go/listers/apps/v1beta2", "k8s.io/client-go/listers/autoscaling/v1", "k8s.io/client-go/listers/autoscaling/v2", "k8s.io/client-go/listers/autoscaling/v2beta1", "k8s.io/client-go/listers/autoscaling/v2beta2", "k8s.io/client-go/listers/batch/v1", "k8s.io/client-go/listers/batch/v1beta1", "k8s.io/client-go/listers/certificates/v1", "k8s.io/client-go/listers/certificates/v1alpha1", "k8s.io/client-go/listers/certificates/v1beta1", "k8s.io/client-go/listers/coordination/v1", "k8s.io/client-go/listers/coordination/v1alpha2", "k8s.io/client-go/listers/coordination/v1beta1", "k8s.io/client-go/listers/core/v1", "k8s.io/client-go/listers/discovery/v1", "k8s.io/client-go/listers/discovery/v1beta1", "k8s.io/client-go/listers/events/v1", "k8s.io/client-go/listers/events/v1beta1", "k8s.io/client-go/listers/extensions/v1beta1", "k8s.io/client-go/listers/flowcontrol/v1", "k8s.io/client-go/listers/flowcontrol/v1beta1", "k8s.io/client-go/listers/flowcontrol/v1beta2", "k8s.io/client-go/listers/flowcontrol/v1beta3", "k8s.io/client-go/listers/networking/v1", "k8s.io/client-go/listers/networking/v1beta1", "k8s.io/client-go/listers/node/v1", "k8s.io/client-go/listers/node/v1alpha1", "k8s.io/client-go/listers/node/v1beta1", "k8s.io/client-go/listers/policy/v1", "k8s.io/client-go/listers/policy/v1beta1", "k8s.io/client-go/listers/rbac/v1", "k8s.io/client-go/listers/rbac/v1alpha1", "k8s.io/client-go/listers/rbac/v1beta1", "k8s.io/client-go/listers/resource/v1", "k8s.io/client-go/listers/resource/v1alpha3", "k8s.io/client-go/listers/resource/v1beta1", "k8s.io/client-go/listers/resource/v1beta2", "k8s.io/client-go/listers/scheduling/v1", "k8s.io/client-go/listers/scheduling/v1alpha1", "k8s.io/client-go/listers/scheduling/v1beta1", "k8s.io/client-go/listers/storage/v1", "k8s.io/client-go/listers/storage/v1alpha1", "k8s.io/client-go/listers/storage/v1beta1", "k8s.io/client-go/listers/storagemigration/v1beta1", "k8s.io/client-go/metadata", "k8s.io/client-go/openapi", "k8s.io/client-go/openapi/cached", "k8s.io/client-go/pkg/apis/clientauthentication", "k8s.io/client-go/pkg/apis/clientauthentication/install", "k8s.io/client-go/pkg/apis/clientauthentication/v1", "k8s.io/client-go/pkg/apis/clientauthentication/v1beta1", "k8s.io/client-go/pkg/version", "k8s.io/client-go/plugin/pkg/client/auth", "k8s.io/client-go/plugin/pkg/client/auth/azure", "k8s.io/client-go/plugin/pkg/client/auth/exec", "k8s.io/client-go/plugin/pkg/client/auth/gcp", "k8s.io/client-go/plugin/pkg/client/auth/oidc", "k8s.io/client-go/rest", "k8s.io/client-go/rest/watch", "k8s.io/client-go/restmapper", "k8s.io/client-go/testing", "k8s.io/client-go/third_party/forked/golang/template", "k8s.io/client-go/tools/auth", "k8s.io/client-go/tools/cache", "k8s.io/client-go/tools/cache/synctrack", "k8s.io/client-go/tools/clientcmd", "k8s.io/client-go/tools/clientcmd/api", "k8s.io/client-go/tools/clientcmd/api/latest", "k8s.io/client-go/tools/clientcmd/api/v1", "k8s.io/client-go/tools/events", "k8s.io/client-go/tools/leaderelection", "k8s.io/client-go/tools/leaderelection/resourcelock", "k8s.io/client-go/tools/metrics", "k8s.io/client-go/tools/pager", "k8s.io/client-go/tools/record", "k8s.io/client-go/tools/record/util", "k8s.io/client-go/tools/reference", "k8s.io/client-go/transport", "k8s.io/client-go/util/apply", "k8s.io/client-go/util/cert", "k8s.io/client-go/util/connrotation", "k8s.io/client-go/util/consistencydetector", "k8s.io/client-go/util/flowcontrol", "k8s.io/client-go/util/homedir", "k8s.io/client-go/util/jsonpath", "k8s.io/client-go/util/keyutil", "k8s.io/client-go/util/retry", "k8s.io/client-go/util/watchlist", "k8s.io/client-go/util/workqueue", "k8s.io/component-base/cli/flag", "k8s.io/component-base/compatibility", "k8s.io/component-base/featuregate", "k8s.io/component-base/metrics", "k8s.io/component-base/metrics/legacyregistry", "k8s.io/component-base/metrics/prometheus/compatversion", "k8s.io/component-base/metrics/prometheus/feature", "k8s.io/component-base/metrics/prometheusextension", "k8s.io/component-base/version", "k8s.io/component-base/zpages/features", "k8s.io/klog/v2", "k8s.io/kube-openapi/pkg/cached", "k8s.io/kube-openapi/pkg/common", "k8s.io/kube-openapi/pkg/handler3", "k8s.io/kube-openapi/pkg/schemaconv", "k8s.io/kube-openapi/pkg/spec3", "k8s.io/kube-openapi/pkg/util", "k8s.io/kube-openapi/pkg/util/proto", "k8s.io/kube-openapi/pkg/validation/errors", "k8s.io/kube-openapi/pkg/validation/spec", "k8s.io/kube-openapi/pkg/validation/strfmt", "k8s.io/kube-openapi/pkg/validation/strfmt/bson", "k8s.io/kube-openapi/pkg/validation/validate", "k8s.io/metrics/pkg/apis/metrics", "k8s.io/metrics/pkg/apis/metrics/v1alpha1", "k8s.io/metrics/pkg/apis/metrics/v1beta1", "k8s.io/metrics/pkg/client/clientset/versioned", "k8s.io/metrics/pkg/client/clientset/versioned/scheme", "k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1alpha1", "k8s.io/metrics/pkg/client/clientset/versioned/typed/metrics/v1beta1", "k8s.io/utils/buffer", "k8s.io/utils/clock", "k8s.io/utils/lru", "k8s.io/utils/net", "k8s.io/utils/ptr", "k8s.io/utils/trace", "sigs.k8s.io/controller-runtime", "sigs.k8s.io/controller-runtime/pkg/builder", "sigs.k8s.io/controller-runtime/pkg/cache", "sigs.k8s.io/controller-runtime/pkg/certwatcher", "sigs.k8s.io/controller-runtime/pkg/certwatcher/metrics", "sigs.k8s.io/controller-runtime/pkg/client", "sigs.k8s.io/controller-runtime/pkg/client/apiutil", "sigs.k8s.io/controller-runtime/pkg/client/config", "sigs.k8s.io/controller-runtime/pkg/cluster", "sigs.k8s.io/controller-runtime/pkg/config", "sigs.k8s.io/controller-runtime/pkg/controller", "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil", "sigs.k8s.io/controller-runtime/pkg/controller/priorityqueue", "sigs.k8s.io/controller-runtime/pkg/conversion", "sigs.k8s.io/controller-runtime/pkg/event", "sigs.k8s.io/controller-runtime/pkg/handler", "sigs.k8s.io/controller-runtime/pkg/healthz", "sigs.k8s.io/controller-runtime/pkg/leaderelection", "sigs.k8s.io/controller-runtime/pkg/log", "sigs.k8s.io/controller-runtime/pkg/log/zap", "sigs.k8s.io/controller-runtime/pkg/manager", "sigs.k8s.io/controller-runtime/pkg/manager/signals", "sigs.k8s.io/controller-runtime/pkg/metrics", "sigs.k8s.io/controller-runtime/pkg/metrics/server", "sigs.k8s.io/controller-runtime/pkg/predicate", "sigs.k8s.io/controller-runtime/pkg/reconcile", "sigs.k8s.io/controller-runtime/pkg/recorder", "sigs.k8s.io/controller-runtime/pkg/scheme", "sigs.k8s.io/controller-runtime/pkg/source", "sigs.k8s.io/controller-runtime/pkg/webhook", "sigs.k8s.io/controller-runtime/pkg/webhook/admission", "sigs.k8s.io/controller-runtime/pkg/webhook/admission/metrics", "sigs.k8s.io/controller-runtime/pkg/webhook/conversion", "sigs.k8s.io/controller-runtime/pkg/webhook/conversion/metrics", "sigs.k8s.io/json", "sigs.k8s.io/randfill", "sigs.k8s.io/randfill/bytesource", "sigs.k8s.io/structured-merge-diff/v6/fieldpath", "sigs.k8s.io/structured-merge-diff/v6/merge", "sigs.k8s.io/structured-merge-diff/v6/schema", "sigs.k8s.io/structured-merge-diff/v6/typed", "sigs.k8s.io/structured-merge-diff/v6/value", "sigs.k8s.io/yaml", "sigs.k8s.io/yaml/kyaml"] [mod] [mod."cel.dev/expr"] @@ -50,6 +50,9 @@ cachePackages = ["cel.dev/expr", "cloud.google.com/go/compute/metadata", "dario. [mod."github.com/ProtonMail/go-crypto"] version = "v1.1.6" hash = "sha256-XlFT3uxgpPYFTND54uO8fH33jtQqAHWa7zrv24nw/PE=" + [mod."github.com/alecthomas/chroma/v2"] + version = "v2.20.0" + hash = "sha256-rL1mJS8fCltcii9w/efyyE4iyzogyjP+N80lE3CuzVE=" [mod."github.com/alecthomas/kong"] version = "v1.14.0" hash = "sha256-F6BYciiFpdtjKosD+L+z0Sc2s903iD2ElbytjcM4mas=" @@ -113,6 +116,9 @@ cachePackages = ["cel.dev/expr", "cloud.google.com/go/compute/metadata", "dario. [mod."github.com/aymanbagabas/go-osc52/v2"] version = "v2.0.1" hash = "sha256-6Bp0jBZ6npvsYcKZGHHIUSVSTAMEyieweAX2YAKDjjg=" + [mod."github.com/aymerick/douceur"] + version = "v0.2.0" + hash = "sha256-NiBX8EfOvLXNiK3pJaZX4N73YgfzdrzRXdiBFe3X3sE=" [mod."github.com/beorn7/perks"] version = "v1.0.1" hash = "sha256-h75GUqfwJKngCJQVE5Ao5wnO3cfKD9lSIteoLp/3xJ4=" @@ -134,15 +140,21 @@ cachePackages = ["cel.dev/expr", "cloud.google.com/go/compute/metadata", "dario. [mod."github.com/charmbracelet/colorprofile"] version = "v0.4.1" hash = "sha256-d/NjM/ybG+bGRRRMMcjbPCFGFS5noZRMaL05Ix5r/II=" + [mod."github.com/charmbracelet/glamour"] + version = "v1.0.0" + hash = "sha256-1sGgVA3QXJ2P5c/DNMb7R0HFG1X5vz9nmDhLrzKdgMw=" [mod."github.com/charmbracelet/lipgloss"] - version = "v1.1.0" - hash = "sha256-RHsRT2EZ1nDOElxAK+6/DC9XAaGVjDTgPvRh3pyCfY4=" + version = "v1.1.1-0.20250404203927-76690c660834" + hash = "sha256-CwS1AyoRsPOFA4SrC0CTtwLnbg57FmmSW/mvVQUFYcc=" [mod."github.com/charmbracelet/x/ansi"] version = "v0.11.6" hash = "sha256-UToZIkqXl9MEppcRgbeBqaaMeAzRkGa0w3lVUs6sxWI=" [mod."github.com/charmbracelet/x/cellbuf"] version = "v0.0.15" hash = "sha256-0S60XaWhKZG+TB3Kqe1oMn2Okwdq53nym8XayVSHHiM=" + [mod."github.com/charmbracelet/x/exp/slice"] + version = "v0.0.0-20250327172914-2fdc97757edf" + hash = "sha256-C1tksnevc/RdytJRQg5LQ0+VVSWlTwbNGic649m6E1Q=" [mod."github.com/charmbracelet/x/term"] version = "v0.2.2" hash = "sha256-KF7IU1Luxl/sZP6XjomWB2e3lxSUS4/5AahhapGir/4=" @@ -203,6 +215,9 @@ cachePackages = ["cel.dev/expr", "cloud.google.com/go/compute/metadata", "dario. [mod."github.com/distribution/reference"] version = "v0.6.0" hash = "sha256-gr4tL+qz4jKyAtl8LINcxMSanztdt+pybj1T+2ulQv4=" + [mod."github.com/dlclark/regexp2"] + version = "v1.11.5" + hash = "sha256-jN5+2ED+YbIoPIuyJ4Ou5pqJb2w1uNKzp5yTjKY6rEQ=" [mod."github.com/docker/cli"] version = "v29.4.0+incompatible" hash = "sha256-mUN7Fu9e4ahtUJBUvCHUk+ICFq1d6vs7MoJf0/cw+mA=" @@ -383,6 +398,9 @@ cachePackages = ["cel.dev/expr", "cloud.google.com/go/compute/metadata", "dario. [mod."github.com/google/uuid"] version = "v1.6.0" hash = "sha256-VWl9sqUzdOuhW0KzQlv0gwwUQClYkmZwSydHG2sALYw=" + [mod."github.com/gorilla/css"] + version = "v1.0.1" + hash = "sha256-6JwNHqlY2NpZ0pSQTyYPSpiNqjXOdFHqrUT10sv3y8A=" [mod."github.com/grpc-ecosystem/grpc-gateway/v2"] version = "v2.28.0" hash = "sha256-QeWb6jN6noeGPCzECgpUSb9YX9LzvKGwImEuX+A03gs=" @@ -443,6 +461,9 @@ cachePackages = ["cel.dev/expr", "cloud.google.com/go/compute/metadata", "dario. [mod."github.com/mattn/go-runewidth"] version = "v0.0.19" hash = "sha256-GpnbKplhX410Q/eIdknvWbYZgdav1keN+7wNUeOSMHE=" + [mod."github.com/microcosm-cc/bluemonday"] + version = "v1.0.27" + hash = "sha256-EZSya9FLPQ83CL7N2cZy21fdS35hViTkiMK5f3op8Es=" [mod."github.com/mitchellh/go-homedir"] version = "v1.1.0" hash = "sha256-oduBKXHAQG8X6aqLEpqZHs5DOKe84u6WkBwi4W6cv3k=" @@ -467,6 +488,9 @@ cachePackages = ["cel.dev/expr", "cloud.google.com/go/compute/metadata", "dario. [mod."github.com/muesli/cancelreader"] version = "v0.2.2" hash = "sha256-uEPpzwRJBJsQWBw6M71FDfgJuR7n55d/7IV8MO+rpwQ=" + [mod."github.com/muesli/reflow"] + version = "v0.3.0" + hash = "sha256-Pou2ybE9SFSZG6YfZLVV1Eyfm+X4FuVpDPLxhpn47Cc=" [mod."github.com/muesli/termenv"] version = "v0.16.0" hash = "sha256-hGo275DJlyLtcifSLpWnk8jardOksdeX9lH4lBeE3gI=" @@ -605,6 +629,12 @@ cachePackages = ["cel.dev/expr", "cloud.google.com/go/compute/metadata", "dario. [mod."github.com/xo/terminfo"] version = "v0.0.0-20220910002029-abceb7e1c41e" hash = "sha256-GyCDxxMQhXA3Pi/TsWXpA8cX5akEoZV7CFx4RO3rARU=" + [mod."github.com/yuin/goldmark"] + version = "v1.7.13" + hash = "sha256-vBCxZrPYPc8x/nvAAv3Au59dCCyfS80Vw3/a9EXK7TE=" + [mod."github.com/yuin/goldmark-emoji"] + version = "v1.0.6" + hash = "sha256-+d6bZzOPE+JSFsZbQNZMCWE+n3jgcQnkPETVk47mxSY=" [mod."go.opentelemetry.io/auto/sdk"] version = "v1.2.1" hash = "sha256-73bFYhnxNf4SfeQ52ebnwOWywdQbqc9lWawCcSgofvE=" diff --git a/internal/style/dark.json b/internal/style/dark.json new file mode 100644 index 0000000..ab64251 --- /dev/null +++ b/internal/style/dark.json @@ -0,0 +1,157 @@ +{ + "document": { + "block_prefix": "\n", + "margin": 2 + }, + "block_quote": { + "indent": 1, + "indent_token": "│ " + }, + "paragraph": {}, + "list": { + "level_indent": 2 + }, + "heading": { + "block_suffix": "\n", + "color": "#35d0ba", + "bold": true + }, + "text": {}, + "strikethrough": { + "crossed_out": true + }, + "emph": { + "italic": true + }, + "strong": { + "bold": true + }, + "hr": { + "color": "#35d0ba", + "format": "\n--------\n" + }, + "item": { + "block_prefix": "• " + }, + "enumeration": { + "block_prefix": ". " + }, + "task": { + "ticked": "[✓] ", + "unticked": "[ ] " + }, + "link": { + "color": "#35d0ba", + "underline": true + }, + "link_text": { + "color": "#35d0ba", + "bold": true + }, + "image": { + "underline": true + }, + "image_text": { + "format": "Image: {{.text}} →" + }, + "code": { + "color": "#35d0ba" + }, + "code_block": { + "margin": 2, + "chroma": { + "text": {}, + "error": { + "color": "#f3807b", + "background_color": "#030724" + }, + "comment": { + "color": "#F7D186" + }, + "comment_preproc": { + "color": "#FF875F" + }, + "keyword": { + "color": "#00AAFF" + }, + "keyword_reserved": { + "color": "#FF5FD2" + }, + "keyword_namespace": { + "color": "#FF5F87" + }, + "keyword_type": { + "color": "#6E6ED8" + }, + "operator": { + "color": "#EF8080" + }, + "punctuation": { + "color": "#E8E8A8" + }, + "name": { + "color": "#C4C4C4" + }, + "name_builtin": { + "color": "#FF8EC7" + }, + "name_tag": { + "color": "#B083EA" + }, + "name_attribute": { + "color": "#7A7AE6" + }, + "name_class": { + "color": "#F1F1F1", + "underline": true, + "bold": true + }, + "name_constant": {}, + "name_decorator": { + "color": "#FFFF87" + }, + "name_exception": {}, + "name_function": { + "color": "#00D787" + }, + "name_other": {}, + "literal": {}, + "literal_number": { + "color": "#6EEFC0" + }, + "literal_date": {}, + "literal_string": { + "color": "#C69669" + }, + "literal_string_escape": { + "color": "#AFFFD7" + }, + "generic_deleted": { + "color": "#FD5B5B" + }, + "generic_emph": { + "italic": true + }, + "generic_inserted": { + "color": "#00D787" + }, + "generic_strong": { + "bold": true + }, + "generic_subheading": { + "color": "#777777" + }, + "background": { + "background_color": "#373737" + } + } + }, + "table": {}, + "definition_list": {}, + "definition_term": {}, + "definition_description": { + "block_prefix": "\n🠶 " + }, + "html_block": {}, + "html_span": {} +} diff --git a/internal/style/light.json b/internal/style/light.json new file mode 100644 index 0000000..09d4f4a --- /dev/null +++ b/internal/style/light.json @@ -0,0 +1,157 @@ +{ + "document": { + "block_prefix": "\n", + "margin": 2 + }, + "block_quote": { + "indent": 1, + "indent_token": "│ " + }, + "paragraph": {}, + "list": { + "level_indent": 2 + }, + "heading": { + "block_suffix": "\n", + "color": "#183d54", + "bold": true + }, + "text": {}, + "strikethrough": { + "crossed_out": true + }, + "emph": { + "italic": true + }, + "strong": { + "bold": true + }, + "hr": { + "color": "#183d54", + "format": "\n--------\n" + }, + "item": { + "block_prefix": "• " + }, + "enumeration": { + "block_prefix": ". " + }, + "task": { + "ticked": "[✓] ", + "unticked": "[ ] " + }, + "link": { + "color": "#183d54", + "underline": true + }, + "link_text": { + "color": "#183d54", + "bold": true + }, + "image": { + "underline": true + }, + "image_text": { + "format": "Image: {{.text}} →" + }, + "code": { + "color": "#183d54" + }, + "code_block": { + "margin": 2, + "chroma": { + "text": {}, + "error": { + "color": "#f3807b", + "background_color": "#030724" + }, + "comment": { + "color": "#183d54" + }, + "comment_preproc": { + "color": "#FF875F" + }, + "keyword": { + "color": "#279EFC" + }, + "keyword_reserved": { + "color": "#FF5FD2" + }, + "keyword_namespace": { + "color": "#FB406F" + }, + "keyword_type": { + "color": "#7049C2" + }, + "operator": { + "color": "#FF2626" + }, + "punctuation": { + "color": "#FA7878" + }, + "name": {}, + "name_builtin": { + "color": "#0A1BB1" + }, + "name_tag": { + "color": "#581290" + }, + "name_attribute": { + "color": "#8362CB" + }, + "name_class": { + "color": "#212121", + "underline": true, + "bold": true + }, + "name_constant": { + "color": "#581290" + }, + "name_decorator": { + "color": "#A3A322" + }, + "name_exception": {}, + "name_function": { + "color": "#019F57" + }, + "name_other": {}, + "literal": {}, + "literal_number": { + "color": "#22CCAE" + }, + "literal_date": {}, + "literal_string": { + "color": "#7E5B38" + }, + "literal_string_escape": { + "color": "#00AEAE" + }, + "generic_deleted": { + "color": "#FD5B5B" + }, + "generic_emph": { + "italic": true + }, + "generic_inserted": { + "color": "#00D787" + }, + "generic_strong": { + "bold": true + }, + "generic_subheading": { + "color": "#777777" + }, + "background": { + "background_color": "#373737" + } + } + }, + "table": {}, + "definition_list": {}, + "definition_term": {}, + "definition_description": { + "block_prefix": "\n🠶 " + }, + "html_block": {}, + "html_span": {} +} diff --git a/internal/style/style.go b/internal/style/style.go new file mode 100644 index 0000000..ad58c45 --- /dev/null +++ b/internal/style/style.go @@ -0,0 +1,70 @@ +/* +Copyright 2026 The Crossplane Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package style contains the shared style for the Crossplane CLI. +package style + +import ( + "os" + + "github.com/charmbracelet/glamour" + "github.com/charmbracelet/glamour/styles" + "github.com/charmbracelet/x/term" + "github.com/muesli/termenv" + + _ "embed" +) + +// RenderMarkdown formats markdown-formatted text for output to the terminal. If +// anything fails, the raw markdown is returned. +func RenderMarkdown(md string) string { + wrapWidth, _, _ := term.GetSize(os.Stdout.Fd()) + wrapWidth = min(wrapWidth, 120) + + tr, err := glamour.NewTermRenderer( + getStyleOpt(), + glamour.WithWordWrap(wrapWidth), + ) + if err != nil { + return md + } + + formatted, err := tr.Render(md) + if err != nil { + return md + } + + return formatted +} + +var ( + //go:embed light.json + lightStylesheet []byte + //go:embed dark.json + darkStylesheet []byte +) + +func getStyleOpt() glamour.TermRendererOption { + if !term.IsTerminal(os.Stdout.Fd()) { + return glamour.WithStandardStyle(styles.AsciiStyle) + } + + if termenv.HasDarkBackground() { + return glamour.WithStylesFromJSONBytes(darkStylesheet) + } + + return glamour.WithStylesFromJSONBytes(lightStylesheet) +} From 339e4080472ffb42cf017ed3213af034453cf89a Mon Sep 17 00:00:00 2001 From: Adam Wolfe Gordon Date: Thu, 14 May 2026 16:58:43 -0600 Subject: [PATCH 2/2] Add a command to generate docs Add `crossplane generate-docs`, which generates a markdown file following the format of the existing CLI reference page in crossplane/docs. The generated file includes full help (summary, details, flags, etc.) for all commands. Signed-off-by: Adam Wolfe Gordon --- .../docs-templates/command-reference.md.tmpl | 45 +++ cmd/crossplane/docs.go | 257 ++++++++++++++++++ cmd/crossplane/main.go | 3 + 3 files changed, 305 insertions(+) create mode 100644 cmd/crossplane/docs-templates/command-reference.md.tmpl create mode 100644 cmd/crossplane/docs.go diff --git a/cmd/crossplane/docs-templates/command-reference.md.tmpl b/cmd/crossplane/docs-templates/command-reference.md.tmpl new file mode 100644 index 0000000..b1ff98c --- /dev/null +++ b/cmd/crossplane/docs-templates/command-reference.md.tmpl @@ -0,0 +1,45 @@ +--- +weight: 50 +title: Command Reference +description: "Command reference for the Crossplane CLI" +--- + + + +This documentation is for the `crossplane` CLI [[ .Version ]]. + +[[ range .Commands ]] + + +[[ .Heading ]] [[ .FullPath ]] + + + +[[ if .Help ]][[ .Help ]][[ end ]] + +[[ if .Detail ]][[ .Detail ]][[ end ]] + +[[ .SubHeading ]] Usage + +``` +crossplane [[ .Summary ]] +``` +[[- if .Positional ]] +[[ .SubHeading ]] Arguments + +{{< table "table table-sm table-striped" >}} +| Argument | Description | +|----------|-------------| +[[ range .Positional ]]| `[[ .Display ]]` | [[ if not .Required ]]*(optional)* [[ end ]][[ .Help ]] | +[[ end ]]{{< /table >}} +[[ end ]] +[[- if .Flags ]] +[[ .SubHeading ]] Flags + +{{< table "table table-sm table-striped" >}} +| Short flag | Long flag | Description | +|------------|-----------|-------------| +[[ range .Flags ]]| [[ if .Short ]]`[[ .Short ]]`[[ end ]] | `[[ .Long ]]` | [[ if .Required ]]**Required.** [[ end ]][[ .Help ]] | +[[ end ]]{{< /table >}} +[[ end ]] +[[ end ]] diff --git a/cmd/crossplane/docs.go b/cmd/crossplane/docs.go new file mode 100644 index 0000000..2ab4591 --- /dev/null +++ b/cmd/crossplane/docs.go @@ -0,0 +1,257 @@ +/* +Copyright 2026 The Crossplane Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package main + +import ( + "bytes" + "fmt" + "os" + "regexp" + "slices" + "strings" + "text/template" + + "github.com/alecthomas/kong" + + "github.com/crossplane/crossplane-runtime/v2/pkg/version" + + _ "embed" +) + +//go:embed docs-templates/command-reference.md.tmpl +var docsTmpl string + +type docsCmd struct { + OutputFile string `default:"command-reference.md" help:"Path to write the generated command-reference markdown file." name:"output-file" short:"o" type:"path"` + + tmpl *template.Template +} + +// AfterApply prepares the template for execution. +func (d *docsCmd) AfterApply() error { + // Use [[ ]] as the action delimiters so the template can contain Hugo + // shortcodes like {{< table >}} without conflict. + t, err := template.New("docs").Delims("[[", "]]").Parse(docsTmpl) + if err != nil { + return err + } + d.tmpl = t + return nil +} + +// docsPositional describes a positional argument in the generated docs. +type docsPositional struct { + Display string + Help string + Required bool +} + +// docsFlag describes a flag in the generated docs. +type docsFlag struct { + Long string + Short string + Help string + Required bool +} + +// docsCommand is the per-command template input. +type docsCommand struct { + FullPath string + Heading string + SubHeading string + Help string + Detail string + Summary string + Positional []docsPositional + Flags []docsFlag +} + +// docsInput is the top-level template input. +type docsInput struct { + Version string + Commands []docsCommand +} + +// Run walks the kong model and writes the generated docs file. +func (d *docsCmd) Run(ctx *kong.Context) error { + root := ctx.Model.Node + + ver := version.New().GetVersionString() + if ver == "" { + ver = "(development build)" + } + input := docsInput{ + Version: ver, + } + + if err := traverseChildren(root, func(n *kong.Node) error { + input.Commands = append(input.Commands, buildDocsCommand(n)) + return nil + }); err != nil { + return err + } + + slices.SortFunc(input.Commands, func(a, b docsCommand) int { + return strings.Compare(a.FullPath, b.FullPath) + }) + + var buf bytes.Buffer + if err := d.tmpl.Execute(&buf, input); err != nil { + return err + } + return os.WriteFile(d.OutputFile, buf.Bytes(), 0o644) //nolint:gosec // 0644 is a fine mode for docs. +} + +func buildDocsCommand(n *kong.Node) docsCommand { + headingLevel := min(depth(n)+1, 6) + dc := docsCommand{ + FullPath: n.FullPath(), + Heading: strings.Repeat("#", headingLevel), + SubHeading: strings.Repeat("#", min(headingLevel+1, 6)), + Help: n.Help, + Detail: normalizeDetail(n.Detail, headingLevel), + Summary: n.Summary(), + } + for _, p := range n.Positional { + dc.Positional = append(dc.Positional, docsPositional{ + Display: p.Summary(), + Help: p.Help, + Required: p.Required, + }) + } + for _, f := range n.Flags { + if f.Hidden { + continue + } + df := docsFlag{ + Long: "--" + f.Name, + Help: f.Help, + Required: f.Required, + } + if f.Short != 0 { + df.Short = "-" + string(f.Short) + } + // Append the placeholder for non-bool, non-counter flags so the docs + // look like the CLI help. + if !f.IsBool() && !f.IsCounter() { + df.Long = fmt.Sprintf("--%s=%s", f.Name, f.FormatPlaceHolder()) + } + dc.Flags = append(dc.Flags, df) + } + return dc +} + +// normalizeDetail prepares embedded help markdown for inclusion in the +// generated Hugo docs page by: +// +// 1. Demoting headings as needed so the content nests below the command's +// heading at headingLevel. +// 2. Replacing any special blockquotes with pretty hugo ones. +// 3. Adding pretty hugo table annotations to tables. +func normalizeDetail(detail string, headingLevel int) string { + detail = strings.TrimSpace(detail) + if headingLevel == 0 { + return detail + } + + // We'll demote each heading so that it's at least headingLevel+1 + // deep. I.e., nesting an H1 under an H1 results in an H2. + demote := headingLevel - 1 + lines := strings.SplitSeq(detail, "\n") + + var ( + sb strings.Builder + codeBlock = false + bq = false + table = false + ) + for line := range lines { + // Skip any lines in a code block (```). + if strings.HasPrefix(line, "```") { + codeBlock = !codeBlock + sb.WriteString(line + "\n") + continue + } + if codeBlock { + sb.WriteString(line + "\n") + continue + } + + // Demote headings, capping at H6. + if strings.HasPrefix(line, "#") { + line = strings.Repeat("#", demote) + line + } + + // Convert special blockquotes into pretty Hugo blocks. + bqRE := regexp.MustCompile(`^> \*\*(\w+):\*\* `) + bqMatch := bqRE.FindStringSubmatch(line) + if bqMatch != nil { + bq = true + fmt.Fprintf(&sb, "{{}}\n", strings.ToLower(bqMatch[1])) + line = strings.TrimPrefix(line, bqMatch[0]) + sb.WriteString(line + "\n") + continue + } + if bq { + if !strings.HasPrefix(line, ">") { + sb.WriteString("{{< /hint >}}\n") + bq = false + } + line = strings.TrimSpace(strings.TrimPrefix(line, ">")) + } + + // Add pretty table markers to tables. + if strings.HasPrefix(line, "|") && !table { + table = true + sb.WriteString("{{}}\n") + } + if table && !strings.HasPrefix(line, "|") { + sb.WriteString("{{< /table >}}\n") + table = false + } + + sb.WriteString(line + "\n") + } + + return strings.TrimSpace(sb.String()) +} + +func depth(n *kong.Node) int { + d := 0 + for cur := n.Parent; cur != nil; cur = cur.Parent { + d++ + } + return d +} + +// traverseChildren walks the kong tree calling fn on each non-hidden node. +func traverseChildren(root *kong.Node, fn func(*kong.Node) error) error { + root.Aliases = nil + + if root.Hidden { + return nil + } + if err := fn(root); err != nil { + return err + } + for _, node := range root.Children { + if err := traverseChildren(node, fn); err != nil { + return err + } + } + return nil +} diff --git a/cmd/crossplane/main.go b/cmd/crossplane/main.go index c5dfd07..9a19a2e 100644 --- a/cmd/crossplane/main.go +++ b/cmd/crossplane/main.go @@ -78,6 +78,9 @@ type cli struct { // Hidden top-level alias for render, since it's GA but has moved. Render renderxr.Cmd `cmd:"" help:"Render Crossplane compositions locally using functions." hidden:""` + // Hidden command to generate the command-reference docs page. + GenerateDocs docsCmd `cmd:"" help:"Generate command-reference docs in markdown format." hidden:""` + // Flags. ConfigPath string `env:"CROSSPLANE_CONFIG" help:"Path to the crossplane CLI config file." name:"config" placeholder:"PATH"` Verbose verboseFlag `help:"Print verbose logging statements." name:"verbose"`