From a906462aecb687befedd66764260ca8b38457e13 Mon Sep 17 00:00:00 2001 From: hulizhe Date: Sat, 17 Aug 2024 19:23:08 +0800 Subject: [PATCH] add new command karmadactl api-resources Signed-off-by: hulizhe --- pkg/karmadactl/apiresources/apiresources.go | 121 ++++++++++++++++++++ pkg/karmadactl/apiresources/apiversions.go | 100 ++++++++++++++++ pkg/karmadactl/karmadactl.go | 8 ++ 3 files changed, 229 insertions(+) create mode 100644 pkg/karmadactl/apiresources/apiresources.go create mode 100644 pkg/karmadactl/apiresources/apiversions.go diff --git a/pkg/karmadactl/apiresources/apiresources.go b/pkg/karmadactl/apiresources/apiresources.go new file mode 100644 index 000000000000..9ada6b845f11 --- /dev/null +++ b/pkg/karmadactl/apiresources/apiresources.go @@ -0,0 +1,121 @@ +/* +Copyright 2024 The Karmada 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 apiresources + +import ( + "fmt" + + "github.com/spf13/cobra" + "k8s.io/cli-runtime/pkg/genericiooptions" + kubectlapiresources "k8s.io/kubectl/pkg/cmd/apiresources" + cmdutil "k8s.io/kubectl/pkg/cmd/util" + "k8s.io/kubectl/pkg/util/templates" + + "github.com/karmada-io/karmada/pkg/karmadactl/options" + "github.com/karmada-io/karmada/pkg/karmadactl/util" +) + +var ( + apiresourcesExample = templates.Examples(` + # Print the supported API resources in Karmada control plane + %[1]s api-resources + + # Print the supported API resources with more information in cluster(member1) + %[1]s api-resources -o wide --operation-scope=members --cluster=member1 + + # Print the supported API resources sorted by a column in Karmada control plane + %[1]s api-resources --sort-by=name + + # Print the supported namespaced resources in Karmada control plane + %[1]s api-resources --namespaced=true + + # Print the supported non-namespaced resources in Karmada control plane + %[1]s api-resources --namespaced=false + + # Print the supported API resources with a specific APIGroup in Karmada control plane + %[1]s api-resources --api-group=rbac.authorization.k8s.io`) +) + +// NewCmdAPIResources creates the api-resources command +func NewCmdAPIResources(f util.Factory, parentCommand string, ioStreams genericiooptions.IOStreams) *cobra.Command { + var o CommandAPIResourcesOptions + o.APIResourceOptions = kubectlapiresources.NewAPIResourceOptions(ioStreams) + + cmd := &cobra.Command{ + Use: "api-resources", + Short: "Print the supported API resources on the server", + Long: "Print the supported API resources on the server.", + Example: fmt.Sprintf(apiresourcesExample, parentCommand), + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.RunAPIResources()) + }, + } + + o.OperationScope = options.KarmadaControlPlane + cmd.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.") + cmd.Flags().StringVarP(&o.Cluster, "cluster", "C", "", "Used to specify a target member cluster and only takes effect when the command's operation scope is member clusters, for example: --operation-scope=members --cluster=member1") + cmd.Flags().BoolVar(&o.NoHeaders, "no-headers", o.NoHeaders, "When using the default or custom-column output format, don't print headers (default print headers).") + cmd.Flags().StringVarP(&o.Output, "output", "o", o.Output, `Output format. One of: (wide, name).`) + + cmd.Flags().StringVar(&o.APIGroup, "api-group", o.APIGroup, "Limit to resources in the specified API group.") + cmd.Flags().BoolVar(&o.Namespaced, "namespaced", o.Namespaced, "If false, non-namespaced resources will be returned, otherwise returning namespaced resources by default.") + cmd.Flags().StringSliceVar(&o.Verbs, "verbs", o.Verbs, "Limit to resources that support the specified verbs.") + cmd.Flags().StringVar(&o.SortBy, "sort-by", o.SortBy, "If non-empty, sort list of resources using specified field. The field can be either 'name' or 'kind'.") + cmd.Flags().BoolVar(&o.Cached, "cached", o.Cached, "Use the cached list of resources if available.") + cmd.Flags().StringSliceVar(&o.Categories, "categories", o.Categories, "Limit to resources that belong to the specified categories.") + return cmd +} + +// CommandAPIResourcesOptions contains the input to the api-resources command. +type CommandAPIResourcesOptions struct { + // flags specific to describe + *kubectlapiresources.APIResourceOptions + Cluster string + OperationScope options.OperationScope +} + +// Complete adapts from the command line args and validates them +func (o *CommandAPIResourcesOptions) Complete(f util.Factory, cmd *cobra.Command, args []string) error { + var apiFactory cmdutil.Factory = f + if o.OperationScope == options.Members && len(o.Cluster) != 0 { + memberFactory, err := f.FactoryForMemberCluster(o.Cluster) + if err != nil { + return err + } + apiFactory = memberFactory + } + return o.APIResourceOptions.Complete(apiFactory, cmd, args) +} + +// Validate checks to the APIResourceOptions to see if there is sufficient information run the command +func (o *CommandAPIResourcesOptions) Validate() error { + err := options.VerifyOperationScopeFlags(o.OperationScope, options.KarmadaControlPlane, options.Members) + if err != nil { + return err + } + if o.OperationScope == options.Members && len(o.Cluster) == 0 { + return fmt.Errorf("must specify a member cluster") + } + return o.APIResourceOptions.Validate() +} + +// Run does the work +func (o *CommandAPIResourcesOptions) Run() error { + return o.APIResourceOptions.RunAPIResources() +} diff --git a/pkg/karmadactl/apiresources/apiversions.go b/pkg/karmadactl/apiresources/apiversions.go new file mode 100644 index 000000000000..34bbddaee0ce --- /dev/null +++ b/pkg/karmadactl/apiresources/apiversions.go @@ -0,0 +1,100 @@ +/* +Copyright 2024 The Karmada 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 apiresources + +import ( + "fmt" + + "github.com/spf13/cobra" + "k8s.io/cli-runtime/pkg/genericiooptions" + kubectlapiresources "k8s.io/kubectl/pkg/cmd/apiresources" + cmdutil "k8s.io/kubectl/pkg/cmd/util" + "k8s.io/kubectl/pkg/util/templates" + + "github.com/karmada-io/karmada/pkg/karmadactl/options" + "github.com/karmada-io/karmada/pkg/karmadactl/util" +) + +var ( + apiversionsExample = templates.Examples(` + # Print the supported API versions + %[1]s api-versions + + # Print the supported API versions in cluster(member1) + %[1]s api-versions --operation-scope=members --cluster=member1`) +) + +// NewCmdAPIVersions creates the api-versions command +func NewCmdAPIVersions(f util.Factory, parentCommand string, ioStreams genericiooptions.IOStreams) *cobra.Command { + var o CommandAPIVersionsOptions + o.APIVersionsOptions = kubectlapiresources.NewAPIVersionsOptions(ioStreams) + cmd := &cobra.Command{ + Use: "api-versions", + Short: "Print the supported API versions on the server, in the form of \"group/version\"", + Long: "Print the supported API versions on the server, in the form of \"group/version\".", + Example: fmt.Sprintf(apiversionsExample, parentCommand), + DisableFlagsInUseLine: true, + Run: func(cmd *cobra.Command, args []string) { + cmdutil.CheckErr(o.Complete(f, cmd, args)) + cmdutil.CheckErr(o.Validate()) + cmdutil.CheckErr(o.RunAPIVersions()) + }, + } + + o.OperationScope = options.KarmadaControlPlane + cmd.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.") + cmd.Flags().StringVarP(&o.Cluster, "cluster", "C", "", "Used to specify a target member cluster and only takes effect when the command's operation scope is member clusters, for example: --operation-scope=members --cluster=member1") + return cmd +} + +// CommandAPIVersionsOptions contains the input to the api-versions command. +type CommandAPIVersionsOptions struct { + // flags specific to api-versions + *kubectlapiresources.APIVersionsOptions + Cluster string + OperationScope options.OperationScope +} + +// Complete adapts from the command line args and factory to the data required +func (o *CommandAPIVersionsOptions) Complete(f util.Factory, cmd *cobra.Command, args []string) error { + var apiFactory cmdutil.Factory = f + if o.OperationScope == options.Members && len(o.Cluster) != 0 { + memberFactory, err := f.FactoryForMemberCluster(o.Cluster) + if err != nil { + return err + } + apiFactory = memberFactory + } + return o.APIVersionsOptions.Complete(apiFactory, cmd, args) +} + +// Validate checks to the APIVersionsOptions to see if there is sufficient information run the command +func (o *CommandAPIVersionsOptions) Validate() error { + err := options.VerifyOperationScopeFlags(o.OperationScope, options.KarmadaControlPlane, options.Members) + if err != nil { + return err + } + if o.OperationScope == options.Members && len(o.Cluster) == 0 { + return fmt.Errorf("must specify a member cluster") + } + return nil +} + +// Run does the work +func (o *CommandAPIVersionsOptions) Run() error { + return o.APIVersionsOptions.RunAPIVersions() +} diff --git a/pkg/karmadactl/karmadactl.go b/pkg/karmadactl/karmadactl.go index 87ab2573f075..ce1c61ff52ed 100644 --- a/pkg/karmadactl/karmadactl.go +++ b/pkg/karmadactl/karmadactl.go @@ -29,6 +29,7 @@ import ( "k8s.io/kubectl/pkg/util/templates" "github.com/karmada-io/karmada/pkg/karmadactl/addons" + "github.com/karmada-io/karmada/pkg/karmadactl/apiresources" "github.com/karmada-io/karmada/pkg/karmadactl/apply" "github.com/karmada-io/karmada/pkg/karmadactl/cmdinit" "github.com/karmada-io/karmada/pkg/karmadactl/cordon" @@ -126,6 +127,13 @@ func NewKarmadaCtlCommand(cmdUse, parentCommand string) *cobra.Command { top.NewCmdTop(f, parentCommand, ioStreams), }, }, + { + Message: "Other Commands:", + Commands: []*cobra.Command{ + apiresources.NewCmdAPIResources(f, parentCommand, ioStreams), + apiresources.NewCmdAPIVersions(f, parentCommand, ioStreams), + }, + }, } groups.Add(rootCmd)