diff --git a/docs/kubectl.md b/docs/kubectl.md index 026e115c81a..992cf657a41 100644 --- a/docs/kubectl.md +++ b/docs/kubectl.md @@ -338,7 +338,7 @@ Usage: kubectl config [command] Available Commands: - view displays the specified .kubeconfig file or a merged result + view displays merged .kubeconfig settings or a specified .kubeconfig file. set-cluster name [--server=server] [--certificate-authority=path/to/certficate/authority] [--api-version=apiversion] [--insecure-skip-tls-verify=true] Sets a cluster entry in .kubeconfig set-credentials name [--auth-path=path/to/auth/file] [--client-certificate=path/to/certficate/file] [--client-key=path/to/key/file] [--token=bearer_token_string] Sets a user entry in .kubeconfig set-context name [--cluster=cluster-nickname] [--user=user-nickname] [--namespace=namespace] Sets a context entry in .kubeconfig @@ -395,7 +395,13 @@ Use "kubectl help [command]" for more information about that command. ``` #### config view -displays the specified .kubeconfig file or a merged result +displays merged .kubeconfig settings or a specified .kubeconfig file. +Examples: + // Show merged .kubeconfig settings. + $ kubectl config view + + // Show only local ./.kubeconfig settings + $ kubectl config view --local Usage: ``` @@ -421,10 +427,14 @@ Usage: --log_flush_frequency=5s: Maximum number of seconds between log flushes --logtostderr=true: log to standard error instead of files --match-server-version=false: Require server version to match client version - --merge=false: merge together the full hierarchy of .kubeconfig files + --merge=true: merge together the full hierarchy of .kubeconfig files --namespace="": If present, the namespace scope for this CLI request. + --no-headers=false: When using the default output, don't print headers + -o, --output="": Output format: json|yaml|template|templatefile + --output-version="": Output the formatted object with the given version (default api-version) -s, --server="": The address of the Kubernetes API server --stderrthreshold=2: logs at or above this threshold go to stderr + -t, --template="": Template string or path to template file to use when -o=template or -o=templatefile. --token="": Bearer token for authentication to the API server. --user="": The name of the kubeconfig user to use --v=0: log level for V logs diff --git a/pkg/kubectl/cmd/cmd.go b/pkg/kubectl/cmd/cmd.go index 53468cb0faf..2c186684a75 100644 --- a/pkg/kubectl/cmd/cmd.go +++ b/pkg/kubectl/cmd/cmd.go @@ -29,6 +29,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" cmdconfig "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/config" + cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource" "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" @@ -143,7 +144,7 @@ func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory { return kubectl.ReaperFor(mapping.Kind, client) }, Validator: func(cmd *cobra.Command) (validation.Schema, error) { - if GetFlagBool(cmd, "validate") { + if cmdutil.GetFlagBool(cmd, "validate") { client, err := clients.ClientForVersion("") if err != nil { return nil, err @@ -217,6 +218,62 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`, return cmds } +// PrintObject prints an api object given command line flags to modify the output format +func (f *Factory) PrintObject(cmd *cobra.Command, obj runtime.Object, out io.Writer) error { + mapper, _ := f.Object(cmd) + _, kind, err := api.Scheme.ObjectVersionAndKind(obj) + if err != nil { + return err + } + + mapping, err := mapper.RESTMapping(kind) + if err != nil { + return err + } + + printer, err := f.PrinterForMapping(cmd, mapping) + if err != nil { + return err + } + return printer.PrintObj(obj, out) +} + +// PrinterForMapping returns a printer suitable for displaying the provided resource type. +// Requires that printer flags have been added to cmd (see AddPrinterFlags). +func (f *Factory) PrinterForMapping(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.ResourcePrinter, error) { + printer, ok, err := cmdutil.PrinterForCommand(cmd) + if err != nil { + return nil, err + } + if ok { + clientConfig, err := f.ClientConfig(cmd) + checkErr(err) + defaultVersion := clientConfig.Version + + version := cmdutil.OutputVersion(cmd, defaultVersion) + if len(version) == 0 { + version = mapping.APIVersion + } + if len(version) == 0 { + return nil, fmt.Errorf("you must specify an output-version when using this output format") + } + printer = kubectl.NewVersionedPrinter(printer, mapping.ObjectConvertor, version) + } else { + printer, err = f.Printer(cmd, mapping, cmdutil.GetFlagBool(cmd, "no-headers")) + if err != nil { + return nil, err + } + } + return printer, nil +} + +// ClientMapperForCommand returns a ClientMapper for the given command and factory. +func (f *Factory) ClientMapperForCommand(cmd *cobra.Command) resource.ClientMapper { + return resource.ClientMapperFunc(func(mapping *meta.RESTMapping) (resource.RESTClient, error) { + return f.RESTClient(cmd, mapping) + }) +} + // DefaultClientConfig creates a clientcmd.ClientConfig with the following hierarchy: // 1. Use the kubeconfig builder. The number of merges and overrides here gets a little crazy. Stay with me. // 1. Merge together the kubeconfig itself. This is done with the following hierarchy and merge rules: @@ -266,13 +323,6 @@ func DefaultClientConfig(flags *pflag.FlagSet) clientcmd.ClientConfig { return clientConfig } -// ClientMapperForCommand returns a ClientMapper for the given command and factory. -func ClientMapperForCommand(cmd *cobra.Command, f *Factory) resource.ClientMapper { - return resource.ClientMapperFunc(func(mapping *meta.RESTMapping) (resource.RESTClient, error) { - return f.RESTClient(cmd, mapping) - }) -} - func checkErr(err error) { if err != nil { glog.FatalDepth(1, err) diff --git a/pkg/kubectl/cmd/cmd_test.go b/pkg/kubectl/cmd/cmd_test.go index ef5dc0bc674..e813e9f7414 100644 --- a/pkg/kubectl/cmd/cmd_test.go +++ b/pkg/kubectl/cmd/cmd_test.go @@ -21,6 +21,7 @@ import ( "fmt" "io" "io/ioutil" + "os" "testing" "github.com/GoogleCloudPlatform/kubernetes/pkg/api" @@ -203,3 +204,43 @@ func TestClientVersions(t *testing.T) { } } } + +func ExamplePrintReplicationController() { + f, tf, codec := NewAPIFactory() + tf.Printer = kubectl.NewHumanReadablePrinter(false) + tf.Client = &client.FakeRESTClient{ + Codec: codec, + Client: nil, + } + cmd := f.NewCmdRunContainer(os.Stdout) + ctrl := &api.ReplicationController{ + ObjectMeta: api.ObjectMeta{ + Name: "foo", + Labels: map[string]string{"foo": "bar"}, + }, + Spec: api.ReplicationControllerSpec{ + Replicas: 1, + Selector: map[string]string{"foo": "bar"}, + Template: &api.PodTemplateSpec{ + ObjectMeta: api.ObjectMeta{ + Labels: map[string]string{"foo": "bar"}, + }, + Spec: api.PodSpec{ + Containers: []api.Container{ + { + Name: "foo", + Image: "someimage", + }, + }, + }, + }, + }, + } + err := f.PrintObject(cmd, ctrl, os.Stdout) + if err != nil { + fmt.Printf("Unexpected error: %v", err) + } + // Output: + // CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS + // foo foo someimage foo=bar 1 +} diff --git a/pkg/kubectl/cmd/config/view.go b/pkg/kubectl/cmd/config/view.go index 4f8c83fc50e..738746d9896 100644 --- a/pkg/kubectl/cmd/config/view.go +++ b/pkg/kubectl/cmd/config/view.go @@ -21,11 +21,12 @@ import ( "io" "os" - "github.com/ghodss/yaml" + "github.com/golang/glog" "github.com/spf13/cobra" "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd" clientcmdapi "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd/api" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" ) type viewOptions struct { @@ -38,40 +39,45 @@ func NewCmdConfigView(out io.Writer, pathOptions *pathOptions) *cobra.Command { cmd := &cobra.Command{ Use: "view", - Short: "displays the specified .kubeconfig file or a merged result", - Long: `displays the specified .kubeconfig file or a merged result`, + Short: "displays merged .kubeconfig settings or a specified .kubeconfig file.", + Long: `displays merged .kubeconfig settings or a specified .kubeconfig file. +Examples: + // Show merged .kubeconfig settings. + $ kubectl config view + + // Show only local ./.kubeconfig settings + $ kubectl config view --local`, Run: func(cmd *cobra.Command, args []string) { - err := options.run() + printer, _, err := util.PrinterForCommand(cmd) if err != nil { - fmt.Printf("%v\n", err) + glog.FatalDepth(1, err) + } + config, err := options.loadConfig() + if err != nil { + glog.FatalDepth(1, err) + } + err = printer.PrintObj(config, out) + if err != nil { + glog.FatalDepth(1, err) } }, } - cmd.Flags().BoolVar(&options.merge, "merge", false, "merge together the full hierarchy of .kubeconfig files") - + util.AddPrinterFlags(cmd) + // Default to yaml + cmd.Flags().Set("output", "yaml") + cmd.Flags().BoolVar(&options.merge, "merge", true, "merge together the full hierarchy of .kubeconfig files") return cmd } -func (o viewOptions) run() error { +func (o viewOptions) loadConfig() (*clientcmdapi.Config, error) { err := o.validate() if err != nil { - return err + return nil, err } config, _, err := o.getStartingConfig() - if err != nil { - return err - } - - content, err := yaml.Marshal(config) - if err != nil { - return err - } - - fmt.Printf("%v", string(content)) - - return nil + return config, err } func (o viewOptions) validate() error { diff --git a/pkg/kubectl/cmd/create.go b/pkg/kubectl/cmd/create.go index 1038560eed6..07fef112291 100644 --- a/pkg/kubectl/cmd/create.go +++ b/pkg/kubectl/cmd/create.go @@ -51,7 +51,7 @@ Examples: checkErr(err) mapper, typer := f.Object(cmd) - r := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)). + r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)). ContinueOnError(). NamespaceParam(cmdNamespace).RequireNamespace(). FilenameParam(flags.Filenames...). diff --git a/pkg/kubectl/cmd/delete.go b/pkg/kubectl/cmd/delete.go index 94704056388..753ecf69314 100644 --- a/pkg/kubectl/cmd/delete.go +++ b/pkg/kubectl/cmd/delete.go @@ -23,6 +23,7 @@ import ( "github.com/spf13/cobra" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/errors" + cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" ) @@ -62,11 +63,11 @@ Examples: checkErr(err) mapper, typer := f.Object(cmd) - r := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)). + r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)). ContinueOnError(). NamespaceParam(cmdNamespace).DefaultNamespace(). FilenameParam(flags.Filenames...). - SelectorParam(GetFlagString(cmd, "selector")). + SelectorParam(cmdutil.GetFlagString(cmd, "selector")). ResourceTypeOrNameArgs(args...). Flatten(). Do() diff --git a/pkg/kubectl/cmd/describe.go b/pkg/kubectl/cmd/describe.go index 7950d57cb73..a8770afda7e 100644 --- a/pkg/kubectl/cmd/describe.go +++ b/pkg/kubectl/cmd/describe.go @@ -20,6 +20,7 @@ import ( "fmt" "io" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/spf13/cobra" ) @@ -36,7 +37,7 @@ given resource.`, checkErr(err) mapper, _ := f.Object(cmd) - mapping, namespace, name := ResourceFromArgs(cmd, args, mapper, cmdNamespace) + mapping, namespace, name := util.ResourceFromArgs(cmd, args, mapper, cmdNamespace) describer, err := f.Describer(cmd, mapping) checkErr(err) diff --git a/pkg/kubectl/cmd/expose.go b/pkg/kubectl/cmd/expose.go index 956da11f3ba..d4ae9d268f0 100644 --- a/pkg/kubectl/cmd/expose.go +++ b/pkg/kubectl/cmd/expose.go @@ -22,6 +22,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/spf13/cobra" ) @@ -51,27 +52,28 @@ $ kubectl expose streamer --port=4100 --protocol=udp --service-name=video-stream client, err := f.Client(cmd) checkErr(err) - generatorName := GetFlagString(cmd, "generator") + generatorName := util.GetFlagString(cmd, "generator") + generator, found := kubectl.Generators[generatorName] if !found { usageError(cmd, fmt.Sprintf("Generator: %s not found.", generator)) } - if GetFlagInt(cmd, "port") < 1 { + if util.GetFlagInt(cmd, "port") < 1 { usageError(cmd, "--port is required and must be a positive integer.") } names := generator.ParamNames() params := kubectl.MakeParams(cmd, names) - if len(GetFlagString(cmd, "service-name")) == 0 { + if len(util.GetFlagString(cmd, "service-name")) == 0 { params["name"] = args[0] } else { - params["name"] = GetFlagString(cmd, "service-name") + params["name"] = util.GetFlagString(cmd, "service-name") } if _, found := params["selector"]; !found { rc, err := client.ReplicationControllers(namespace).Get(args[0]) checkErr(err) params["selector"] = kubectl.MakeLabels(rc.Spec.Selector) } - if GetFlagBool(cmd, "create-external-load-balancer") { + if util.GetFlagBool(cmd, "create-external-load-balancer") { params["create-external-load-balancer"] = "true" } @@ -81,22 +83,22 @@ $ kubectl expose streamer --port=4100 --protocol=udp --service-name=video-stream service, err := generator.Generate(params) checkErr(err) - inline := GetFlagString(cmd, "overrides") + inline := util.GetFlagString(cmd, "overrides") if len(inline) > 0 { - Merge(service, inline, "Service") + util.Merge(service, inline, "Service") } // TODO: extract this flag to a central location, when such a location exists. - if !GetFlagBool(cmd, "dry-run") { + if !util.GetFlagBool(cmd, "dry-run") { service, err = client.Services(namespace).Create(service.(*api.Service)) checkErr(err) } - err = PrintObject(cmd, service, f, out) + err = f.PrintObject(cmd, service, out) checkErr(err) }, } - AddPrinterFlags(cmd) + util.AddPrinterFlags(cmd) cmd.Flags().String("generator", "service/v1", "The name of the api generator that you want to use. Default 'service/v1'") cmd.Flags().String("protocol", "TCP", "The network protocol for the service you want to be created. Default 'tcp'") cmd.Flags().Int("port", -1, "The port that the service should serve on. Required.") diff --git a/pkg/kubectl/cmd/get.go b/pkg/kubectl/cmd/get.go index 273fc1d8688..25977c31ab4 100644 --- a/pkg/kubectl/cmd/get.go +++ b/pkg/kubectl/cmd/get.go @@ -23,6 +23,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch" @@ -59,7 +60,7 @@ Examples: RunGet(f, out, cmd, args) }, } - AddPrinterFlags(cmd) + util.AddPrinterFlags(cmd) cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on") cmd.Flags().BoolP("watch", "w", false, "After listing/getting the requested object, watch for changes.") cmd.Flags().Bool("watch-only", false, "Watch for changes to the requested object(s), without listing/getting first.") @@ -70,16 +71,16 @@ Examples: // TODO: convert all direct flag accessors to a struct and pass that instead of cmd // TODO: return an error instead of using glog.Fatal and checkErr func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) { - selector := GetFlagString(cmd, "selector") + selector := util.GetFlagString(cmd, "selector") mapper, typer := f.Object(cmd) cmdNamespace, err := f.DefaultNamespace(cmd) checkErr(err) // handle watch separately since we cannot watch multiple resource types - isWatch, isWatchOnly := GetFlagBool(cmd, "watch"), GetFlagBool(cmd, "watch-only") + isWatch, isWatchOnly := util.GetFlagBool(cmd, "watch"), util.GetFlagBool(cmd, "watch-only") if isWatch || isWatchOnly { - r := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)). + r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)). NamespaceParam(cmdNamespace).DefaultNamespace(). SelectorParam(selector). ResourceTypeOrNameArgs(args...). @@ -89,7 +90,7 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) { mapping, err := r.ResourceMapping() checkErr(err) - printer, err := PrinterForMapping(f, cmd, mapping) + printer, err := f.PrinterForMapping(cmd, mapping) checkErr(err) obj, err := r.Object() @@ -115,12 +116,12 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) { return } - b := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)). + b := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)). NamespaceParam(cmdNamespace).DefaultNamespace(). SelectorParam(selector). ResourceTypeOrNameArgs(args...). Latest() - printer, generic, err := PrinterForCommand(cmd) + printer, generic, err := util.PrinterForCommand(cmd) checkErr(err) if generic { @@ -129,7 +130,7 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) { defaultVersion := clientConfig.Version // the outermost object will be converted to the output-version - version := outputVersion(cmd, defaultVersion) + version := util.OutputVersion(cmd, defaultVersion) if len(version) == 0 { // TODO: add a new ResourceBuilder mode for Object() that attempts to ensure the objects // are in the appropriate version if one exists (and if not, use the best effort). @@ -149,7 +150,7 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) { // use the default printer for each object err = b.Do().Visit(func(r *resource.Info) error { - printer, err := PrinterForMapping(f, cmd, r.Mapping) + printer, err := f.PrinterForMapping(cmd, r.Mapping) if err != nil { return err } diff --git a/pkg/kubectl/cmd/log.go b/pkg/kubectl/cmd/log.go index f1067172b5d..7a8f768ce34 100644 --- a/pkg/kubectl/cmd/log.go +++ b/pkg/kubectl/cmd/log.go @@ -20,6 +20,7 @@ import ( "io" "strconv" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/spf13/cobra" ) @@ -66,7 +67,7 @@ Examples: } follow := false - if GetFlagBool(cmd, "follow") { + if util.GetFlagBool(cmd, "follow") { follow = true } diff --git a/pkg/kubectl/cmd/printing_test.go b/pkg/kubectl/cmd/printing_test.go deleted file mode 100644 index 9dc8d06d99b..00000000000 --- a/pkg/kubectl/cmd/printing_test.go +++ /dev/null @@ -1,67 +0,0 @@ -/* -Copyright 2014 Google Inc. All rights reserved. - -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 cmd_test - -import ( - "fmt" - "os" - - "github.com/GoogleCloudPlatform/kubernetes/pkg/api" - "github.com/GoogleCloudPlatform/kubernetes/pkg/client" - "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" - . "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd" -) - -func ExamplePrintReplicationController() { - f, tf, codec := NewAPIFactory() - tf.Printer = kubectl.NewHumanReadablePrinter(false) - tf.Client = &client.FakeRESTClient{ - Codec: codec, - Client: nil, - } - cmd := f.NewCmdRunContainer(os.Stdout) - ctrl := &api.ReplicationController{ - ObjectMeta: api.ObjectMeta{ - Name: "foo", - Labels: map[string]string{"foo": "bar"}, - }, - Spec: api.ReplicationControllerSpec{ - Replicas: 1, - Selector: map[string]string{"foo": "bar"}, - Template: &api.PodTemplateSpec{ - ObjectMeta: api.ObjectMeta{ - Labels: map[string]string{"foo": "bar"}, - }, - Spec: api.PodSpec{ - Containers: []api.Container{ - { - Name: "foo", - Image: "someimage", - }, - }, - }, - }, - }, - } - err := PrintObject(cmd, ctrl, f, os.Stdout) - if err != nil { - fmt.Printf("Unexpected error: %v", err) - } - // Output: - // CONTROLLER CONTAINER(S) IMAGE(S) SELECTOR REPLICAS - // foo foo someimage foo=bar 1 -} diff --git a/pkg/kubectl/cmd/proxy.go b/pkg/kubectl/cmd/proxy.go index 508c01b5a72..4896be6f5f8 100644 --- a/pkg/kubectl/cmd/proxy.go +++ b/pkg/kubectl/cmd/proxy.go @@ -21,6 +21,7 @@ import ( "strings" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/golang/glog" "github.com/spf13/cobra" ) @@ -31,17 +32,17 @@ func (f *Factory) NewCmdProxy(out io.Writer) *cobra.Command { Short: "Run a proxy to the Kubernetes API server", Long: `Run a proxy to the Kubernetes API server.`, Run: func(cmd *cobra.Command, args []string) { - port := GetFlagInt(cmd, "port") + port := util.GetFlagInt(cmd, "port") glog.Infof("Starting to serve on localhost:%d", port) clientConfig, err := f.ClientConfig(cmd) checkErr(err) - staticPrefix := GetFlagString(cmd, "www-prefix") + staticPrefix := util.GetFlagString(cmd, "www-prefix") if !strings.HasSuffix(staticPrefix, "/") { staticPrefix += "/" } - server, err := kubectl.NewProxyServer(GetFlagString(cmd, "www"), staticPrefix, clientConfig) + server, err := kubectl.NewProxyServer(util.GetFlagString(cmd, "www"), staticPrefix, clientConfig) checkErr(err) glog.Fatal(server.Serve(port)) }, diff --git a/pkg/kubectl/cmd/resize.go b/pkg/kubectl/cmd/resize.go index 2a547663427..d04c564498a 100644 --- a/pkg/kubectl/cmd/resize.go +++ b/pkg/kubectl/cmd/resize.go @@ -21,6 +21,7 @@ import ( "io" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/spf13/cobra" ) @@ -44,7 +45,7 @@ Examples: $ kubectl resize --current-replicas=2 --replicas=3 replicationcontrollers foo `, Run: func(cmd *cobra.Command, args []string) { - count := GetFlagInt(cmd, "replicas") + count := util.GetFlagInt(cmd, "replicas") if len(args) != 2 || count < 0 { usageError(cmd, "--replicas= ") } @@ -53,13 +54,13 @@ Examples: checkErr(err) mapper, _ := f.Object(cmd) - mapping, namespace, name := ResourceFromArgs(cmd, args, mapper, cmdNamespace) + mapping, namespace, name := util.ResourceFromArgs(cmd, args, mapper, cmdNamespace) resizer, err := f.Resizer(cmd, mapping) checkErr(err) - resourceVersion := GetFlagString(cmd, "resource-version") - currentSize := GetFlagInt(cmd, "current-replicas") + resourceVersion := util.GetFlagString(cmd, "resource-version") + currentSize := util.GetFlagInt(cmd, "current-replicas") s, err := resizer.Resize(namespace, name, &kubectl.ResizePrecondition{currentSize, resourceVersion}, uint(count)) checkErr(err) fmt.Fprintf(out, "%s\n", s) diff --git a/pkg/kubectl/cmd/rollingupdate.go b/pkg/kubectl/cmd/rollingupdate.go index 4cf57c565ba..8abcba5b801 100644 --- a/pkg/kubectl/cmd/rollingupdate.go +++ b/pkg/kubectl/cmd/rollingupdate.go @@ -22,6 +22,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/spf13/cobra" ) @@ -48,13 +49,13 @@ $ kubectl rollingupdate frontend-v1 -f frontend-v2.json $ cat frontend-v2.json | kubectl rollingupdate frontend-v1 -f - `, Run: func(cmd *cobra.Command, args []string) { - filename := GetFlagString(cmd, "filename") + filename := util.GetFlagString(cmd, "filename") if len(filename) == 0 { usageError(cmd, "Must specify filename for new controller") } - period := GetFlagDuration(cmd, "update-period") - interval := GetFlagDuration(cmd, "poll-interval") - timeout := GetFlagDuration(cmd, "timeout") + period := util.GetFlagDuration(cmd, "update-period") + interval := util.GetFlagDuration(cmd, "poll-interval") + timeout := util.GetFlagDuration(cmd, "timeout") if len(args) != 1 { usageError(cmd, "Must specify the controller to update") } @@ -67,7 +68,7 @@ $ cat frontend-v2.json | kubectl rollingupdate frontend-v1 -f - cmdApiVersion := clientConfig.Version mapper, typer := f.Object(cmd) - mapping, namespace, newName, data := ResourceFromFile(filename, typer, mapper, schema, cmdApiVersion) + mapping, namespace, newName, data := util.ResourceFromFile(filename, typer, mapper, schema, cmdApiVersion) if mapping.Kind != "ReplicationController" { usageError(cmd, "%s does not specify a valid ReplicationController", filename) } @@ -78,7 +79,7 @@ $ cat frontend-v2.json | kubectl rollingupdate frontend-v1 -f - cmdNamespace, err := f.DefaultNamespace(cmd) checkErr(err) - err = CompareNamespace(cmdNamespace, namespace) + err = util.CompareNamespace(cmdNamespace, namespace) checkErr(err) client, err := f.Client(cmd) diff --git a/pkg/kubectl/cmd/run.go b/pkg/kubectl/cmd/run.go index dc96df3959d..3b6bcab5adf 100644 --- a/pkg/kubectl/cmd/run.go +++ b/pkg/kubectl/cmd/run.go @@ -22,6 +22,7 @@ import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/spf13/cobra" ) @@ -55,7 +56,7 @@ Examples: client, err := f.Client(cmd) checkErr(err) - generatorName := GetFlagString(cmd, "generator") + generatorName := util.GetFlagString(cmd, "generator") generator, found := kubectl.Generators[generatorName] if !found { usageError(cmd, fmt.Sprintf("Generator: %s not found.", generator)) @@ -70,22 +71,22 @@ Examples: controller, err := generator.Generate(params) checkErr(err) - inline := GetFlagString(cmd, "overrides") + inline := util.GetFlagString(cmd, "overrides") if len(inline) > 0 { - Merge(controller, inline, "ReplicationController") + util.Merge(controller, inline, "ReplicationController") } // TODO: extract this flag to a central location, when such a location exists. - if !GetFlagBool(cmd, "dry-run") { + if !util.GetFlagBool(cmd, "dry-run") { controller, err = client.ReplicationControllers(namespace).Create(controller.(*api.ReplicationController)) checkErr(err) } - err = PrintObject(cmd, controller, f, out) + err = f.PrintObject(cmd, controller, out) checkErr(err) }, } - AddPrinterFlags(cmd) + util.AddPrinterFlags(cmd) cmd.Flags().String("generator", "run-container/v1", "The name of the api generator that you want to use. Default 'run-container-controller/v1'") cmd.Flags().String("image", "", "The image for the container you wish to run.") cmd.Flags().IntP("replicas", "r", 1, "Number of replicas to create for this container. Default 1") diff --git a/pkg/kubectl/cmd/stop.go b/pkg/kubectl/cmd/stop.go index 17e2782f3d0..3da95bf67a3 100644 --- a/pkg/kubectl/cmd/stop.go +++ b/pkg/kubectl/cmd/stop.go @@ -20,6 +20,7 @@ import ( "fmt" "io" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/spf13/cobra" ) @@ -42,7 +43,7 @@ Examples: } cmdNamespace, err := f.DefaultNamespace(cmd) mapper, _ := f.Object(cmd) - mapping, namespace, name := ResourceFromArgs(cmd, args, mapper, cmdNamespace) + mapping, namespace, name := util.ResourceFromArgs(cmd, args, mapper, cmdNamespace) reaper, err := f.Reaper(cmd, mapping) checkErr(err) diff --git a/pkg/kubectl/cmd/update.go b/pkg/kubectl/cmd/update.go index 69ebb5b19a4..83c239355f0 100644 --- a/pkg/kubectl/cmd/update.go +++ b/pkg/kubectl/cmd/update.go @@ -20,6 +20,7 @@ import ( "fmt" "io" + cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/spf13/cobra" @@ -53,14 +54,14 @@ Examples: checkErr(err) mapper, typer := f.Object(cmd) - r := resource.NewBuilder(mapper, typer, ClientMapperForCommand(cmd, f)). + r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand(cmd)). ContinueOnError(). NamespaceParam(cmdNamespace).RequireNamespace(). FilenameParam(flags.Filenames...). Flatten(). Do() - patch := GetFlagString(cmd, "patch") + patch := cmdutil.GetFlagString(cmd, "patch") if len(flags.Filenames) == 0 && len(patch) == 0 { usageError(cmd, "Must specify --filename or --patch to update") } @@ -102,7 +103,7 @@ func updateWithPatch(cmd *cobra.Command, args []string, f *Factory, patch string checkErr(err) mapper, _ := f.Object(cmd) - mapping, namespace, name := ResourceFromArgs(cmd, args, mapper, cmdNamespace) + mapping, namespace, name := cmdutil.ResourceFromArgs(cmd, args, mapper, cmdNamespace) client, err := f.RESTClient(cmd, mapping) checkErr(err) @@ -110,7 +111,7 @@ func updateWithPatch(cmd *cobra.Command, args []string, f *Factory, patch string obj, err := helper.Get(namespace, name) checkErr(err) - Merge(obj, patch, mapping.Kind) + cmdutil.Merge(obj, patch, mapping.Kind) data, err := helper.Codec.Encode(obj) checkErr(err) diff --git a/pkg/kubectl/cmd/helpers.go b/pkg/kubectl/cmd/util/helpers.go similarity index 95% rename from pkg/kubectl/cmd/helpers.go rename to pkg/kubectl/cmd/util/helpers.go index aa3c7053cdc..d3001c059d4 100644 --- a/pkg/kubectl/cmd/helpers.go +++ b/pkg/kubectl/cmd/util/helpers.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package util import ( "encoding/json" @@ -34,6 +34,18 @@ import ( "github.com/spf13/cobra" ) +func checkErr(err error) { + if err != nil { + glog.FatalDepth(1, err) + } +} + +func usageError(cmd *cobra.Command, format string, args ...interface{}) { + glog.Errorf(format, args...) + glog.Errorf("See '%s -h' for help.", cmd.CommandPath()) + os.Exit(1) +} + func GetFlagString(cmd *cobra.Command, flag string) string { f := cmd.Flags().Lookup(flag) if f == nil { diff --git a/pkg/kubectl/cmd/helpers_test.go b/pkg/kubectl/cmd/util/helpers_test.go similarity index 99% rename from pkg/kubectl/cmd/helpers_test.go rename to pkg/kubectl/cmd/util/helpers_test.go index ed0ec504ea3..32673373c74 100644 --- a/pkg/kubectl/cmd/helpers_test.go +++ b/pkg/kubectl/cmd/util/helpers_test.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package util import ( "reflect" diff --git a/pkg/kubectl/cmd/printing.go b/pkg/kubectl/cmd/util/printing.go similarity index 50% rename from pkg/kubectl/cmd/printing.go rename to pkg/kubectl/cmd/util/printing.go index 3f3b5ad5bae..284b5442c00 100644 --- a/pkg/kubectl/cmd/printing.go +++ b/pkg/kubectl/cmd/util/printing.go @@ -14,16 +14,10 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package util import ( - "fmt" - "io" - - "github.com/GoogleCloudPlatform/kubernetes/pkg/api" - "github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" - "github.com/GoogleCloudPlatform/kubernetes/pkg/runtime" "github.com/spf13/cobra" ) @@ -35,28 +29,8 @@ func AddPrinterFlags(cmd *cobra.Command) { cmd.Flags().StringP("template", "t", "", "Template string or path to template file to use when -o=template or -o=templatefile.") } -// PrintObject prints an api object given command line flags to modify the output format -func PrintObject(cmd *cobra.Command, obj runtime.Object, f *Factory, out io.Writer) error { - mapper, _ := f.Object(cmd) - _, kind, err := api.Scheme.ObjectVersionAndKind(obj) - if err != nil { - return err - } - - mapping, err := mapper.RESTMapping(kind) - if err != nil { - return err - } - - printer, err := PrinterForMapping(f, cmd, mapping) - if err != nil { - return err - } - return printer.PrintObj(obj, out) -} - -// outputVersion returns the preferred output version for generic content (JSON, YAML, or templates) -func outputVersion(cmd *cobra.Command, defaultVersion string) string { +// OutputVersion returns the preferred output version for generic content (JSON, YAML, or templates) +func OutputVersion(cmd *cobra.Command, defaultVersion string) string { outputVersion := GetFlagString(cmd, "output-version") if len(outputVersion) == 0 { outputVersion = defaultVersion @@ -75,32 +49,3 @@ func PrinterForCommand(cmd *cobra.Command) (kubectl.ResourcePrinter, bool, error return kubectl.GetPrinter(outputFormat, templateFile) } - -// PrinterForMapping returns a printer suitable for displaying the provided resource type. -// Requires that printer flags have been added to cmd (see AddPrinterFlags). -func PrinterForMapping(f *Factory, cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.ResourcePrinter, error) { - printer, ok, err := PrinterForCommand(cmd) - if err != nil { - return nil, err - } - if ok { - clientConfig, err := f.ClientConfig(cmd) - checkErr(err) - defaultVersion := clientConfig.Version - - version := outputVersion(cmd, defaultVersion) - if len(version) == 0 { - version = mapping.APIVersion - } - if len(version) == 0 { - return nil, fmt.Errorf("you must specify an output-version when using this output format") - } - printer = kubectl.NewVersionedPrinter(printer, mapping.ObjectConvertor, version) - } else { - printer, err = f.Printer(cmd, mapping, GetFlagBool(cmd, "no-headers")) - if err != nil { - return nil, err - } - } - return printer, nil -} diff --git a/pkg/kubectl/cmd/resource.go b/pkg/kubectl/cmd/util/resource.go similarity index 99% rename from pkg/kubectl/cmd/resource.go rename to pkg/kubectl/cmd/util/resource.go index ab440996786..a4f4ca9310b 100644 --- a/pkg/kubectl/cmd/resource.go +++ b/pkg/kubectl/cmd/util/resource.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -package cmd +package util import ( "fmt" diff --git a/pkg/kubectl/cmd/version.go b/pkg/kubectl/cmd/version.go index 5e434a58e16..0a8282ec5b3 100644 --- a/pkg/kubectl/cmd/version.go +++ b/pkg/kubectl/cmd/version.go @@ -22,6 +22,7 @@ import ( "github.com/spf13/cobra" "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl" + "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util" ) func (f *Factory) NewCmdVersion(out io.Writer) *cobra.Command { @@ -29,7 +30,7 @@ func (f *Factory) NewCmdVersion(out io.Writer) *cobra.Command { Use: "version", Short: "Print version of client and server", Run: func(cmd *cobra.Command, args []string) { - if GetFlagBool(cmd, "client") { + if util.GetFlagBool(cmd, "client") { kubectl.GetClientVersion(out) return }