mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
remove printer helpers
This commit is contained in:
parent
d7d4381961
commit
5a34e4f594
@ -90,8 +90,10 @@ func NewCmdApiResources(f cmdutil.Factory, ioStreams genericclioptions.IOStreams
|
||||
cmdutil.CheckErr(o.RunApiResources(cmd, f))
|
||||
},
|
||||
}
|
||||
cmdutil.AddOutputFlags(cmd)
|
||||
cmdutil.AddNoHeadersFlags(cmd)
|
||||
|
||||
cmd.Flags().Bool("no-headers", false, "When using the default or custom-column output format, don't print headers (default print headers).")
|
||||
cmd.Flags().StringP("output", "o", "", "Output format. One of: wide|name.")
|
||||
|
||||
cmd.Flags().StringVar(&o.APIGroup, "api-group", "", "Limit to resources in the specified API group.")
|
||||
cmd.Flags().BoolVar(&o.Namespaced, "namespaced", true, "Namespaced indicates if a resource is namespaced or not.")
|
||||
cmd.Flags().StringSliceVar(&o.Verbs, "verbs", o.Verbs, "Limit to resources that support the specified verbs.")
|
||||
|
@ -102,8 +102,9 @@ func NewCmdApplySetLastApplied(f cmdutil.Factory, ioStreams genericclioptions.IO
|
||||
},
|
||||
}
|
||||
|
||||
o.PrintFlags.AddFlags(cmd)
|
||||
|
||||
cmdutil.AddDryRunFlag(cmd)
|
||||
cmdutil.AddPrinterFlags(cmd)
|
||||
cmd.Flags().BoolVar(&o.CreateAnnotation, "create-annotation", o.CreateAnnotation, "Will create 'last-applied-configuration' annotations if current objects doesn't have one")
|
||||
kubectl.AddJsonFilenameFlag(cmd, &o.FilenameOptions.Filenames, "Filename, directory, or URL to files that contains the last-applied-configuration annotations")
|
||||
|
||||
|
@ -1121,7 +1121,7 @@ func TestRunApplySetLastApplied(t *testing.T) {
|
||||
name: "set with exist object",
|
||||
filePath: filenameRC,
|
||||
expectedErr: "",
|
||||
expectedOut: "replicationcontroller/test-rc configured\n",
|
||||
expectedOut: "replicationcontroller/test-rc\n",
|
||||
output: "name",
|
||||
},
|
||||
{
|
||||
@ -1142,14 +1142,14 @@ func TestRunApplySetLastApplied(t *testing.T) {
|
||||
name: "set with exist object output json",
|
||||
filePath: filenameRCJSON,
|
||||
expectedErr: "",
|
||||
expectedOut: "replicationcontroller/test-rc configured\n",
|
||||
expectedOut: "replicationcontroller/test-rc\n",
|
||||
output: "name",
|
||||
},
|
||||
{
|
||||
name: "set test for a directory of files",
|
||||
filePath: dirName,
|
||||
expectedErr: "",
|
||||
expectedOut: "replicationcontroller/test-rc configured\nreplicationcontroller/test-rc configured\n",
|
||||
expectedOut: "replicationcontroller/test-rc\nreplicationcontroller/test-rc\n",
|
||||
output: "name",
|
||||
},
|
||||
}
|
||||
|
@ -24,7 +24,9 @@ go_library(
|
||||
"//pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion:go_default_library",
|
||||
"//pkg/kubectl/cmd/templates:go_default_library",
|
||||
"//pkg/kubectl/cmd/util:go_default_library",
|
||||
"//pkg/kubectl/genericclioptions:go_default_library",
|
||||
"//pkg/kubectl/resource:go_default_library",
|
||||
"//pkg/printers:go_default_library",
|
||||
"//pkg/registry/rbac/reconciliation:go_default_library",
|
||||
"//vendor/github.com/golang/glog:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||
|
@ -17,24 +17,23 @@ limitations under the License.
|
||||
package auth
|
||||
|
||||
import (
|
||||
"io"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
)
|
||||
|
||||
func NewCmdAuth(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
||||
func NewCmdAuth(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
|
||||
// Parent command to which all subcommands are added.
|
||||
cmds := &cobra.Command{
|
||||
Use: "auth",
|
||||
Short: "Inspect authorization",
|
||||
Long: `Inspect authorization`,
|
||||
Run: cmdutil.DefaultSubCommandRun(errOut),
|
||||
Run: cmdutil.DefaultSubCommandRun(streams.ErrOut),
|
||||
}
|
||||
|
||||
cmds.AddCommand(NewCmdCanI(f, out, errOut))
|
||||
cmds.AddCommand(NewCmdReconcile(f, out, errOut))
|
||||
cmds.AddCommand(NewCmdCanI(f, streams))
|
||||
cmds.AddCommand(NewCmdReconcile(f, streams))
|
||||
|
||||
return cmds
|
||||
}
|
||||
|
@ -19,12 +19,12 @@ package auth
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
@ -48,8 +48,7 @@ type CanIOptions struct {
|
||||
Subresource string
|
||||
ResourceName string
|
||||
|
||||
Out io.Writer
|
||||
Err io.Writer
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
|
||||
var (
|
||||
@ -81,10 +80,9 @@ var (
|
||||
kubectl auth can-i get /logs/`)
|
||||
)
|
||||
|
||||
func NewCmdCanI(f cmdutil.Factory, out, err io.Writer) *cobra.Command {
|
||||
func NewCmdCanI(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := &CanIOptions{
|
||||
Out: out,
|
||||
Err: err,
|
||||
IOStreams: streams,
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
@ -232,9 +230,9 @@ func (o *CanIOptions) resourceFor(mapper meta.RESTMapper, resourceArg string) sc
|
||||
gvr, err = mapper.ResourceFor(groupResource.WithVersion(""))
|
||||
if err != nil {
|
||||
if len(groupResource.Group) == 0 {
|
||||
fmt.Fprintf(o.Err, "Warning: the server doesn't have a resource type '%s'\n", groupResource.Resource)
|
||||
fmt.Fprintf(o.ErrOut, "Warning: the server doesn't have a resource type '%s'\n", groupResource.Resource)
|
||||
} else {
|
||||
fmt.Fprintf(o.Err, "Warning: the server doesn't have a resource type '%s' in group '%s'\n", groupResource.Resource, groupResource.Group)
|
||||
fmt.Fprintf(o.ErrOut, "Warning: the server doesn't have a resource type '%s' in group '%s'\n", groupResource.Resource, groupResource.Group)
|
||||
}
|
||||
return schema.GroupVersionResource{Resource: resourceArg}
|
||||
}
|
||||
|
@ -119,7 +119,7 @@ func TestRunAccessCheck(t *testing.T) {
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
test.o.Out = ioutil.Discard
|
||||
test.o.Err = ioutil.Discard
|
||||
test.o.ErrOut = ioutil.Discard
|
||||
|
||||
tf := cmdtesting.NewTestFactory()
|
||||
defer tf.Cleanup()
|
||||
|
@ -18,7 +18,6 @@ package auth
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"io"
|
||||
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
@ -29,21 +28,25 @@ import (
|
||||
internalrbacclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/rbac/internalversion"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
"k8s.io/kubernetes/pkg/kubectl/resource"
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
"k8s.io/kubernetes/pkg/registry/rbac/reconciliation"
|
||||
)
|
||||
|
||||
// ReconcileOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
|
||||
// referencing the cmd.Flags()
|
||||
type ReconcileOptions struct {
|
||||
PrintFlags *printers.PrintFlags
|
||||
FilenameOptions *resource.FilenameOptions
|
||||
|
||||
Visitor resource.Visitor
|
||||
RBACClient internalrbacclient.RbacInterface
|
||||
NamespaceClient internalcoreclient.NamespaceInterface
|
||||
|
||||
Print func(*resource.Info) error
|
||||
PrintObject printers.ResourcePrinterFunc
|
||||
|
||||
Out io.Writer
|
||||
Err io.Writer
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
|
||||
var (
|
||||
@ -57,12 +60,16 @@ var (
|
||||
kubectl auth reconcile -f my-rbac-rules.yaml`)
|
||||
)
|
||||
|
||||
func NewCmdReconcile(f cmdutil.Factory, out, err io.Writer) *cobra.Command {
|
||||
fileOptions := &resource.FilenameOptions{}
|
||||
o := &ReconcileOptions{
|
||||
Out: out,
|
||||
Err: err,
|
||||
func NewReconcileOptions(ioStreams genericclioptions.IOStreams) *ReconcileOptions {
|
||||
return &ReconcileOptions{
|
||||
FilenameOptions: &resource.FilenameOptions{},
|
||||
PrintFlags: printers.NewPrintFlags("reconciled"),
|
||||
IOStreams: ioStreams,
|
||||
}
|
||||
}
|
||||
|
||||
func NewCmdReconcile(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := NewReconcileOptions(streams)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "reconcile -f FILENAME",
|
||||
@ -71,21 +78,21 @@ func NewCmdReconcile(f cmdutil.Factory, out, err io.Writer) *cobra.Command {
|
||||
Long: reconcileLong,
|
||||
Example: reconcileExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(o.Complete(cmd, f, args, fileOptions))
|
||||
cmdutil.CheckErr(o.Complete(cmd, f, args))
|
||||
cmdutil.CheckErr(o.Validate())
|
||||
cmdutil.CheckErr(o.RunReconcile())
|
||||
},
|
||||
}
|
||||
|
||||
cmdutil.AddPrinterFlags(cmd)
|
||||
usage := "identifying the resource to reconcile."
|
||||
cmdutil.AddFilenameOptionFlags(cmd, fileOptions, usage)
|
||||
o.PrintFlags.AddFlags(cmd)
|
||||
|
||||
cmdutil.AddFilenameOptionFlags(cmd, o.FilenameOptions, "identifying the resource to reconcile.")
|
||||
cmd.MarkFlagRequired("filename")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (o *ReconcileOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args []string, options *resource.FilenameOptions) error {
|
||||
func (o *ReconcileOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args []string) error {
|
||||
if len(args) > 0 {
|
||||
return errors.New("no arguments are allowed")
|
||||
}
|
||||
@ -99,7 +106,7 @@ func (o *ReconcileOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args
|
||||
WithScheme(legacyscheme.Scheme).
|
||||
ContinueOnError().
|
||||
NamespaceParam(namespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, options).
|
||||
FilenameParam(enforceNamespace, o.FilenameOptions).
|
||||
Flatten().
|
||||
Do()
|
||||
|
||||
@ -115,17 +122,12 @@ func (o *ReconcileOptions) Complete(cmd *cobra.Command, f cmdutil.Factory, args
|
||||
o.RBACClient = client.Rbac()
|
||||
o.NamespaceClient = client.Core().Namespaces()
|
||||
|
||||
dryRun := false
|
||||
output := cmdutil.GetFlagString(cmd, "output")
|
||||
shortOutput := output == "name"
|
||||
o.Print = func(info *resource.Info) error {
|
||||
if len(output) > 0 && !shortOutput {
|
||||
return cmdutil.PrintObject(cmd, info.Object, o.Out)
|
||||
}
|
||||
cmdutil.PrintSuccess(shortOutput, o.Out, info.Object, dryRun, "reconciled")
|
||||
return nil
|
||||
printer, err := o.PrintFlags.ToPrinter()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.PrintObject = printer.PrintObj
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -139,13 +141,13 @@ func (o *ReconcileOptions) Validate() error {
|
||||
if o.NamespaceClient == nil {
|
||||
return errors.New("ReconcileOptions.NamespaceClient must be set")
|
||||
}
|
||||
if o.Print == nil {
|
||||
if o.PrintObject == nil {
|
||||
return errors.New("ReconcileOptions.Print must be set")
|
||||
}
|
||||
if o.Out == nil {
|
||||
return errors.New("ReconcileOptions.Out must be set")
|
||||
}
|
||||
if o.Err == nil {
|
||||
if o.ErrOut == nil {
|
||||
return errors.New("ReconcileOptions.Err must be set")
|
||||
}
|
||||
return nil
|
||||
@ -157,10 +159,6 @@ func (o *ReconcileOptions) RunReconcile() error {
|
||||
return err
|
||||
}
|
||||
|
||||
// shallowInfoCopy this is used to later twiddle the Object for printing
|
||||
// we really need more straightforward printing options
|
||||
shallowInfoCopy := *info
|
||||
|
||||
switch t := info.Object.(type) {
|
||||
case *rbac.Role:
|
||||
reconcileOptions := reconciliation.ReconcileRoleOptions{
|
||||
@ -176,8 +174,7 @@ func (o *ReconcileOptions) RunReconcile() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
shallowInfoCopy.Object = result.Role.GetObject()
|
||||
o.Print(&shallowInfoCopy)
|
||||
o.PrintObject(result.Role.GetObject(), o.Out)
|
||||
|
||||
case *rbac.ClusterRole:
|
||||
reconcileOptions := reconciliation.ReconcileRoleOptions{
|
||||
@ -192,8 +189,7 @@ func (o *ReconcileOptions) RunReconcile() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
shallowInfoCopy.Object = result.Role.GetObject()
|
||||
o.Print(&shallowInfoCopy)
|
||||
o.PrintObject(result.Role.GetObject(), o.Out)
|
||||
|
||||
case *rbac.RoleBinding:
|
||||
reconcileOptions := reconciliation.ReconcileRoleBindingOptions{
|
||||
@ -209,8 +205,7 @@ func (o *ReconcileOptions) RunReconcile() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
shallowInfoCopy.Object = result.RoleBinding.GetObject()
|
||||
o.Print(&shallowInfoCopy)
|
||||
o.PrintObject(result.RoleBinding.GetObject(), o.Out)
|
||||
|
||||
case *rbac.ClusterRoleBinding:
|
||||
reconcileOptions := reconciliation.ReconcileRoleBindingOptions{
|
||||
@ -225,8 +220,7 @@ func (o *ReconcileOptions) RunReconcile() error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
shallowInfoCopy.Object = result.RoleBinding.GetObject()
|
||||
o.Print(&shallowInfoCopy)
|
||||
o.PrintObject(result.RoleBinding.GetObject(), o.Out)
|
||||
|
||||
default:
|
||||
glog.V(1).Infof("skipping %#v", info.Object.GetObjectKind())
|
||||
|
@ -123,8 +123,10 @@ func NewCmdCertificateApprove(f cmdutil.Factory, ioStreams genericclioptions.IOS
|
||||
cmdutil.CheckErr(options.RunCertificateApprove(cmdutil.GetFlagBool(cmd, "force")))
|
||||
},
|
||||
}
|
||||
|
||||
options.PrintFlags.AddFlags(cmd)
|
||||
|
||||
cmd.Flags().Bool("force", false, "Update the CSR even if it is already approved.")
|
||||
cmdutil.AddOutputFlagsForMutation(cmd)
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, "identifying the resource to update")
|
||||
|
||||
return cmd
|
||||
@ -173,8 +175,10 @@ func NewCmdCertificateDeny(f cmdutil.Factory, ioStreams genericclioptions.IOStre
|
||||
cmdutil.CheckErr(options.RunCertificateDeny(cmdutil.GetFlagBool(cmd, "force")))
|
||||
},
|
||||
}
|
||||
|
||||
options.PrintFlags.AddFlags(cmd)
|
||||
|
||||
cmd.Flags().Bool("force", false, "Update the CSR even if it is already denied.")
|
||||
cmdutil.AddOutputFlagsForMutation(cmd)
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, "identifying the resource to update")
|
||||
|
||||
return cmd
|
||||
|
@ -309,7 +309,7 @@ func NewKubectlCommand(in io.Reader, out, err io.Writer) *cobra.Command {
|
||||
NewCmdPortForward(f, out, err),
|
||||
NewCmdProxy(f, out),
|
||||
NewCmdCp(f, ioStreams),
|
||||
auth.NewCmdAuth(f, out, err),
|
||||
auth.NewCmdAuth(f, ioStreams),
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -355,7 +355,7 @@ func NewKubectlCommand(in io.Reader, out, err io.Writer) *cobra.Command {
|
||||
}
|
||||
|
||||
cmds.AddCommand(alpha)
|
||||
cmds.AddCommand(cmdconfig.NewCmdConfig(f, clientcmd.NewDefaultPathOptions(), out, err))
|
||||
cmds.AddCommand(cmdconfig.NewCmdConfig(f, clientcmd.NewDefaultPathOptions(), ioStreams))
|
||||
cmds.AddCommand(NewCmdPlugin(f, in, out, err))
|
||||
cmds.AddCommand(NewCmdVersion(f, ioStreams))
|
||||
cmds.AddCommand(NewCmdApiVersions(f, ioStreams))
|
||||
|
@ -14,6 +14,7 @@ go_library(
|
||||
"current_context.go",
|
||||
"delete_cluster.go",
|
||||
"delete_context.go",
|
||||
"flags.go",
|
||||
"get_clusters.go",
|
||||
"get_contexts.go",
|
||||
"navigation_step_parser.go",
|
||||
@ -30,6 +31,7 @@ go_library(
|
||||
deps = [
|
||||
"//pkg/kubectl/cmd/templates:go_default_library",
|
||||
"//pkg/kubectl/cmd/util:go_default_library",
|
||||
"//pkg/kubectl/genericclioptions:go_default_library",
|
||||
"//pkg/kubectl/util/i18n:go_default_library",
|
||||
"//pkg/printers:go_default_library",
|
||||
"//vendor/github.com/spf13/cobra:go_default_library",
|
||||
@ -64,6 +66,7 @@ go_test(
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/kubectl/cmd/util:go_default_library",
|
||||
"//pkg/kubectl/genericclioptions:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/util/diff:go_default_library",
|
||||
"//vendor/k8s.io/apiserver/pkg/util/flag:go_default_library",
|
||||
|
@ -18,7 +18,6 @@ package config
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"path"
|
||||
"strconv"
|
||||
|
||||
@ -27,11 +26,12 @@ import (
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
|
||||
)
|
||||
|
||||
// NewCmdConfig creates a command object for the "config" action, and adds all child commands to it.
|
||||
func NewCmdConfig(f cmdutil.Factory, pathOptions *clientcmd.PathOptions, out, errOut io.Writer) *cobra.Command {
|
||||
func NewCmdConfig(f cmdutil.Factory, pathOptions *clientcmd.PathOptions, streams genericclioptions.IOStreams) *cobra.Command {
|
||||
if len(pathOptions.ExplicitFileFlag) == 0 {
|
||||
pathOptions.ExplicitFileFlag = clientcmd.RecommendedConfigPathFlag
|
||||
}
|
||||
@ -48,25 +48,26 @@ func NewCmdConfig(f cmdutil.Factory, pathOptions *clientcmd.PathOptions, out, er
|
||||
1. If the --` + pathOptions.ExplicitFileFlag + ` flag is set, then only that file is loaded. The flag may only be set once and no merging takes place.
|
||||
2. If $` + pathOptions.EnvVar + ` environment variable is set, then it is used a list of paths (normal path delimitting rules for your system). These paths are merged. When a value is modified, it is modified in the file that defines the stanza. When a value is created, it is created in the first file that exists. If no files in the chain exist, then it creates the last file in the list.
|
||||
3. Otherwise, ` + path.Join("${HOME}", pathOptions.GlobalFileSubpath) + ` is used and no merging takes place.`),
|
||||
Run: cmdutil.DefaultSubCommandRun(errOut),
|
||||
Run: cmdutil.DefaultSubCommandRun(streams.Out),
|
||||
}
|
||||
|
||||
// file paths are common to all sub commands
|
||||
cmd.PersistentFlags().StringVar(&pathOptions.LoadingRules.ExplicitPath, pathOptions.ExplicitFileFlag, pathOptions.LoadingRules.ExplicitPath, "use a particular kubeconfig file")
|
||||
|
||||
cmd.AddCommand(NewCmdConfigView(f, out, errOut, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigSetCluster(out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigSetAuthInfo(out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigSetContext(out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigSet(out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigUnset(out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigCurrentContext(out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigUseContext(out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigGetContexts(out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigGetClusters(out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigDeleteCluster(out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigDeleteContext(out, errOut, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigRenameContext(out, pathOptions))
|
||||
// TODO(juanvallejo): update all subcommands to work with genericclioptions.IOStreams
|
||||
cmd.AddCommand(NewCmdConfigView(f, streams, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigSetCluster(streams.Out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigSetAuthInfo(streams.Out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigSetContext(streams.Out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigSet(streams.Out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigUnset(streams.Out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigCurrentContext(streams.Out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigUseContext(streams.Out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigGetContexts(streams, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigGetClusters(streams.Out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigDeleteCluster(streams.Out, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigDeleteContext(streams.Out, streams.ErrOut, pathOptions))
|
||||
cmd.AddCommand(NewCmdConfigRenameContext(streams.Out, pathOptions))
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
@ -17,7 +17,6 @@ limitations under the License.
|
||||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@ -31,6 +30,7 @@ import (
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
)
|
||||
|
||||
func newRedFederalCowHammerConfig() clientcmdapi.Config {
|
||||
@ -863,9 +863,8 @@ func testConfigCommand(args []string, startingConfig clientcmdapi.Config, t *tes
|
||||
argsToUse = append(argsToUse, "--kubeconfig="+fakeKubeFile.Name())
|
||||
argsToUse = append(argsToUse, args...)
|
||||
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := NewCmdConfig(cmdutil.NewFactory(cmdutil.NewTestConfigFlags()), clientcmd.NewDefaultPathOptions(), buf, buf)
|
||||
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
|
||||
cmd := NewCmdConfig(cmdutil.NewFactory(cmdutil.NewTestConfigFlags()), clientcmd.NewDefaultPathOptions(), streams)
|
||||
cmd.SetArgs(argsToUse)
|
||||
cmd.Execute()
|
||||
|
||||
|
95
pkg/kubectl/cmd/config/flags.go
Normal file
95
pkg/kubectl/cmd/config/flags.go
Normal file
@ -0,0 +1,95 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 config
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
)
|
||||
|
||||
// PrintFlags composes common printer flag structs
|
||||
// used across all config commands, and provides a method
|
||||
// of retrieving a known printer based on flag values provided.
|
||||
type PrintFlags struct {
|
||||
JSONYamlPrintFlags *printers.JSONYamlPrintFlags
|
||||
NamePrintFlags *printers.NamePrintFlags
|
||||
TemplateFlags *printers.KubeTemplatePrintFlags
|
||||
|
||||
OutputFormat *string
|
||||
}
|
||||
|
||||
func (f *PrintFlags) Complete(successTemplate string) error {
|
||||
return f.NamePrintFlags.Complete(successTemplate)
|
||||
}
|
||||
|
||||
func (f *PrintFlags) ToPrinter() (printers.ResourcePrinter, error) {
|
||||
outputFormat := ""
|
||||
if f.OutputFormat != nil {
|
||||
outputFormat = *f.OutputFormat
|
||||
}
|
||||
|
||||
if p, err := f.JSONYamlPrintFlags.ToPrinter(outputFormat); !printers.IsNoCompatiblePrinterError(err) {
|
||||
return p, err
|
||||
}
|
||||
|
||||
if p, err := f.NamePrintFlags.ToPrinter(outputFormat); !printers.IsNoCompatiblePrinterError(err) {
|
||||
return p, err
|
||||
}
|
||||
|
||||
if p, err := f.TemplateFlags.ToPrinter(outputFormat); !printers.IsNoCompatiblePrinterError(err) {
|
||||
return p, err
|
||||
}
|
||||
|
||||
return nil, printers.NoCompatiblePrinterError{Options: f}
|
||||
}
|
||||
|
||||
func (f *PrintFlags) AddFlags(cmd *cobra.Command) {
|
||||
f.JSONYamlPrintFlags.AddFlags(cmd)
|
||||
f.NamePrintFlags.AddFlags(cmd)
|
||||
f.TemplateFlags.AddFlags(cmd)
|
||||
|
||||
if f.OutputFormat != nil {
|
||||
cmd.Flags().StringVarP(f.OutputFormat, "output", "o", *f.OutputFormat, "Output format. One of: json|yaml|wide|name|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See custom columns [http://kubernetes.io/docs/user-guide/kubectl-overview/#custom-columns], golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://kubernetes.io/docs/user-guide/jsonpath].")
|
||||
}
|
||||
}
|
||||
|
||||
// WithDefaultOutput sets a default output format if one is not provided through a flag value
|
||||
func (f *PrintFlags) WithDefaultOutput(output string) *PrintFlags {
|
||||
existingFormat := ""
|
||||
if f.OutputFormat != nil {
|
||||
existingFormat = *f.OutputFormat
|
||||
}
|
||||
if len(existingFormat) == 0 {
|
||||
existingFormat = output
|
||||
}
|
||||
f.OutputFormat = &existingFormat
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func NewPrintFlags(operation string) *PrintFlags {
|
||||
outputFormat := ""
|
||||
|
||||
return &PrintFlags{
|
||||
OutputFormat: &outputFormat,
|
||||
|
||||
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
|
||||
NamePrintFlags: printers.NewNamePrintFlags(operation),
|
||||
TemplateFlags: printers.NewKubeTemplatePrintFlags(),
|
||||
}
|
||||
}
|
@ -31,6 +31,7 @@ import (
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
)
|
||||
@ -41,7 +42,8 @@ type GetContextsOptions struct {
|
||||
nameOnly bool
|
||||
showHeaders bool
|
||||
contextNames []string
|
||||
out io.Writer
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
|
||||
var (
|
||||
@ -57,8 +59,12 @@ var (
|
||||
|
||||
// NewCmdConfigGetContexts creates a command object for the "get-contexts" action, which
|
||||
// retrieves one or more contexts from a kubeconfig.
|
||||
func NewCmdConfigGetContexts(out io.Writer, configAccess clientcmd.ConfigAccess) *cobra.Command {
|
||||
options := &GetContextsOptions{configAccess: configAccess}
|
||||
func NewCmdConfigGetContexts(streams genericclioptions.IOStreams, configAccess clientcmd.ConfigAccess) *cobra.Command {
|
||||
options := &GetContextsOptions{
|
||||
configAccess: configAccess,
|
||||
|
||||
IOStreams: streams,
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "get-contexts [(-o|--output=)name)]",
|
||||
@ -74,22 +80,22 @@ func NewCmdConfigGetContexts(out io.Writer, configAccess clientcmd.ConfigAccess)
|
||||
cmdutil.CheckErr(fmt.Errorf("output must be one of '' or 'name': %v", outputFormat))
|
||||
}
|
||||
if !supportedOutputTypes.Has(outputFormat) {
|
||||
fmt.Fprintf(out, "--output %v is not available in kubectl config get-contexts; resetting to default output format\n", outputFormat)
|
||||
fmt.Fprintf(options.Out, "--output %v is not available in kubectl config get-contexts; resetting to default output format\n", outputFormat)
|
||||
cmd.Flags().Set("output", "")
|
||||
}
|
||||
cmdutil.CheckErr(options.Complete(cmd, args, out))
|
||||
cmdutil.CheckErr(options.Complete(cmd, args))
|
||||
cmdutil.CheckErr(options.RunGetContexts())
|
||||
},
|
||||
}
|
||||
cmdutil.AddOutputFlags(cmd)
|
||||
cmdutil.AddNoHeadersFlags(cmd)
|
||||
|
||||
cmd.Flags().Bool("no-headers", false, "When using the default or custom-column output format, don't print headers (default print headers).")
|
||||
cmd.Flags().StringP("output", "o", "", "Output format. One of: name")
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Complete assigns GetContextsOptions from the args.
|
||||
func (o *GetContextsOptions) Complete(cmd *cobra.Command, args []string, out io.Writer) error {
|
||||
func (o *GetContextsOptions) Complete(cmd *cobra.Command, args []string) error {
|
||||
o.contextNames = args
|
||||
o.out = out
|
||||
o.nameOnly = false
|
||||
if cmdutil.GetFlagString(cmd, "output") == "name" {
|
||||
o.nameOnly = true
|
||||
@ -109,9 +115,9 @@ func (o GetContextsOptions) RunGetContexts() error {
|
||||
return err
|
||||
}
|
||||
|
||||
out, found := o.out.(*tabwriter.Writer)
|
||||
out, found := o.Out.(*tabwriter.Writer)
|
||||
if !found {
|
||||
out = printers.GetNewTabWriter(o.out)
|
||||
out = printers.GetNewTabWriter(o.Out)
|
||||
defer out.Flush()
|
||||
}
|
||||
|
||||
|
@ -17,13 +17,13 @@ limitations under the License.
|
||||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
)
|
||||
|
||||
type getContextsTest struct {
|
||||
@ -157,11 +157,11 @@ func (test getContextsTest) run(t *testing.T) {
|
||||
pathOptions := clientcmd.NewDefaultPathOptions()
|
||||
pathOptions.GlobalFile = fakeKubeFile.Name()
|
||||
pathOptions.EnvVar = ""
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
|
||||
options := GetContextsOptions{
|
||||
configAccess: pathOptions,
|
||||
}
|
||||
cmd := NewCmdConfigGetContexts(buf, options.configAccess)
|
||||
cmd := NewCmdConfigGetContexts(streams, options.configAccess)
|
||||
if test.nameOnly {
|
||||
cmd.Flags().Set("output", "name")
|
||||
}
|
||||
|
@ -18,8 +18,6 @@ package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
@ -29,16 +27,24 @@ import (
|
||||
"k8s.io/client-go/tools/clientcmd/api/latest"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
)
|
||||
|
||||
type ViewOptions struct {
|
||||
PrintFlags *PrintFlags
|
||||
PrintObject printers.ResourcePrinterFunc
|
||||
|
||||
ConfigAccess clientcmd.ConfigAccess
|
||||
Merge flag.Tristate
|
||||
Flatten bool
|
||||
Minify bool
|
||||
RawByteData bool
|
||||
|
||||
OutputFormat string
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
|
||||
var (
|
||||
@ -56,12 +62,17 @@ var (
|
||||
|
||||
# Get the password for the e2e user
|
||||
kubectl config view -o jsonpath='{.users[?(@.name == "e2e")].user.password}'`)
|
||||
|
||||
defaultOutputFormat = "yaml"
|
||||
)
|
||||
|
||||
func NewCmdConfigView(f cmdutil.Factory, out, errOut io.Writer, ConfigAccess clientcmd.ConfigAccess) *cobra.Command {
|
||||
options := &ViewOptions{ConfigAccess: ConfigAccess}
|
||||
// Default to yaml
|
||||
defaultOutputFormat := "yaml"
|
||||
func NewCmdConfigView(f cmdutil.Factory, streams genericclioptions.IOStreams, ConfigAccess clientcmd.ConfigAccess) *cobra.Command {
|
||||
o := &ViewOptions{
|
||||
PrintFlags: NewPrintFlags("").WithDefaultOutput("yaml"),
|
||||
ConfigAccess: ConfigAccess,
|
||||
|
||||
IOStreams: streams,
|
||||
}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "view",
|
||||
@ -69,40 +80,48 @@ func NewCmdConfigView(f cmdutil.Factory, out, errOut io.Writer, ConfigAccess cli
|
||||
Long: view_long,
|
||||
Example: view_example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options.Complete()
|
||||
outputFormat := cmdutil.GetFlagString(cmd, "output")
|
||||
if outputFormat == "wide" {
|
||||
fmt.Fprintf(errOut, "--output wide is not available in kubectl config view; reset to default output format (%s)\n\n", defaultOutputFormat)
|
||||
// TODO: once printing is abstracted, this should be handled at flag declaration time
|
||||
cmd.Flags().Set("output", defaultOutputFormat)
|
||||
}
|
||||
if outputFormat == "" {
|
||||
fmt.Fprintf(errOut, "Reset to default output format (%s) as --output is empty\n", defaultOutputFormat)
|
||||
// TODO: once printing is abstracted, this should be handled at flag declaration time
|
||||
cmd.Flags().Set("output", defaultOutputFormat)
|
||||
}
|
||||
|
||||
printOpts := cmdutil.ExtractCmdPrintOptions(cmd, false)
|
||||
printer, err := cmdutil.PrinterForOptions(printOpts)
|
||||
cmdutil.CheckErr(err)
|
||||
|
||||
cmdutil.CheckErr(options.Run(out, printer))
|
||||
cmdutil.CheckErr(o.Complete(cmd))
|
||||
cmdutil.CheckErr(o.Validate())
|
||||
cmdutil.CheckErr(o.Run())
|
||||
},
|
||||
}
|
||||
|
||||
cmdutil.AddPrinterFlags(cmd)
|
||||
cmd.Flags().Set("output", defaultOutputFormat)
|
||||
o.PrintFlags.AddFlags(cmd)
|
||||
|
||||
options.Merge.Default(true)
|
||||
mergeFlag := cmd.Flags().VarPF(&options.Merge, "merge", "", "Merge the full hierarchy of kubeconfig files")
|
||||
o.Merge.Default(true)
|
||||
mergeFlag := cmd.Flags().VarPF(&o.Merge, "merge", "", "Merge the full hierarchy of kubeconfig files")
|
||||
mergeFlag.NoOptDefVal = "true"
|
||||
cmd.Flags().BoolVar(&options.RawByteData, "raw", options.RawByteData, "Display raw byte data")
|
||||
cmd.Flags().BoolVar(&options.Flatten, "flatten", options.Flatten, "Flatten the resulting kubeconfig file into self-contained output (useful for creating portable kubeconfig files)")
|
||||
cmd.Flags().BoolVar(&options.Minify, "minify", options.Minify, "Remove all information not used by current-context from the output")
|
||||
cmd.Flags().BoolVar(&o.RawByteData, "raw", o.RawByteData, "Display raw byte data")
|
||||
cmd.Flags().BoolVar(&o.Flatten, "flatten", o.Flatten, "Flatten the resulting kubeconfig file into self-contained output (useful for creating portable kubeconfig files)")
|
||||
cmd.Flags().BoolVar(&o.Minify, "minify", o.Minify, "Remove all information not used by current-context from the output")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (o ViewOptions) Run(out io.Writer, printer printers.ResourcePrinter) error {
|
||||
func (o *ViewOptions) Complete(cmd *cobra.Command) error {
|
||||
if o.ConfigAccess.IsExplicitFile() {
|
||||
if !o.Merge.Provided() {
|
||||
o.Merge.Set("false")
|
||||
}
|
||||
}
|
||||
|
||||
printer, err := o.PrintFlags.ToPrinter()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.PrintObject = printer.PrintObj
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o ViewOptions) Validate() error {
|
||||
if !o.Merge.Value() && !o.ConfigAccess.IsExplicitFile() {
|
||||
return errors.New("if merge==false a precise file must to specified")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o ViewOptions) Run() error {
|
||||
config, err := o.loadConfig()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -127,22 +146,7 @@ func (o ViewOptions) Run(out io.Writer, printer printers.ResourcePrinter) error
|
||||
return err
|
||||
}
|
||||
|
||||
err = printer.PrintObj(convertedObj, out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *ViewOptions) Complete() bool {
|
||||
if o.ConfigAccess.IsExplicitFile() {
|
||||
if !o.Merge.Provided() {
|
||||
o.Merge.Set("false")
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
return o.PrintObject(convertedObj, o.Out)
|
||||
}
|
||||
|
||||
func (o ViewOptions) loadConfig() (*clientcmdapi.Config, error) {
|
||||
@ -155,14 +159,6 @@ func (o ViewOptions) loadConfig() (*clientcmdapi.Config, error) {
|
||||
return config, err
|
||||
}
|
||||
|
||||
func (o ViewOptions) Validate() error {
|
||||
if !o.Merge.Value() && !o.ConfigAccess.IsExplicitFile() {
|
||||
return errors.New("if merge==false a precise file must to specified")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// getStartingConfig returns the Config object built from the sources specified by the options, the filename read (only if it was a single file), and an error if something goes wrong
|
||||
func (o *ViewOptions) getStartingConfig() (*clientcmdapi.Config, error) {
|
||||
switch {
|
||||
|
@ -17,7 +17,6 @@ limitations under the License.
|
||||
package config
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
@ -25,6 +24,7 @@ import (
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
)
|
||||
|
||||
type viewClusterTest struct {
|
||||
@ -141,9 +141,8 @@ func (test viewClusterTest) run(t *testing.T) {
|
||||
pathOptions := clientcmd.NewDefaultPathOptions()
|
||||
pathOptions.GlobalFile = fakeKubeFile.Name()
|
||||
pathOptions.EnvVar = ""
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
errBuf := bytes.NewBuffer([]byte{})
|
||||
cmd := NewCmdConfigView(cmdutil.NewFactory(cmdutil.NewTestConfigFlags()), buf, errBuf, pathOptions)
|
||||
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
|
||||
cmd := NewCmdConfigView(cmdutil.NewFactory(cmdutil.NewTestConfigFlags()), streams, pathOptions)
|
||||
cmd.Flags().Parse(test.flags)
|
||||
if err := cmd.Execute(); err != nil {
|
||||
t.Fatalf("unexpected error executing command: %v,kubectl config view flags: %v", err, test.flags)
|
||||
|
@ -124,8 +124,6 @@ func NewCmdDelete(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
||||
Example: delete_example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options := deleteFlags.ToOptions(out, errOut)
|
||||
cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd))
|
||||
|
||||
if err := options.Complete(f, out, errOut, args, cmd); err != nil {
|
||||
cmdutil.CheckErr(err)
|
||||
}
|
||||
@ -185,6 +183,11 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args
|
||||
}
|
||||
|
||||
func (o *DeleteOptions) Validate(cmd *cobra.Command) error {
|
||||
outputMode := cmdutil.GetFlagString(cmd, "output")
|
||||
if outputMode != "" && outputMode != "name" {
|
||||
return cmdutil.UsageErrorf(cmd, "Unexpected -o output mode: %v. We only support '-o name'.", outputMode)
|
||||
}
|
||||
|
||||
if o.DeleteAll && len(o.LabelSelector) > 0 {
|
||||
return fmt.Errorf("cannot set --all and --selector at the same time")
|
||||
}
|
||||
|
@ -48,9 +48,7 @@ func fakecmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "delete ([-f FILENAME] | TYPE [(NAME | -l label | --all)])",
|
||||
DisableFlagsInUseLine: true,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd))
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
@ -91,8 +91,15 @@ type ReplaceOptions struct {
|
||||
}
|
||||
|
||||
func NewReplaceOptions(out, errOut io.Writer) *ReplaceOptions {
|
||||
outputFormat := ""
|
||||
|
||||
return &ReplaceOptions{
|
||||
PrintFlags: printers.NewPrintFlags("replaced"),
|
||||
// TODO(juanvallejo): figure out why we only support the "name" outputFormat in this command
|
||||
// we only support "-o name" for this command, so only register the name printer
|
||||
PrintFlags: &printers.PrintFlags{
|
||||
OutputFormat: &outputFormat,
|
||||
NamePrintFlags: printers.NewNamePrintFlags("replaced"),
|
||||
},
|
||||
DeleteFlags: NewDeleteFlags("to use to replace the resource."),
|
||||
|
||||
Out: out,
|
||||
@ -110,7 +117,6 @@ func NewCmdReplace(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
|
||||
Long: replaceLong,
|
||||
Example: replaceExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd))
|
||||
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
||||
cmdutil.CheckErr(o.Validate(cmd))
|
||||
cmdutil.CheckErr(o.Run())
|
||||
|
@ -93,9 +93,16 @@ type ScaleOptions struct {
|
||||
}
|
||||
|
||||
func NewScaleOptions(ioStreams genericclioptions.IOStreams) *ScaleOptions {
|
||||
outputFormat := ""
|
||||
|
||||
return &ScaleOptions{
|
||||
// TODO(juanvallejo): figure out why we only support the "name" outputFormat in this command
|
||||
// we only support "-o name" for this command, so only register the name printer
|
||||
PrintFlags: &printers.PrintFlags{
|
||||
OutputFormat: &outputFormat,
|
||||
NamePrintFlags: printers.NewNamePrintFlags("scaled"),
|
||||
},
|
||||
RecordFlags: genericclioptions.NewRecordFlags(),
|
||||
PrintFlags: printers.NewPrintFlags("scaled"),
|
||||
CurrentReplicas: -1,
|
||||
Recorder: genericclioptions.NoopRecorder{},
|
||||
IOStreams: ioStreams,
|
||||
@ -173,9 +180,6 @@ func (o *ScaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
|
||||
}
|
||||
|
||||
func (o *ScaleOptions) Validate(cmd *cobra.Command) error {
|
||||
if err := cmdutil.ValidateOutputArgs(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
if o.Replicas < 0 {
|
||||
return fmt.Errorf("The --replicas=COUNT flag is required, and COUNT must be greater than or equal to 0")
|
||||
}
|
||||
|
@ -18,222 +18,12 @@ package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
kubectlscheme "k8s.io/kubernetes/pkg/kubectl/scheme"
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
printersinternal "k8s.io/kubernetes/pkg/printers/internalversion"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
)
|
||||
|
||||
// AddPrinterFlags adds printing related flags to a command (e.g. output format, no headers, template path)
|
||||
func AddPrinterFlags(cmd *cobra.Command) {
|
||||
AddNonDeprecatedPrinterFlags(cmd)
|
||||
|
||||
cmd.Flags().String("output-version", "", "DEPRECATED: To use a specific API version, fully-qualify the resource, version, and group (for example: 'jobs.v1.batch/myjob').")
|
||||
cmd.Flags().MarkDeprecated("output-version", "The resource is used exactly as fetched from the API. To get a specific API version, fully-qualify the resource, version, and group (for example: 'jobs.v1.batch/myjob').")
|
||||
cmd.Flags().MarkHidden("output-version")
|
||||
}
|
||||
|
||||
// AddNonDeprecatedPrinterFlags supports the conversion case which must logically have output-version. Once output-version
|
||||
// is completely removed, this function can go away.
|
||||
func AddNonDeprecatedPrinterFlags(cmd *cobra.Command) {
|
||||
AddOutputFlags(cmd)
|
||||
AddNoHeadersFlags(cmd)
|
||||
cmd.Flags().Bool("show-labels", false, "When printing, show all labels as the last column (default hide labels column)")
|
||||
cmd.Flags().String("template", "", "Template string or path to template file to use when -o=go-template, -o=go-template-file. The template format is golang templates [http://golang.org/pkg/text/template/#pkg-overview].")
|
||||
cmd.MarkFlagFilename("template")
|
||||
cmd.Flags().String("sort-by", "", "If non-empty, sort list types using this field specification. The field specification is expressed as a JSONPath expression (e.g. '{.metadata.name}'). The field in the API resource specified by this JSONPath expression must be an integer or a string.")
|
||||
cmd.Flags().BoolP("show-all", "a", true, "When printing, show all resources (default show all pods including terminated one.)")
|
||||
cmd.Flags().MarkDeprecated("show-all", "will be removed in an upcoming release")
|
||||
}
|
||||
|
||||
// AddOutputFlagsForMutation adds output related flags to a command. Used by mutations only.
|
||||
func AddOutputFlagsForMutation(cmd *cobra.Command) {
|
||||
cmd.Flags().StringP("output", "o", "", "Output mode. Use \"-o name\" for shorter output (resource/name).")
|
||||
}
|
||||
|
||||
// AddOutputVarFlagsForMutation adds output related flags to a command. Used by mutations only.
|
||||
func AddOutputVarFlagsForMutation(cmd *cobra.Command, output *string) {
|
||||
cmd.Flags().StringVarP(output, "output", "o", *output, "Output mode. Use \"-o name\" for shorter output (resource/name).")
|
||||
}
|
||||
|
||||
// AddOutputFlags adds output related flags to a command.
|
||||
func AddOutputFlags(cmd *cobra.Command) {
|
||||
cmd.Flags().StringP("output", "o", "", "Output format. One of: json|yaml|wide|name|custom-columns=...|custom-columns-file=...|go-template=...|go-template-file=...|jsonpath=...|jsonpath-file=... See custom columns [http://kubernetes.io/docs/user-guide/kubectl-overview/#custom-columns], golang template [http://golang.org/pkg/text/template/#pkg-overview] and jsonpath template [http://kubernetes.io/docs/user-guide/jsonpath].")
|
||||
cmd.Flags().Bool("allow-missing-template-keys", true, "If true, ignore any errors in templates when a field or map key is missing in the template. Only applies to golang and jsonpath output formats.")
|
||||
}
|
||||
|
||||
// AddNoHeadersFlags adds no-headers flags to a command.
|
||||
func AddNoHeadersFlags(cmd *cobra.Command) {
|
||||
cmd.Flags().Bool("no-headers", false, "When using the default or custom-column output format, don't print headers (default print headers).")
|
||||
}
|
||||
|
||||
// ValidateOutputArgs validates -o flag args for mutations
|
||||
func ValidateOutputArgs(cmd *cobra.Command) error {
|
||||
outputMode := GetFlagString(cmd, "output")
|
||||
if outputMode != "" && outputMode != "name" {
|
||||
return UsageErrorf(cmd, "Unexpected -o output mode: %v. We only support '-o name'.", outputMode)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// PrintSuccess prints a success message and can do a "-o name" as "shortOutput"
|
||||
// TODO this should really just be a printer. It's got just about the exact same signature.
|
||||
func PrintSuccess(shortOutput bool, out io.Writer, obj runtime.Object, dryRun bool, operation string) {
|
||||
dryRunMsg := ""
|
||||
if dryRun {
|
||||
dryRunMsg = " (dry run)"
|
||||
}
|
||||
|
||||
// match name printer format
|
||||
name := "<unknown>"
|
||||
if acc, err := meta.Accessor(obj); err == nil {
|
||||
if n := acc.GetName(); len(n) > 0 {
|
||||
name = n
|
||||
}
|
||||
}
|
||||
|
||||
// legacy scheme to be sure we work ok with internal types.
|
||||
// TODO internal types aren't supposed to exist here
|
||||
groupKind := printers.GetObjectGroupKind(obj, legacyscheme.Scheme)
|
||||
kindString := fmt.Sprintf("%s.%s", strings.ToLower(groupKind.Kind), groupKind.Group)
|
||||
if len(groupKind.Group) == 0 {
|
||||
kindString = strings.ToLower(groupKind.Kind)
|
||||
}
|
||||
|
||||
if shortOutput {
|
||||
// -o name: prints resource/name
|
||||
fmt.Fprintf(out, "%s/%s\n", kindString, name)
|
||||
return
|
||||
}
|
||||
|
||||
// understandable output by default
|
||||
fmt.Fprintf(out, "%s \"%s\" %s%s\n", kindString, name, operation, dryRunMsg)
|
||||
}
|
||||
|
||||
// PrintObject prints a single object based on the default command options
|
||||
// TODO this should go away once commands can embed the PrintOptions instead
|
||||
func PrintObject(cmd *cobra.Command, obj runtime.Object, out io.Writer) error {
|
||||
printer, err := PrinterForOptions(ExtractCmdPrintOptions(cmd, false))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printer.PrintObj(obj, out)
|
||||
}
|
||||
|
||||
// PrinterForOptions returns the printer for the outputOptions (if given) or
|
||||
// returns the default printer for the command.
|
||||
// TODO this should become a function on the PrintOptions struct
|
||||
func PrinterForOptions(options *printers.PrintOptions) (printers.ResourcePrinter, error) {
|
||||
// TODO: used by the custom column implementation and the name implementation, break this dependency
|
||||
decoders := []runtime.Decoder{kubectlscheme.Codecs.UniversalDecoder(), unstructured.UnstructuredJSONScheme}
|
||||
encoder := kubectlscheme.Codecs.LegacyCodec(kubectlscheme.Registry.RegisteredGroupVersions()...)
|
||||
|
||||
printer, err := printers.GetStandardPrinter(kubectlscheme.Scheme, encoder, decoders, *options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// we try to convert to HumanReadablePrinter, if return ok, it must be no generic
|
||||
// we execute AddHandlers() here before maybeWrapSortingPrinter so that we don't
|
||||
// need to convert to delegatePrinter again then invoke AddHandlers()
|
||||
// TODO this looks highly questionable. human readable printers are baked into code. This can just live in the definition of the handler itself
|
||||
// TODO or be registered there
|
||||
if humanReadablePrinter, ok := printer.(printers.PrintHandler); ok {
|
||||
printersinternal.AddHandlers(humanReadablePrinter)
|
||||
}
|
||||
|
||||
printer = maybeWrapSortingPrinter(printer, *options)
|
||||
|
||||
// wrap the printer in a versioning printer that understands when to convert and when not to convert
|
||||
printer = printers.NewVersionedPrinter(printer, legacyscheme.Scheme, legacyscheme.Scheme, kubectlscheme.Versions...)
|
||||
|
||||
return printer, nil
|
||||
}
|
||||
|
||||
// ExtractCmdPrintOptions parses printer specific commandline args and
|
||||
// returns a PrintOptions object.
|
||||
// Requires that printer flags have been added to cmd (see AddPrinterFlags)
|
||||
func ExtractCmdPrintOptions(cmd *cobra.Command, withNamespace bool) *printers.PrintOptions {
|
||||
flags := cmd.Flags()
|
||||
|
||||
columnLabel, err := flags.GetStringSlice("label-columns")
|
||||
if err != nil {
|
||||
columnLabel = []string{}
|
||||
}
|
||||
|
||||
options := &printers.PrintOptions{
|
||||
NoHeaders: GetFlagBool(cmd, "no-headers"),
|
||||
Wide: GetWideFlag(cmd),
|
||||
ShowAll: GetFlagBool(cmd, "show-all"),
|
||||
ShowLabels: GetFlagBool(cmd, "show-labels"),
|
||||
AbsoluteTimestamps: isWatch(cmd),
|
||||
ColumnLabels: columnLabel,
|
||||
WithNamespace: withNamespace,
|
||||
}
|
||||
|
||||
var outputFormat string
|
||||
if flags.Lookup("output") != nil {
|
||||
outputFormat = GetFlagString(cmd, "output")
|
||||
}
|
||||
|
||||
if flags.Lookup("sort-by") != nil {
|
||||
options.SortBy = GetFlagString(cmd, "sort-by")
|
||||
}
|
||||
|
||||
// templates are logically optional for specifying a format.
|
||||
// TODO once https://github.com/kubernetes/kubernetes/issues/12668 is fixed, this should fall back to GetFlagString
|
||||
var templateFile string
|
||||
if flag := flags.Lookup("template"); flag != nil {
|
||||
if flag.Value.Type() == "string" {
|
||||
templateFile = GetFlagString(cmd, "template")
|
||||
}
|
||||
}
|
||||
if len(outputFormat) == 0 && len(templateFile) != 0 {
|
||||
outputFormat = "template"
|
||||
}
|
||||
|
||||
templateFormats := []string{
|
||||
"go-template=", "go-template-file=", "jsonpath=", "jsonpath-file=", "custom-columns=", "custom-columns-file=",
|
||||
}
|
||||
for _, format := range templateFormats {
|
||||
if strings.HasPrefix(outputFormat, format) {
|
||||
templateFile = outputFormat[len(format):]
|
||||
outputFormat = format[:len(format)-1]
|
||||
}
|
||||
}
|
||||
|
||||
// this function may be invoked by a command that did not call AddPrinterFlags first, so we need
|
||||
// to be safe about how we access the allow-missing-template-keys flag
|
||||
if flags.Lookup("allow-missing-template-keys") != nil {
|
||||
options.AllowMissingKeys = GetFlagBool(cmd, "allow-missing-template-keys")
|
||||
}
|
||||
|
||||
options.OutputFormatType = outputFormat
|
||||
options.OutputFormatArgument = templateFile
|
||||
|
||||
return options
|
||||
}
|
||||
|
||||
func maybeWrapSortingPrinter(printer printers.ResourcePrinter, printOpts printers.PrintOptions) printers.ResourcePrinter {
|
||||
if len(printOpts.SortBy) != 0 {
|
||||
return &kubectl.SortingPrinter{
|
||||
Delegate: printer,
|
||||
SortField: fmt.Sprintf("{%s}", printOpts.SortBy),
|
||||
}
|
||||
}
|
||||
return printer
|
||||
}
|
||||
|
||||
// SuggestApiResources returns a suggestion to use the "api-resources" command
|
||||
// to retrieve a supported list of resources
|
||||
func SuggestApiResources(parent string) string {
|
||||
|
@ -65,12 +65,16 @@ func (f *PrintFlags) ToPrinter() (ResourcePrinter, error) {
|
||||
outputFormat = *f.OutputFormat
|
||||
}
|
||||
|
||||
if p, err := f.JSONYamlPrintFlags.ToPrinter(outputFormat); !IsNoCompatiblePrinterError(err) {
|
||||
return p, err
|
||||
if f.JSONYamlPrintFlags != nil {
|
||||
if p, err := f.JSONYamlPrintFlags.ToPrinter(outputFormat); !IsNoCompatiblePrinterError(err) {
|
||||
return p, err
|
||||
}
|
||||
}
|
||||
|
||||
if p, err := f.NamePrintFlags.ToPrinter(outputFormat); !IsNoCompatiblePrinterError(err) {
|
||||
return p, err
|
||||
if f.NamePrintFlags != nil {
|
||||
if p, err := f.NamePrintFlags.ToPrinter(outputFormat); !IsNoCompatiblePrinterError(err) {
|
||||
return p, err
|
||||
}
|
||||
}
|
||||
|
||||
return nil, NoCompatiblePrinterError{Options: f, OutputFormat: f.OutputFormat}
|
||||
|
Loading…
Reference in New Issue
Block a user