|
| 1 | +/* |
| 2 | +Copyright 2024 The Karmada Authors. |
| 3 | +
|
| 4 | +Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | +you may not use this file except in compliance with the License. |
| 6 | +You may obtain a copy of the License at |
| 7 | +
|
| 8 | + http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | +
|
| 10 | +Unless required by applicable law or agreed to in writing, software |
| 11 | +distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | +See the License for the specific language governing permissions and |
| 14 | +limitations under the License. |
| 15 | +*/ |
| 16 | + |
| 17 | +package explain |
| 18 | + |
| 19 | +import ( |
| 20 | + "fmt" |
| 21 | + |
| 22 | + "github.com/spf13/cobra" |
| 23 | + "k8s.io/cli-runtime/pkg/genericiooptions" |
| 24 | + kubectlexplain "k8s.io/kubectl/pkg/cmd/explain" |
| 25 | + cmdutil "k8s.io/kubectl/pkg/cmd/util" |
| 26 | + "k8s.io/kubectl/pkg/util/templates" |
| 27 | + |
| 28 | + "github.com/karmada-io/karmada/pkg/karmadactl/options" |
| 29 | + "github.com/karmada-io/karmada/pkg/karmadactl/util" |
| 30 | +) |
| 31 | + |
| 32 | +var ( |
| 33 | + explainLong = templates.LongDesc(` |
| 34 | + Describe fields and structure of various resources in Karmada control plane or a member cluster. |
| 35 | +
|
| 36 | + This command describes the fields associated with each supported API resource. |
| 37 | + Fields are identified via a simple JSONPath identifier: |
| 38 | +
|
| 39 | + <type>.<fieldName>[.<fieldName>] |
| 40 | +
|
| 41 | + Information about each field is retrieved from the server in OpenAPI format.`) |
| 42 | + |
| 43 | + explainExamples = templates.Examples(` |
| 44 | + # Get the documentation of the resource and its fields in Karmada control plane |
| 45 | + %[1]s explain propagationpolicies |
| 46 | +
|
| 47 | + # Get all the fields in the resource in member cluster member1 |
| 48 | + %[1]s explain pods --recursive --operation-scope=members --cluster=member1 |
| 49 | +
|
| 50 | + # Get the explanation for resourcebindings in supported api versions in Karmada control plane |
| 51 | + %[1]s explain resourcebindings --api-version=work.karmada.io/v1alpha1 |
| 52 | +
|
| 53 | + # Get the documentation of a specific field of a resource in member cluster member1 |
| 54 | + %[1]s explain pods.spec.containers --operation-scope=members --cluster=member1 |
| 55 | + |
| 56 | + # Get the documentation of resources in different format in Karmada control plane |
| 57 | + %[1]s explain clusterpropagationpolicies --output=plaintext-openapiv2`) |
| 58 | + plaintextTemplateName = "plaintext" |
| 59 | +) |
| 60 | + |
| 61 | +// NewCmdExplain new explain command. |
| 62 | +func NewCmdExplain(f util.Factory, parentCommand string, streams genericiooptions.IOStreams) *cobra.Command { |
| 63 | + var o CommandExplainOptions |
| 64 | + o.ExplainOptions = kubectlexplain.NewExplainOptions(parentCommand, streams) |
| 65 | + |
| 66 | + cmd := &cobra.Command{ |
| 67 | + Use: "explain TYPE [--recursive=FALSE|TRUE] [--api-version=api-version-group] [--output=plaintext|plaintext-openapiv2] ", |
| 68 | + DisableFlagsInUseLine: true, |
| 69 | + Short: "Get documentation for a resource", |
| 70 | + Long: fmt.Sprintf(explainLong, parentCommand), |
| 71 | + Example: fmt.Sprintf(explainExamples, parentCommand), |
| 72 | + Run: func(cmd *cobra.Command, args []string) { |
| 73 | + cmdutil.CheckErr(o.Complete(f, cmd, args)) |
| 74 | + cmdutil.CheckErr(o.Validate()) |
| 75 | + cmdutil.CheckErr(o.Run()) |
| 76 | + }, |
| 77 | + } |
| 78 | + |
| 79 | + flags := cmd.Flags() |
| 80 | + o.OperationScope = options.KarmadaControlPlane |
| 81 | + flags.Var(&o.OperationScope, "operation-scope", "Used to control the operation scope of the command. The optional values are karmada and members. Defaults to karmada.") |
| 82 | + flags.BoolVar(&o.Recursive, "recursive", o.Recursive, "When true, print the name of all the fields recursively. Otherwise, print the available fields with their description.") |
| 83 | + flags.StringVar(&o.APIVersion, "api-version", o.APIVersion, "Use given api-version (group/version) of the resource.") |
| 84 | + |
| 85 | + // Only enable --output as a valid flag if the feature is enabled |
| 86 | + flags.StringVar(&o.OutputFormat, "output", plaintextTemplateName, "Format in which to render the schema. Valid values are: (plaintext, plaintext-openapiv2).") |
| 87 | + |
| 88 | + flags.StringVarP(options.DefaultConfigFlags.Namespace, "namespace", "n", *options.DefaultConfigFlags.Namespace, "If present, the namespace scope for this CLI request") |
| 89 | + flags.StringVar(&o.Cluster, "cluster", "", "Used to specify a target member cluster and only takes effect when the command's operation scope is member clusters, for example: --operation-scope=all --cluster=member1") |
| 90 | + return cmd |
| 91 | +} |
| 92 | + |
| 93 | +// CommandExplainOptions contains the input to the explain command. |
| 94 | +type CommandExplainOptions struct { |
| 95 | + // flags specific to explain |
| 96 | + *kubectlexplain.ExplainOptions |
| 97 | + Cluster string |
| 98 | + OperationScope options.OperationScope |
| 99 | +} |
| 100 | + |
| 101 | +// Complete ensures that options are valid and marshals them if necessary |
| 102 | +func (o *CommandExplainOptions) Complete(f util.Factory, cmd *cobra.Command, args []string) error { |
| 103 | + var explainFactory cmdutil.Factory = f |
| 104 | + if o.OperationScope == options.Members && len(o.Cluster) != 0 { |
| 105 | + memberFactory, err := f.FactoryForMemberCluster(o.Cluster) |
| 106 | + if err != nil { |
| 107 | + return err |
| 108 | + } |
| 109 | + explainFactory = memberFactory |
| 110 | + } |
| 111 | + |
| 112 | + return o.ExplainOptions.Complete(explainFactory, cmd, args) |
| 113 | +} |
| 114 | + |
| 115 | +// Validate checks that the provided explain options are specified |
| 116 | +func (o *CommandExplainOptions) Validate() error { |
| 117 | + err := options.VerifyOperationScopeFlags(o.OperationScope, options.KarmadaControlPlane, options.Members) |
| 118 | + if err != nil { |
| 119 | + return err |
| 120 | + } |
| 121 | + if o.OperationScope == options.Members && len(o.Cluster) == 0 { |
| 122 | + return fmt.Errorf("must specify a member cluster") |
| 123 | + } |
| 124 | + return o.ExplainOptions.Validate() |
| 125 | +} |
| 126 | + |
| 127 | +// Run executes the appropriate steps to print a model's documentation |
| 128 | +func (o *CommandExplainOptions) Run() error { |
| 129 | + return o.ExplainOptions.Run() |
| 130 | +} |
0 commit comments