mirror of https://github.com/k3s-io/k3s
refactor to move kubectl.cmd.Factory to kubect/cmd/util
parent
13b805fe1e
commit
6344cf3c3a
|
@ -25,6 +25,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
@ -139,7 +140,7 @@ func main() {
|
|||
// regardless of where we run.
|
||||
os.Setenv("HOME", "/home/username")
|
||||
//TODO os.Stdin should really be something like ioutil.Discard, but a Reader
|
||||
kubectl := cmd.NewFactory(nil).NewKubectlCommand(os.Stdin, ioutil.Discard, ioutil.Discard)
|
||||
kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard)
|
||||
genMarkdown(kubectl, "", docsDir)
|
||||
for _, c := range kubectl.Commands() {
|
||||
genMarkdown(c, "kubectl", docsDir)
|
||||
|
|
|
@ -25,6 +25,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/cpuguy83/go-md2man/mangen"
|
||||
"github.com/russross/blackfriday"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -63,7 +64,7 @@ func main() {
|
|||
// regardless of where we run.
|
||||
os.Setenv("HOME", "/home/username")
|
||||
//TODO os.Stdin should really be something like ioutil.Discard, but a Reader
|
||||
kubectl := cmd.NewFactory(nil).NewKubectlCommand(os.Stdin, ioutil.Discard, ioutil.Discard)
|
||||
kubectl := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, ioutil.Discard, ioutil.Discard)
|
||||
genMarkdown(kubectl, "", docsDir)
|
||||
for _, c := range kubectl.Commands() {
|
||||
genMarkdown(c, "kubectl", docsDir)
|
||||
|
|
|
@ -21,11 +21,12 @@ import (
|
|||
"runtime"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
)
|
||||
|
||||
func main() {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
cmd := cmd.NewFactory(nil).NewKubectlCommand(os.Stdin, os.Stdout, os.Stderr)
|
||||
cmd := cmd.NewKubectlCommand(cmdutil.NewFactory(nil), os.Stdin, os.Stdout, os.Stderr)
|
||||
if err := cmd.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
|
@ -23,10 +23,10 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
)
|
||||
|
||||
func (f *Factory) NewCmdApiVersions(out io.Writer) *cobra.Command {
|
||||
func NewCmdApiVersions(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "api-versions",
|
||||
// apiversions is deprecated.
|
||||
|
@ -34,13 +34,13 @@ func (f *Factory) NewCmdApiVersions(out io.Writer) *cobra.Command {
|
|||
Short: "Print available API versions.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunApiVersions(f, out)
|
||||
util.CheckErr(err)
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func RunApiVersions(f *Factory, out io.Writer) error {
|
||||
func RunApiVersions(f *cmdutil.Factory, out io.Writer) error {
|
||||
if os.Args[1] == "apiversions" {
|
||||
printDeprecationWarning("api-versions", "apiversions")
|
||||
}
|
||||
|
|
|
@ -23,14 +23,14 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
|
||||
|
||||
"github.com/daviddengcn/go-colortext"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func (f *Factory) NewCmdClusterInfo(out io.Writer) *cobra.Command {
|
||||
func NewCmdClusterInfo(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "cluster-info",
|
||||
// clusterinfo is deprecated.
|
||||
|
@ -39,13 +39,13 @@ func (f *Factory) NewCmdClusterInfo(out io.Writer) *cobra.Command {
|
|||
Long: "Display addresses of the master and services with label kubernetes.io/cluster-service=true",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunClusterInfo(f, out, cmd)
|
||||
util.CheckErr(err)
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func RunClusterInfo(factory *Factory, out io.Writer, cmd *cobra.Command) error {
|
||||
func RunClusterInfo(factory *cmdutil.Factory, out io.Writer, cmd *cobra.Command) error {
|
||||
if os.Args[1] == "clusterinfo" {
|
||||
printDeprecationWarning("cluster-info", "clusterinfo")
|
||||
}
|
||||
|
|
|
@ -17,254 +17,17 @@ limitations under the License.
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
||||
"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"
|
||||
"github.com/golang/glog"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
)
|
||||
|
||||
const (
|
||||
FlagMatchBinaryVersion = "match-server-version"
|
||||
)
|
||||
|
||||
// Factory provides abstractions that allow the Kubectl command to be extended across multiple types
|
||||
// of resources and different API sets.
|
||||
// TODO: make the functions interfaces
|
||||
// TODO: pass the various interfaces on the factory directly into the command constructors (so the
|
||||
// commands are decoupled from the factory).
|
||||
type Factory struct {
|
||||
clients *clientCache
|
||||
flags *pflag.FlagSet
|
||||
|
||||
// Returns interfaces for dealing with arbitrary runtime.Objects.
|
||||
Object func() (meta.RESTMapper, runtime.ObjectTyper)
|
||||
// Returns a client for accessing Kubernetes resources or an error.
|
||||
Client func() (*client.Client, error)
|
||||
// Returns a client.Config for accessing the Kubernetes server.
|
||||
ClientConfig func() (*client.Config, error)
|
||||
// Returns a RESTClient for working with the specified RESTMapping or an error. This is intended
|
||||
// for working with arbitrary resources and is not guaranteed to point to a Kubernetes APIServer.
|
||||
RESTClient func(mapping *meta.RESTMapping) (resource.RESTClient, error)
|
||||
// Returns a Describer for displaying the specified RESTMapping type or an error.
|
||||
Describer func(mapping *meta.RESTMapping) (kubectl.Describer, error)
|
||||
// Returns a Printer for formatting objects of the given type or an error.
|
||||
Printer func(mapping *meta.RESTMapping, noHeaders bool) (kubectl.ResourcePrinter, error)
|
||||
// Returns a Resizer for changing the size of the specified RESTMapping type or an error
|
||||
Resizer func(mapping *meta.RESTMapping) (kubectl.Resizer, error)
|
||||
// Returns a Reaper for gracefully shutting down resources.
|
||||
Reaper func(mapping *meta.RESTMapping) (kubectl.Reaper, error)
|
||||
// PodSelectorForResource returns the pod selector associated with the provided resource name
|
||||
// or an error.
|
||||
PodSelectorForResource func(mapping *meta.RESTMapping, namespace, name string) (string, error)
|
||||
// PortForResource returns the ports associated with the provided resource name or an error
|
||||
PortsForResource func(mapping *meta.RESTMapping, namespace, name string) ([]string, error)
|
||||
// Returns a schema that can validate objects stored on disk.
|
||||
Validator func() (validation.Schema, error)
|
||||
// Returns the default namespace to use in cases where no other namespace is specified
|
||||
DefaultNamespace func() (string, error)
|
||||
}
|
||||
|
||||
func getPorts(spec api.PodSpec) []string {
|
||||
result := []string{}
|
||||
for _, container := range spec.Containers {
|
||||
for _, port := range container.Ports {
|
||||
result = append(result, strconv.Itoa(port.ContainerPort))
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// NewFactory creates a factory with the default Kubernetes resources defined
|
||||
// if optionalClientConfig is nil, then flags will be bound to a new clientcmd.ClientConfig.
|
||||
// if optionalClientConfig is not nil, then this factory will make use of it.
|
||||
func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
|
||||
mapper := kubectl.ShortcutExpander{latest.RESTMapper}
|
||||
|
||||
flags := pflag.NewFlagSet("", pflag.ContinueOnError)
|
||||
|
||||
clientConfig := optionalClientConfig
|
||||
if optionalClientConfig == nil {
|
||||
clientConfig = DefaultClientConfig(flags)
|
||||
}
|
||||
|
||||
clients := &clientCache{
|
||||
clients: make(map[string]*client.Client),
|
||||
loader: clientConfig,
|
||||
}
|
||||
|
||||
return &Factory{
|
||||
clients: clients,
|
||||
flags: flags,
|
||||
|
||||
Object: func() (meta.RESTMapper, runtime.ObjectTyper) {
|
||||
cfg, err := clientConfig.ClientConfig()
|
||||
cmdutil.CheckErr(err)
|
||||
cmdApiVersion := cfg.Version
|
||||
|
||||
return kubectl.OutputVersionMapper{mapper, cmdApiVersion}, api.Scheme
|
||||
},
|
||||
Client: func() (*client.Client, error) {
|
||||
return clients.ClientForVersion("")
|
||||
},
|
||||
ClientConfig: func() (*client.Config, error) {
|
||||
return clients.ClientConfigForVersion("")
|
||||
},
|
||||
RESTClient: func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
|
||||
client, err := clients.ClientForVersion(mapping.APIVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return client.RESTClient, nil
|
||||
},
|
||||
Describer: func(mapping *meta.RESTMapping) (kubectl.Describer, error) {
|
||||
client, err := clients.ClientForVersion(mapping.APIVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
describer, ok := kubectl.DescriberFor(mapping.Kind, client)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no description has been implemented for %q", mapping.Kind)
|
||||
}
|
||||
return describer, nil
|
||||
},
|
||||
Printer: func(mapping *meta.RESTMapping, noHeaders bool) (kubectl.ResourcePrinter, error) {
|
||||
return kubectl.NewHumanReadablePrinter(noHeaders), nil
|
||||
},
|
||||
PodSelectorForResource: func(mapping *meta.RESTMapping, namespace, name string) (string, error) {
|
||||
// TODO: replace with a swagger schema based approach (identify pod selector via schema introspection)
|
||||
client, err := clients.ClientForVersion("")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
switch mapping.Kind {
|
||||
case "ReplicationController":
|
||||
rc, err := client.ReplicationControllers(namespace).Get(name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return kubectl.MakeLabels(rc.Spec.Selector), nil
|
||||
case "Pod":
|
||||
rc, err := client.Pods(namespace).Get(name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(rc.Labels) == 0 {
|
||||
return "", fmt.Errorf("the pod has no labels and cannot be exposed")
|
||||
}
|
||||
return kubectl.MakeLabels(rc.Labels), nil
|
||||
case "Service":
|
||||
rc, err := client.ReplicationControllers(namespace).Get(name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if rc.Spec.Selector == nil {
|
||||
return "", fmt.Errorf("the service has no pod selector set")
|
||||
}
|
||||
return kubectl.MakeLabels(rc.Spec.Selector), nil
|
||||
default:
|
||||
return "", fmt.Errorf("it is not possible to get a pod selector from %s", mapping.Kind)
|
||||
}
|
||||
},
|
||||
PortsForResource: func(mapping *meta.RESTMapping, namespace, name string) ([]string, error) {
|
||||
// TODO: replace with a swagger schema based approach (identify pod selector via schema introspection)
|
||||
client, err := clients.ClientForVersion("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch mapping.Kind {
|
||||
case "ReplicationController":
|
||||
rc, err := client.ReplicationControllers(namespace).Get(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return getPorts(rc.Spec.Template.Spec), nil
|
||||
case "Pod":
|
||||
pod, err := client.Pods(namespace).Get(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return getPorts(pod.Spec), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("it is not possible to get ports from %s", mapping.Kind)
|
||||
}
|
||||
},
|
||||
Resizer: func(mapping *meta.RESTMapping) (kubectl.Resizer, error) {
|
||||
client, err := clients.ClientForVersion(mapping.APIVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return kubectl.ResizerFor(mapping.Kind, client)
|
||||
},
|
||||
Reaper: func(mapping *meta.RESTMapping) (kubectl.Reaper, error) {
|
||||
client, err := clients.ClientForVersion(mapping.APIVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return kubectl.ReaperFor(mapping.Kind, client)
|
||||
},
|
||||
Validator: func() (validation.Schema, error) {
|
||||
if flags.Lookup("validate").Value.String() == "true" {
|
||||
client, err := clients.ClientForVersion("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &clientSwaggerSchema{client, api.Scheme}, nil
|
||||
}
|
||||
return validation.NullSchema{}, nil
|
||||
},
|
||||
DefaultNamespace: func() (string, error) {
|
||||
return clientConfig.Namespace()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// BindFlags adds any flags that are common to all kubectl sub commands.
|
||||
func (f *Factory) BindFlags(flags *pflag.FlagSet) {
|
||||
// any flags defined by external projects (not part of pflags)
|
||||
util.AddAllFlagsToPFlagSet(flags)
|
||||
|
||||
// This is necessary as github.com/spf13/cobra doesn't support "global"
|
||||
// pflags currently. See https://github.com/spf13/cobra/issues/44.
|
||||
util.AddPFlagSetToPFlagSet(pflag.CommandLine, flags)
|
||||
|
||||
// Hack for global access to validation flag.
|
||||
// TODO: Refactor out after configuration flag overhaul.
|
||||
if f.flags.Lookup("validate") == nil {
|
||||
f.flags.Bool("validate", false, "If true, use a schema to validate the input before sending it")
|
||||
}
|
||||
|
||||
if f.flags != nil {
|
||||
f.flags.VisitAll(func(flag *pflag.Flag) {
|
||||
flags.AddFlag(flag)
|
||||
})
|
||||
}
|
||||
|
||||
// Globally persistent flags across all subcommands.
|
||||
// TODO Change flag names to consts to allow safer lookup from subcommands.
|
||||
// TODO Add a verbose flag that turns on glog logging. Probably need a way
|
||||
// to do that automatically for every subcommand.
|
||||
flags.BoolVar(&f.clients.matchVersion, FlagMatchBinaryVersion, false, "Require server version to match client version")
|
||||
}
|
||||
|
||||
// NewKubectlCommand creates the `kubectl` command and its nested children.
|
||||
func (f *Factory) NewKubectlCommand(in io.Reader, out, err io.Writer) *cobra.Command {
|
||||
func NewKubectlCommand(f *cmdutil.Factory, in io.Reader, out, err io.Writer) *cobra.Command {
|
||||
// Parent command to which all subcommands are added.
|
||||
cmds := &cobra.Command{
|
||||
Use: "kubectl",
|
||||
|
@ -277,223 +40,39 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`,
|
|||
|
||||
f.BindFlags(cmds.PersistentFlags())
|
||||
|
||||
cmds.AddCommand(f.NewCmdGet(out))
|
||||
cmds.AddCommand(f.NewCmdDescribe(out))
|
||||
cmds.AddCommand(f.NewCmdCreate(out))
|
||||
cmds.AddCommand(f.NewCmdUpdate(out))
|
||||
cmds.AddCommand(f.NewCmdDelete(out))
|
||||
cmds.AddCommand(NewCmdGet(f, out))
|
||||
cmds.AddCommand(NewCmdDescribe(f, out))
|
||||
cmds.AddCommand(NewCmdCreate(f, out))
|
||||
cmds.AddCommand(NewCmdUpdate(f, out))
|
||||
cmds.AddCommand(NewCmdDelete(f, out))
|
||||
|
||||
cmds.AddCommand(NewCmdNamespace(out))
|
||||
cmds.AddCommand(f.NewCmdLog(out))
|
||||
cmds.AddCommand(f.NewCmdRollingUpdate(out))
|
||||
cmds.AddCommand(f.NewCmdResize(out))
|
||||
cmds.AddCommand(NewCmdLog(f, out))
|
||||
cmds.AddCommand(NewCmdRollingUpdate(f, out))
|
||||
cmds.AddCommand(NewCmdResize(f, out))
|
||||
|
||||
cmds.AddCommand(f.NewCmdExec(in, out, err))
|
||||
cmds.AddCommand(f.NewCmdPortForward())
|
||||
cmds.AddCommand(f.NewCmdProxy(out))
|
||||
cmds.AddCommand(NewCmdExec(f, in, out, err))
|
||||
cmds.AddCommand(NewCmdPortForward(f))
|
||||
cmds.AddCommand(NewCmdProxy(f, out))
|
||||
|
||||
cmds.AddCommand(f.NewCmdRunContainer(out))
|
||||
cmds.AddCommand(f.NewCmdStop(out))
|
||||
cmds.AddCommand(f.NewCmdExposeService(out))
|
||||
cmds.AddCommand(NewCmdRunContainer(f, out))
|
||||
cmds.AddCommand(NewCmdStop(f, out))
|
||||
cmds.AddCommand(NewCmdExposeService(f, out))
|
||||
|
||||
cmds.AddCommand(f.NewCmdLabel(out))
|
||||
cmds.AddCommand(NewCmdLabel(f, out))
|
||||
|
||||
cmds.AddCommand(cmdconfig.NewCmdConfig(out))
|
||||
cmds.AddCommand(f.NewCmdClusterInfo(out))
|
||||
cmds.AddCommand(f.NewCmdApiVersions(out))
|
||||
cmds.AddCommand(f.NewCmdVersion(out))
|
||||
cmds.AddCommand(cmdconfig.NewCmdConfig(f, out))
|
||||
cmds.AddCommand(NewCmdClusterInfo(f, out))
|
||||
cmds.AddCommand(NewCmdApiVersions(f, out))
|
||||
cmds.AddCommand(NewCmdVersion(f, out))
|
||||
|
||||
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()
|
||||
_, 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()
|
||||
if err != nil {
|
||||
return nil, 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(mapping, cmdutil.GetFlagBool(cmd, "no-headers"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return printer, nil
|
||||
}
|
||||
|
||||
// ClientMapperForCommand returns a ClientMapper for the factory.
|
||||
func (f *Factory) ClientMapperForCommand() resource.ClientMapper {
|
||||
return resource.ClientMapperFunc(func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
|
||||
return f.RESTClient(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:
|
||||
// 1. CommandLineLocation - this parsed from the command line, so it must be late bound
|
||||
// 2. EnvVarLocation
|
||||
// 3. CurrentDirectoryLocation
|
||||
// 4. HomeDirectoryLocation
|
||||
// Empty filenames are ignored. Files with non-deserializable content produced errors.
|
||||
// The first file to set a particular value or map key wins and the value or map key is never changed.
|
||||
// This means that the first file to set CurrentContext will have its context preserved. It also means
|
||||
// that if two files specify a "red-user", only values from the first file's red-user are used. Even
|
||||
// non-conflicting entries from the second file's "red-user" are discarded.
|
||||
// 2. Determine the context to use based on the first hit in this chain
|
||||
// 1. command line argument - again, parsed from the command line, so it must be late bound
|
||||
// 2. CurrentContext from the merged kubeconfig file
|
||||
// 3. Empty is allowed at this stage
|
||||
// 3. Determine the cluster info and auth info to use. At this point, we may or may not have a context. They
|
||||
// are built based on the first hit in this chain. (run it twice, once for auth, once for cluster)
|
||||
// 1. command line argument
|
||||
// 2. If context is present, then use the context value
|
||||
// 3. Empty is allowed
|
||||
// 4. Determine the actual cluster info to use. At this point, we may or may not have a cluster info. Build
|
||||
// each piece of the cluster info based on the chain:
|
||||
// 1. command line argument
|
||||
// 2. If cluster info is present and a value for the attribute is present, use it.
|
||||
// 3. If you don't have a server location, bail.
|
||||
// 5. Auth info is build using the same rules as cluster info, EXCEPT that you can only have one authentication
|
||||
// technique per auth info. The following conditions result in an error:
|
||||
// 1. If there are two conflicting techniques specified from the command line, fail.
|
||||
// 2. If the command line does not specify one, and the auth info has conflicting techniques, fail.
|
||||
// 3. If the command line specifies one and the auth info specifies another, honor the command line technique.
|
||||
// 2. Use default values and potentially prompt for auth information
|
||||
func DefaultClientConfig(flags *pflag.FlagSet) clientcmd.ClientConfig {
|
||||
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
|
||||
flags.StringVar(&loadingRules.ExplicitPath, "kubeconfig", "", "Path to the kubeconfig file to use for CLI requests.")
|
||||
|
||||
overrides := &clientcmd.ConfigOverrides{}
|
||||
flagNames := clientcmd.RecommendedConfigOverrideFlags("")
|
||||
// short flagnames are disabled by default. These are here for compatibility with existing scripts
|
||||
flagNames.AuthOverrideFlags.AuthPathShort = "a"
|
||||
flagNames.ClusterOverrideFlags.APIServerShort = "s"
|
||||
|
||||
clientcmd.BindOverrideFlags(overrides, flags, flagNames)
|
||||
clientConfig := clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, overrides, os.Stdin)
|
||||
|
||||
return clientConfig
|
||||
}
|
||||
|
||||
func runHelp(cmd *cobra.Command, args []string) {
|
||||
cmd.Help()
|
||||
}
|
||||
|
||||
type clientSwaggerSchema struct {
|
||||
c *client.Client
|
||||
t runtime.ObjectTyper
|
||||
}
|
||||
|
||||
func (c *clientSwaggerSchema) ValidateBytes(data []byte) error {
|
||||
version, _, err := c.t.DataVersionAndKind(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
schemaData, err := c.c.RESTClient.Get().
|
||||
AbsPath("/swaggerapi/api", version).
|
||||
Do().
|
||||
Raw()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
schema, err := validation.NewSwaggerSchemaFromBytes(schemaData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return schema.ValidateBytes(data)
|
||||
}
|
||||
|
||||
// clientCache caches previously loaded clients for reuse, and ensures MatchServerVersion
|
||||
// is invoked only once
|
||||
type clientCache struct {
|
||||
loader clientcmd.ClientConfig
|
||||
clients map[string]*client.Client
|
||||
defaultConfig *client.Config
|
||||
matchVersion bool
|
||||
}
|
||||
|
||||
// ClientConfigForVersion returns the correct config for a server
|
||||
func (c *clientCache) ClientConfigForVersion(version string) (*client.Config, error) {
|
||||
if c.defaultConfig == nil {
|
||||
config, err := c.loader.ClientConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.defaultConfig = config
|
||||
if c.matchVersion {
|
||||
if err := client.MatchesServerVersion(config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: have a better config copy method
|
||||
config := *c.defaultConfig
|
||||
if len(version) != 0 {
|
||||
config.Version = version
|
||||
}
|
||||
client.SetKubernetesDefaults(&config)
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// ClientForVersion initializes or reuses a client for the specified version, or returns an
|
||||
// error if that is not possible
|
||||
func (c *clientCache) ClientForVersion(version string) (*client.Client, error) {
|
||||
config, err := c.ClientConfigForVersion(version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if client, ok := c.clients[config.Version]; ok {
|
||||
return client, nil
|
||||
}
|
||||
|
||||
client, err := client.New(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.clients[config.Version] = client
|
||||
return client, nil
|
||||
}
|
||||
|
||||
func printDeprecationWarning(command, alias string) {
|
||||
glog.Warningf("%s is DEPRECATED and will be removed in a future version. Use %s instead.", alias, command)
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ import (
|
|||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
)
|
||||
|
@ -109,14 +110,14 @@ type testFactory struct {
|
|||
Err error
|
||||
}
|
||||
|
||||
func NewTestFactory() (*Factory, *testFactory, runtime.Codec) {
|
||||
func NewTestFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) {
|
||||
scheme, mapper, codec := newExternalScheme()
|
||||
t := &testFactory{
|
||||
Validator: validation.NullSchema{},
|
||||
Mapper: mapper,
|
||||
Typer: scheme,
|
||||
}
|
||||
return &Factory{
|
||||
return &cmdutil.Factory{
|
||||
Object: func() (meta.RESTMapper, runtime.ObjectTyper) {
|
||||
return t.Mapper, t.Typer
|
||||
},
|
||||
|
@ -141,11 +142,11 @@ func NewTestFactory() (*Factory, *testFactory, runtime.Codec) {
|
|||
}, t, codec
|
||||
}
|
||||
|
||||
func NewAPIFactory() (*Factory, *testFactory, runtime.Codec) {
|
||||
func NewAPIFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) {
|
||||
t := &testFactory{
|
||||
Validator: validation.NullSchema{},
|
||||
}
|
||||
return &Factory{
|
||||
return &cmdutil.Factory{
|
||||
Object: func() (meta.RESTMapper, runtime.ObjectTyper) {
|
||||
return latest.RESTMapper, api.Scheme
|
||||
},
|
||||
|
@ -180,7 +181,7 @@ func stringBody(body string) io.ReadCloser {
|
|||
|
||||
// Verify that resource.RESTClients constructed from a factory respect mapping.APIVersion
|
||||
func TestClientVersions(t *testing.T) {
|
||||
f := NewFactory(nil)
|
||||
f := cmdutil.NewFactory(nil)
|
||||
|
||||
versions := []string{
|
||||
"v1beta1",
|
||||
|
@ -209,7 +210,7 @@ func ExamplePrintReplicationController() {
|
|||
Codec: codec,
|
||||
Client: nil,
|
||||
}
|
||||
cmd := f.NewCmdRunContainer(os.Stdout)
|
||||
cmd := NewCmdRunContainer(f, os.Stdout)
|
||||
ctrl := &api.ReplicationController{
|
||||
ObjectMeta: api.ObjectMeta{
|
||||
Name: "foo",
|
||||
|
|
|
@ -27,6 +27,7 @@ import (
|
|||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
|
||||
clientcmdapi "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd/api"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
)
|
||||
|
||||
type pathOptions struct {
|
||||
|
@ -36,7 +37,7 @@ type pathOptions struct {
|
|||
specifiedFile string
|
||||
}
|
||||
|
||||
func NewCmdConfig(out io.Writer) *cobra.Command {
|
||||
func NewCmdConfig(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
pathOptions := &pathOptions{}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
|
||||
clientcmdapi "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd/api"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
)
|
||||
|
||||
|
@ -618,8 +619,9 @@ func testConfigCommand(args []string, startingConfig clientcmdapi.Config) (strin
|
|||
argsToUse = append(argsToUse, args...)
|
||||
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
f := cmdutil.NewFactory(nil)
|
||||
|
||||
cmd := NewCmdConfig(buf)
|
||||
cmd := NewCmdConfig(f, buf)
|
||||
cmd.SetArgs(argsToUse)
|
||||
cmd.Execute()
|
||||
|
||||
|
|
|
@ -38,7 +38,7 @@ $ kubectl create -f pod.json
|
|||
$ cat pod.json | kubectl create -f -`
|
||||
)
|
||||
|
||||
func (f *Factory) NewCmdCreate(out io.Writer) *cobra.Command {
|
||||
func NewCmdCreate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
var filenames util.StringList
|
||||
cmd := &cobra.Command{
|
||||
Use: "create -f FILENAME",
|
||||
|
@ -61,7 +61,7 @@ func ValidateArgs(cmd *cobra.Command, args []string) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func RunCreate(f *Factory, out io.Writer, filenames util.StringList) error {
|
||||
func RunCreate(f *cmdutil.Factory, out io.Writer, filenames util.StringList) error {
|
||||
schema, err := f.Validator()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -28,7 +28,7 @@ func TestExtraArgsFail(t *testing.T) {
|
|||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
f, _, _ := NewAPIFactory()
|
||||
c := f.NewCmdCreate(buf)
|
||||
c := NewCmdCreate(f, buf)
|
||||
if ValidateArgs(c, []string{"rc"}) == nil {
|
||||
t.Errorf("unexpected non-error")
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ func TestCreateObject(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdCreate(buf)
|
||||
cmd := NewCmdCreate(f, buf)
|
||||
cmd.Flags().Set("filename", "../../../examples/guestbook/redis-master-controller.json")
|
||||
cmd.Run(cmd, []string{})
|
||||
|
||||
|
@ -87,7 +87,7 @@ func TestCreateMultipleObject(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdCreate(buf)
|
||||
cmd := NewCmdCreate(f, buf)
|
||||
cmd.Flags().Set("filename", "../../../examples/guestbook/redis-master-controller.json")
|
||||
cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.json")
|
||||
cmd.Run(cmd, []string{})
|
||||
|
@ -121,7 +121,7 @@ func TestCreateDirectory(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdCreate(buf)
|
||||
cmd := NewCmdCreate(f, buf)
|
||||
cmd.Flags().Set("filename", "../../../examples/guestbook")
|
||||
cmd.Run(cmd, []string{})
|
||||
|
||||
|
|
|
@ -55,7 +55,7 @@ $ kubectl delete pod 1234-56-7890-234234-456456
|
|||
$ kubectl delete pods --all`
|
||||
)
|
||||
|
||||
func (f *Factory) NewCmdDelete(out io.Writer) *cobra.Command {
|
||||
func NewCmdDelete(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
var filenames util.StringList
|
||||
cmd := &cobra.Command{
|
||||
Use: "delete ([-f FILENAME] | (RESOURCE [(ID | -l label | --all)]",
|
||||
|
@ -73,7 +73,7 @@ func (f *Factory) NewCmdDelete(out io.Writer) *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func RunDelete(f *Factory, out io.Writer, cmd *cobra.Command, args []string, filenames util.StringList) error {
|
||||
func RunDelete(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, filenames util.StringList) error {
|
||||
cmdNamespace, err := f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -47,7 +47,7 @@ func TestDeleteObject(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdDelete(buf)
|
||||
cmd := NewCmdDelete(f, buf)
|
||||
cmd.Flags().Set("filename", "../../../examples/guestbook/redis-master-controller.json")
|
||||
cmd.Run(cmd, []string{})
|
||||
|
||||
|
@ -75,7 +75,7 @@ func TestDeleteObjectIgnoreNotFound(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdDelete(buf)
|
||||
cmd := NewCmdDelete(f, buf)
|
||||
cmd.Flags().Set("filename", "../../../examples/guestbook/redis-master-controller.json")
|
||||
cmd.Run(cmd, []string{})
|
||||
|
||||
|
@ -106,7 +106,7 @@ func TestDeleteMultipleObject(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdDelete(buf)
|
||||
cmd := NewCmdDelete(f, buf)
|
||||
cmd.Flags().Set("filename", "../../../examples/guestbook/redis-master-controller.json")
|
||||
cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.json")
|
||||
cmd.Run(cmd, []string{})
|
||||
|
@ -138,7 +138,7 @@ func TestDeleteMultipleObjectIgnoreMissing(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdDelete(buf)
|
||||
cmd := NewCmdDelete(f, buf)
|
||||
cmd.Flags().Set("filename", "../../../examples/guestbook/redis-master-controller.json")
|
||||
cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.json")
|
||||
cmd.Run(cmd, []string{})
|
||||
|
@ -170,7 +170,7 @@ func TestDeleteDirectory(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdDelete(buf)
|
||||
cmd := NewCmdDelete(f, buf)
|
||||
cmd.Flags().Set("filename", "../../../examples/guestbook")
|
||||
cmd.Run(cmd, []string{})
|
||||
|
||||
|
@ -211,7 +211,7 @@ func TestDeleteMultipleSelector(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdDelete(buf)
|
||||
cmd := NewCmdDelete(f, buf)
|
||||
cmd.Flags().Set("selector", "a=b")
|
||||
cmd.Run(cmd, []string{"pods,services"})
|
||||
|
||||
|
|
|
@ -20,11 +20,11 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
func (f *Factory) NewCmdDescribe(out io.Writer) *cobra.Command {
|
||||
func NewCmdDescribe(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "describe RESOURCE ID",
|
||||
Short: "Show details of a specific resource",
|
||||
|
@ -34,13 +34,13 @@ This command joins many API calls together to form a detailed description of a
|
|||
given resource.`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunDescribe(f, out, cmd, args)
|
||||
util.CheckErr(err)
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func RunDescribe(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
func RunDescribe(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
cmdNamespace, err := f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -48,7 +48,7 @@ func RunDescribe(f *Factory, out io.Writer, cmd *cobra.Command, args []string) e
|
|||
|
||||
mapper, _ := f.Object()
|
||||
// TODO: use resource.Builder instead
|
||||
mapping, namespace, name, err := util.ResourceFromArgs(cmd, args, mapper, cmdNamespace)
|
||||
mapping, namespace, name, err := cmdutil.ResourceFromArgs(cmd, args, mapper, cmdNamespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ func TestDescribeUnknownSchemaObject(t *testing.T) {
|
|||
tf.Namespace = "non-default"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdDescribe(buf)
|
||||
cmd := NewCmdDescribe(f, buf)
|
||||
cmd.Run(cmd, []string{"type", "foo"})
|
||||
|
||||
if d.Name != "foo" || d.Namespace != "non-default" {
|
||||
|
|
|
@ -24,7 +24,7 @@ import (
|
|||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/remotecommand"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/docker/docker/pkg/term"
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -38,7 +38,7 @@ $ kubectl exec -p 123456-7890 -c ruby-container date
|
|||
$ kubectl exec -p 123456-7890 -c ruby-container -i -t -- bash -il`
|
||||
)
|
||||
|
||||
func (f *Factory) NewCmdExec(cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.Command {
|
||||
func NewCmdExec(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "exec -p POD -c CONTAINER -- COMMAND [args...]",
|
||||
Short: "Execute a command in a container.",
|
||||
|
@ -46,7 +46,7 @@ func (f *Factory) NewCmdExec(cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.C
|
|||
Example: exec_example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunExec(f, cmdIn, cmdOut, cmdErr, cmd, args)
|
||||
util.CheckErr(err)
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
cmd.Flags().StringP("pod", "p", "", "Pod name")
|
||||
|
@ -57,14 +57,14 @@ func (f *Factory) NewCmdExec(cmdIn io.Reader, cmdOut, cmdErr io.Writer) *cobra.C
|
|||
return cmd
|
||||
}
|
||||
|
||||
func RunExec(f *Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cobra.Command, args []string) error {
|
||||
podName := util.GetFlagString(cmd, "pod")
|
||||
func RunExec(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cobra.Command, args []string) error {
|
||||
podName := cmdutil.GetFlagString(cmd, "pod")
|
||||
if len(podName) == 0 {
|
||||
return util.UsageError(cmd, "POD is required for exec")
|
||||
return cmdutil.UsageError(cmd, "POD is required for exec")
|
||||
}
|
||||
|
||||
if len(args) < 1 {
|
||||
return util.UsageError(cmd, "COMMAND is required for exec")
|
||||
return cmdutil.UsageError(cmd, "COMMAND is required for exec")
|
||||
}
|
||||
|
||||
namespace, err := f.DefaultNamespace()
|
||||
|
@ -86,14 +86,14 @@ func RunExec(f *Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cobra.C
|
|||
glog.Fatalf("Unable to execute command because pod is not running. Current status=%v", pod.Status.Phase)
|
||||
}
|
||||
|
||||
containerName := util.GetFlagString(cmd, "container")
|
||||
containerName := cmdutil.GetFlagString(cmd, "container")
|
||||
if len(containerName) == 0 {
|
||||
containerName = pod.Spec.Containers[0].Name
|
||||
}
|
||||
|
||||
var stdin io.Reader
|
||||
tty := util.GetFlagBool(cmd, "tty")
|
||||
if util.GetFlagBool(cmd, "stdin") {
|
||||
tty := cmdutil.GetFlagBool(cmd, "tty")
|
||||
if cmdutil.GetFlagBool(cmd, "stdin") {
|
||||
stdin = cmdIn
|
||||
if tty {
|
||||
if file, ok := cmdIn.(*os.File); ok {
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
@ -42,7 +42,7 @@ $ kubectl expose service nginx --port=443 --target-port=8443 --service-name=ngin
|
|||
$ kubectl expose streamer --port=4100 --protocol=udp --service-name=video-stream`
|
||||
)
|
||||
|
||||
func (f *Factory) NewCmdExposeService(out io.Writer) *cobra.Command {
|
||||
func NewCmdExposeService(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "expose RESOURCE NAME --port=port [--protocol=TCP|UDP] [--target-port=number-or-name] [--service-name=name] [--public-ip=ip] [--create-external-load-balancer=bool]",
|
||||
Short: "Take a replicated application and expose it as Kubernetes Service",
|
||||
|
@ -50,10 +50,10 @@ func (f *Factory) NewCmdExposeService(out io.Writer) *cobra.Command {
|
|||
Example: expose_example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunExpose(f, out, cmd, args)
|
||||
util.CheckErr(err)
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
util.AddPrinterFlags(cmd)
|
||||
cmdutil.AddPrinterFlags(cmd)
|
||||
cmd.Flags().String("generator", "service/v1", "The name of the API generator to use. Default is 'service/v1'.")
|
||||
cmd.Flags().String("protocol", "TCP", "The network protocol for the service to be created. Default is 'tcp'.")
|
||||
cmd.Flags().Int("port", -1, "The port that the service should serve on. Required.")
|
||||
|
@ -69,13 +69,13 @@ func (f *Factory) NewCmdExposeService(out io.Writer) *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func RunExpose(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
func RunExpose(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
var name, resource string
|
||||
switch l := len(args); {
|
||||
case l == 2:
|
||||
resource, name = args[0], args[1]
|
||||
default:
|
||||
return util.UsageError(cmd, "the type and name of a resource to expose are required arguments")
|
||||
return cmdutil.UsageError(cmd, "the type and name of a resource to expose are required arguments")
|
||||
}
|
||||
|
||||
namespace, err := f.DefaultNamespace()
|
||||
|
@ -87,20 +87,20 @@ func RunExpose(f *Factory, out io.Writer, cmd *cobra.Command, args []string) err
|
|||
return err
|
||||
}
|
||||
|
||||
generatorName := util.GetFlagString(cmd, "generator")
|
||||
generatorName := cmdutil.GetFlagString(cmd, "generator")
|
||||
|
||||
generator, found := kubectl.Generators[generatorName]
|
||||
if !found {
|
||||
return util.UsageError(cmd, fmt.Sprintf("generator %q not found.", generator))
|
||||
return cmdutil.UsageError(cmd, fmt.Sprintf("generator %q not found.", generator))
|
||||
}
|
||||
names := generator.ParamNames()
|
||||
params := kubectl.MakeParams(cmd, names)
|
||||
if len(util.GetFlagString(cmd, "service-name")) == 0 {
|
||||
if len(cmdutil.GetFlagString(cmd, "service-name")) == 0 {
|
||||
params["name"] = name
|
||||
} else {
|
||||
params["name"] = util.GetFlagString(cmd, "service-name")
|
||||
params["name"] = cmdutil.GetFlagString(cmd, "service-name")
|
||||
}
|
||||
if s, found := params["selector"]; !found || len(s) == 0 || util.GetFlagInt(cmd, "port") < 1 {
|
||||
if s, found := params["selector"]; !found || len(s) == 0 || cmdutil.GetFlagInt(cmd, "port") < 1 {
|
||||
mapper, _ := f.Object()
|
||||
v, k, err := mapper.VersionAndKindForResource(resource)
|
||||
if err != nil {
|
||||
|
@ -117,21 +117,21 @@ func RunExpose(f *Factory, out io.Writer, cmd *cobra.Command, args []string) err
|
|||
}
|
||||
params["selector"] = s
|
||||
}
|
||||
if util.GetFlagInt(cmd, "port") < 0 {
|
||||
if cmdutil.GetFlagInt(cmd, "port") < 0 {
|
||||
ports, err := f.PortsForResource(mapping, namespace, name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(ports) == 0 {
|
||||
return util.UsageError(cmd, "couldn't find a suitable port via --port flag or introspection")
|
||||
return cmdutil.UsageError(cmd, "couldn't find a suitable port via --port flag or introspection")
|
||||
}
|
||||
if len(ports) > 1 {
|
||||
return util.UsageError(cmd, "more than one port to choose from, please explicitly specify a port using the --port flag.")
|
||||
return cmdutil.UsageError(cmd, "more than one port to choose from, please explicitly specify a port using the --port flag.")
|
||||
}
|
||||
params["port"] = ports[0]
|
||||
}
|
||||
}
|
||||
if util.GetFlagBool(cmd, "create-external-load-balancer") {
|
||||
if cmdutil.GetFlagBool(cmd, "create-external-load-balancer") {
|
||||
params["create-external-load-balancer"] = "true"
|
||||
}
|
||||
|
||||
|
@ -145,16 +145,16 @@ func RunExpose(f *Factory, out io.Writer, cmd *cobra.Command, args []string) err
|
|||
return err
|
||||
}
|
||||
|
||||
inline := util.GetFlagString(cmd, "overrides")
|
||||
inline := cmdutil.GetFlagString(cmd, "overrides")
|
||||
if len(inline) > 0 {
|
||||
service, err = util.Merge(service, inline, "Service")
|
||||
service, err = cmdutil.Merge(service, inline, "Service")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: extract this flag to a central location, when such a location exists.
|
||||
if !util.GetFlagBool(cmd, "dry-run") {
|
||||
if !cmdutil.GetFlagBool(cmd, "dry-run") {
|
||||
service, err = client.Services(namespace).Create(service.(*api.Service))
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -23,7 +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"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
||||
|
||||
|
@ -59,7 +59,7 @@ $ kubectl get rc/web service/frontend pods/web-pod-13je7`
|
|||
|
||||
// NewCmdGet creates a command object for the generic "get" action, which
|
||||
// retrieves one or more resources from a server.
|
||||
func (f *Factory) NewCmdGet(out io.Writer) *cobra.Command {
|
||||
func NewCmdGet(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "get [(-o|--output=)json|yaml|template|...] (RESOURCE [NAME] | RESOURCE/NAME ...)",
|
||||
Short: "Display one or many resources",
|
||||
|
@ -67,10 +67,10 @@ func (f *Factory) NewCmdGet(out io.Writer) *cobra.Command {
|
|||
Example: get_example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunGet(f, out, cmd, args)
|
||||
util.CheckErr(err)
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
util.AddPrinterFlags(cmd)
|
||||
cmdutil.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.")
|
||||
|
@ -79,8 +79,8 @@ func (f *Factory) NewCmdGet(out io.Writer) *cobra.Command {
|
|||
|
||||
// RunGet implements the generic Get command
|
||||
// TODO: convert all direct flag accessors to a struct and pass that instead of cmd
|
||||
func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
selector := util.GetFlagString(cmd, "selector")
|
||||
func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
selector := cmdutil.GetFlagString(cmd, "selector")
|
||||
mapper, typer := f.Object()
|
||||
|
||||
cmdNamespace, err := f.DefaultNamespace()
|
||||
|
@ -89,7 +89,7 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error
|
|||
}
|
||||
|
||||
// handle watch separately since we cannot watch multiple resource types
|
||||
isWatch, isWatchOnly := util.GetFlagBool(cmd, "watch"), util.GetFlagBool(cmd, "watch-only")
|
||||
isWatch, isWatchOnly := cmdutil.GetFlagBool(cmd, "watch"), cmdutil.GetFlagBool(cmd, "watch-only")
|
||||
if isWatch || isWatchOnly {
|
||||
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
|
@ -146,7 +146,7 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error
|
|||
ResourceTypeOrNameArgs(true, args...).
|
||||
ContinueOnError().
|
||||
Latest()
|
||||
printer, generic, err := util.PrinterForCommand(cmd)
|
||||
printer, generic, err := cmdutil.PrinterForCommand(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -159,7 +159,7 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error
|
|||
defaultVersion := clientConfig.Version
|
||||
|
||||
// the outermost object will be converted to the output-version
|
||||
version := util.OutputVersion(cmd, defaultVersion)
|
||||
version := cmdutil.OutputVersion(cmd, defaultVersion)
|
||||
|
||||
r := b.Flatten().Do()
|
||||
obj, err := r.Object()
|
||||
|
|
|
@ -99,7 +99,7 @@ func TestGetUnknownSchemaObject(t *testing.T) {
|
|||
tf.ClientConfig = &client.Config{Version: latest.Version}
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdGet(buf)
|
||||
cmd := NewCmdGet(f, buf)
|
||||
cmd.SetOutput(buf)
|
||||
cmd.Run(cmd, []string{"type", "foo"})
|
||||
|
||||
|
@ -128,7 +128,7 @@ func TestGetSchemaObject(t *testing.T) {
|
|||
tf.ClientConfig = &client.Config{Version: "v1beta3"}
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdGet(buf)
|
||||
cmd := NewCmdGet(f, buf)
|
||||
cmd.Run(cmd, []string{"replicationcontrollers", "foo"})
|
||||
|
||||
if !strings.Contains(buf.String(), "\"foo\"") {
|
||||
|
@ -148,7 +148,7 @@ func TestGetObjects(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdGet(buf)
|
||||
cmd := NewCmdGet(f, buf)
|
||||
cmd.SetOutput(buf)
|
||||
cmd.Run(cmd, []string{"pods", "foo"})
|
||||
|
||||
|
@ -174,7 +174,7 @@ func TestGetListObjects(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdGet(buf)
|
||||
cmd := NewCmdGet(f, buf)
|
||||
cmd.SetOutput(buf)
|
||||
cmd.Run(cmd, []string{"pods"})
|
||||
|
||||
|
@ -210,7 +210,7 @@ func TestGetMultipleTypeObjects(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdGet(buf)
|
||||
cmd := NewCmdGet(f, buf)
|
||||
cmd.SetOutput(buf)
|
||||
cmd.Run(cmd, []string{"pods,services"})
|
||||
|
||||
|
@ -247,7 +247,7 @@ func TestGetMultipleTypeObjectsAsList(t *testing.T) {
|
|||
tf.ClientConfig = &client.Config{Version: "v1beta1"}
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdGet(buf)
|
||||
cmd := NewCmdGet(f, buf)
|
||||
cmd.SetOutput(buf)
|
||||
|
||||
cmd.Flags().Set("output", "json")
|
||||
|
@ -298,7 +298,7 @@ func TestGetMultipleTypeObjectsWithSelector(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdGet(buf)
|
||||
cmd := NewCmdGet(f, buf)
|
||||
cmd.SetOutput(buf)
|
||||
|
||||
cmd.Flags().Set("selector", "a=b")
|
||||
|
@ -344,7 +344,7 @@ func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdGet(buf)
|
||||
cmd := NewCmdGet(f, buf)
|
||||
cmd.SetOutput(buf)
|
||||
|
||||
cmd.Run(cmd, []string{"services/bar", "node/foo"})
|
||||
|
@ -430,7 +430,7 @@ func TestWatchSelector(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdGet(buf)
|
||||
cmd := NewCmdGet(f, buf)
|
||||
cmd.SetOutput(buf)
|
||||
|
||||
cmd.Flags().Set("watch", "true")
|
||||
|
@ -469,7 +469,7 @@ func TestWatchResource(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdGet(buf)
|
||||
cmd := NewCmdGet(f, buf)
|
||||
cmd.SetOutput(buf)
|
||||
|
||||
cmd.Flags().Set("watch", "true")
|
||||
|
@ -507,7 +507,7 @@ func TestWatchOnlyResource(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdGet(buf)
|
||||
cmd := NewCmdGet(f, buf)
|
||||
cmd.SetOutput(buf)
|
||||
|
||||
cmd.Flags().Set("watch-only", "true")
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/spf13/cobra"
|
||||
|
@ -50,7 +50,7 @@ $ kubectl label pods foo status=unhealthy --resource-version=1
|
|||
$ kubectl label pods foo bar-`
|
||||
)
|
||||
|
||||
func (f *Factory) NewCmdLabel(out io.Writer) *cobra.Command {
|
||||
func NewCmdLabel(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "label [--overwrite] RESOURCE NAME KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]",
|
||||
Short: "Update the labels on a resource",
|
||||
|
@ -58,10 +58,10 @@ func (f *Factory) NewCmdLabel(out io.Writer) *cobra.Command {
|
|||
Example: label_example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunLabel(f, out, cmd, args)
|
||||
util.CheckErr(err)
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
util.AddPrinterFlags(cmd)
|
||||
cmdutil.AddPrinterFlags(cmd)
|
||||
cmd.Flags().Bool("overwrite", false, "If true, allow labels to be overwritten, otherwise reject label updates that overwrite existing labels.")
|
||||
cmd.Flags().StringP("selector", "l", "", "Selector (label query) to filter on")
|
||||
cmd.Flags().Bool("all", false, "select all resources in the namespace of the specified resource types")
|
||||
|
@ -149,7 +149,7 @@ func labelFunc(obj runtime.Object, overwrite bool, resourceVersion string, label
|
|||
return obj, nil
|
||||
}
|
||||
|
||||
func RunLabel(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
func RunLabel(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
resources, labelArgs := []string{}, []string{}
|
||||
first := true
|
||||
for _, s := range args {
|
||||
|
@ -163,20 +163,20 @@ func RunLabel(f *Factory, out io.Writer, cmd *cobra.Command, args []string) erro
|
|||
case first && !isLabel:
|
||||
resources = append(resources, s)
|
||||
case !first && !isLabel:
|
||||
return util.UsageError(cmd, "all resources must be specified before label changes: %s", s)
|
||||
return cmdutil.UsageError(cmd, "all resources must be specified before label changes: %s", s)
|
||||
}
|
||||
}
|
||||
if len(resources) < 1 {
|
||||
return util.UsageError(cmd, "one or more resources must be specified as <resource> <name> or <resource>/<name>")
|
||||
return cmdutil.UsageError(cmd, "one or more resources must be specified as <resource> <name> or <resource>/<name>")
|
||||
}
|
||||
if len(labelArgs) < 1 {
|
||||
return util.UsageError(cmd, "at least one label update is required")
|
||||
return cmdutil.UsageError(cmd, "at least one label update is required")
|
||||
}
|
||||
|
||||
selector := util.GetFlagString(cmd, "selector")
|
||||
all := util.GetFlagBool(cmd, "all")
|
||||
overwrite := util.GetFlagBool(cmd, "overwrite")
|
||||
resourceVersion := util.GetFlagString(cmd, "resource-version")
|
||||
selector := cmdutil.GetFlagString(cmd, "selector")
|
||||
all := cmdutil.GetFlagBool(cmd, "all")
|
||||
overwrite := cmdutil.GetFlagBool(cmd, "overwrite")
|
||||
resourceVersion := cmdutil.GetFlagString(cmd, "resource-version")
|
||||
|
||||
cmdNamespace, err := f.DefaultNamespace()
|
||||
if err != nil {
|
||||
|
@ -204,7 +204,7 @@ func RunLabel(f *Factory, out io.Writer, cmd *cobra.Command, args []string) erro
|
|||
}
|
||||
// only apply resource version locking on a single resource
|
||||
if !one && len(resourceVersion) > 0 {
|
||||
return util.UsageError(cmd, "--resource-version may only be used with a single resource")
|
||||
return cmdutil.UsageError(cmd, "--resource-version may only be used with a single resource")
|
||||
}
|
||||
|
||||
// TODO: support bulk generic output a la Get
|
||||
|
|
|
@ -294,7 +294,7 @@ func TestLabelErrors(t *testing.T) {
|
|||
tf.ClientConfig = &client.Config{Version: "v1beta1"}
|
||||
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
cmd := f.NewCmdLabel(buf)
|
||||
cmd := NewCmdLabel(f, buf)
|
||||
cmd.SetOutput(buf)
|
||||
|
||||
for k, v := range testCase.flags {
|
||||
|
@ -351,7 +351,7 @@ func TestLabelMultipleObjects(t *testing.T) {
|
|||
tf.ClientConfig = &client.Config{Version: "v1beta1"}
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdLabel(buf)
|
||||
cmd := NewCmdLabel(f, buf)
|
||||
|
||||
cmd.Flags().Set("all", "true")
|
||||
if err := RunLabel(f, buf, cmd, []string{"pods", "a=b"}); err != nil {
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
"strconv"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
libutil "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
@ -57,7 +57,7 @@ func selectContainer(pod *api.Pod, in io.Reader, out io.Writer) string {
|
|||
}
|
||||
}
|
||||
|
||||
func (f *Factory) NewCmdLog(out io.Writer) *cobra.Command {
|
||||
func NewCmdLog(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "log [-f] POD [CONTAINER]",
|
||||
Short: "Print the logs for a container in a pod.",
|
||||
|
@ -65,7 +65,7 @@ func (f *Factory) NewCmdLog(out io.Writer) *cobra.Command {
|
|||
Example: log_example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunLog(f, out, cmd, args)
|
||||
util.CheckErr(err)
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
cmd.Flags().BoolP("follow", "f", false, "Specify if the logs should be streamed.")
|
||||
|
@ -73,13 +73,13 @@ func (f *Factory) NewCmdLog(out io.Writer) *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func RunLog(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
func RunLog(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
if len(args) == 0 {
|
||||
return util.UsageError(cmd, "POD is required for log")
|
||||
return cmdutil.UsageError(cmd, "POD is required for log")
|
||||
}
|
||||
|
||||
if len(args) > 2 {
|
||||
return util.UsageError(cmd, "log POD [CONTAINER]")
|
||||
return cmdutil.UsageError(cmd, "log POD [CONTAINER]")
|
||||
}
|
||||
|
||||
namespace, err := f.DefaultNamespace()
|
||||
|
@ -109,7 +109,7 @@ func RunLog(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error
|
|||
}
|
||||
|
||||
follow := false
|
||||
if util.GetFlagBool(cmd, "follow") {
|
||||
if cmdutil.GetFlagBool(cmd, "follow") {
|
||||
follow = true
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/portforward"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
@ -42,7 +42,7 @@ $ kubectl port-forward -p mypod :5000
|
|||
$ kubectl port-forward -p mypod 0:5000`
|
||||
)
|
||||
|
||||
func (f *Factory) NewCmdPortForward() *cobra.Command {
|
||||
func NewCmdPortForward(f *cmdutil.Factory) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "port-forward -p POD [LOCAL_PORT:]REMOTE_PORT [...[LOCAL_PORT_N:]REMOTE_PORT_N]",
|
||||
Short: "Forward one or more local ports to a pod.",
|
||||
|
@ -50,7 +50,7 @@ func (f *Factory) NewCmdPortForward() *cobra.Command {
|
|||
Example: portforward_example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunPortForward(f, cmd, args)
|
||||
util.CheckErr(err)
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
cmd.Flags().StringP("pod", "p", "", "Pod name")
|
||||
|
@ -58,14 +58,14 @@ func (f *Factory) NewCmdPortForward() *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func RunPortForward(f *Factory, cmd *cobra.Command, args []string) error {
|
||||
podName := util.GetFlagString(cmd, "pod")
|
||||
func RunPortForward(f *cmdutil.Factory, cmd *cobra.Command, args []string) error {
|
||||
podName := cmdutil.GetFlagString(cmd, "pod")
|
||||
if len(podName) == 0 {
|
||||
return util.UsageError(cmd, "POD is required for exec")
|
||||
return cmdutil.UsageError(cmd, "POD is required for exec")
|
||||
}
|
||||
|
||||
if len(args) < 1 {
|
||||
return util.UsageError(cmd, "at least 1 PORT is required for port-forward")
|
||||
return cmdutil.UsageError(cmd, "at least 1 PORT is required for port-forward")
|
||||
}
|
||||
|
||||
namespace, err := f.DefaultNamespace()
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
"strings"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
@ -36,7 +36,7 @@ $ kubectl proxy --port=8011 --www=./local/www/
|
|||
$ kubectl proxy --api-prefix=k8s-api`
|
||||
)
|
||||
|
||||
func (f *Factory) NewCmdProxy(out io.Writer) *cobra.Command {
|
||||
func NewCmdProxy(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "proxy [--port=PORT] [--www=static-dir] [--www-prefix=prefix] [--api-prefix=prefix]",
|
||||
Short: "Run a proxy to the Kubernetes API server",
|
||||
|
@ -44,7 +44,7 @@ func (f *Factory) NewCmdProxy(out io.Writer) *cobra.Command {
|
|||
Example: proxy_example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunProxy(f, out, cmd)
|
||||
util.CheckErr(err)
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
cmd.Flags().StringP("www", "w", "", "Also serve static files from the given directory under the specified prefix.")
|
||||
|
@ -54,8 +54,8 @@ func (f *Factory) NewCmdProxy(out io.Writer) *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func RunProxy(f *Factory, out io.Writer, cmd *cobra.Command) error {
|
||||
port := util.GetFlagInt(cmd, "port")
|
||||
func RunProxy(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command) error {
|
||||
port := cmdutil.GetFlagInt(cmd, "port")
|
||||
fmt.Fprintf(out, "Starting to serve on localhost:%d", port)
|
||||
|
||||
clientConfig, err := f.ClientConfig()
|
||||
|
@ -63,16 +63,16 @@ func RunProxy(f *Factory, out io.Writer, cmd *cobra.Command) error {
|
|||
return err
|
||||
}
|
||||
|
||||
staticPrefix := util.GetFlagString(cmd, "www-prefix")
|
||||
staticPrefix := cmdutil.GetFlagString(cmd, "www-prefix")
|
||||
if !strings.HasSuffix(staticPrefix, "/") {
|
||||
staticPrefix += "/"
|
||||
}
|
||||
|
||||
apiProxyPrefix := util.GetFlagString(cmd, "api-prefix")
|
||||
apiProxyPrefix := cmdutil.GetFlagString(cmd, "api-prefix")
|
||||
if !strings.HasSuffix(apiProxyPrefix, "/") {
|
||||
apiProxyPrefix += "/"
|
||||
}
|
||||
server, err := kubectl.NewProxyServer(util.GetFlagString(cmd, "www"), apiProxyPrefix, staticPrefix, clientConfig)
|
||||
server, err := kubectl.NewProxyServer(cmdutil.GetFlagString(cmd, "www"), apiProxyPrefix, staticPrefix, clientConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ import (
|
|||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/controller"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util/wait"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
@ -45,7 +45,7 @@ $ kubectl resize --current-replicas=2 --replicas=3 replicationcontrollers foo`
|
|||
retryTimeout = 10 * time.Second
|
||||
)
|
||||
|
||||
func (f *Factory) NewCmdResize(out io.Writer) *cobra.Command {
|
||||
func NewCmdResize(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "resize [--resource-version=version] [--current-replicas=count] --replicas=COUNT RESOURCE ID",
|
||||
Short: "Set a new size for a Replication Controller.",
|
||||
|
@ -53,7 +53,7 @@ func (f *Factory) NewCmdResize(out io.Writer) *cobra.Command {
|
|||
Example: resize_example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunResize(f, out, cmd, args)
|
||||
util.CheckErr(err)
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
cmd.Flags().String("resource-version", "", "Precondition for resource version. Requires that the current resource version match this value in order to resize.")
|
||||
|
@ -62,10 +62,10 @@ func (f *Factory) NewCmdResize(out io.Writer) *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func RunResize(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
count := util.GetFlagInt(cmd, "replicas")
|
||||
func RunResize(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
count := cmdutil.GetFlagInt(cmd, "replicas")
|
||||
if len(args) != 2 || count < 0 {
|
||||
return util.UsageError(cmd, "--replicas=COUNT RESOURCE ID")
|
||||
return cmdutil.UsageError(cmd, "--replicas=COUNT RESOURCE ID")
|
||||
}
|
||||
|
||||
cmdNamespace, err := f.DefaultNamespace()
|
||||
|
@ -75,7 +75,7 @@ func RunResize(f *Factory, out io.Writer, cmd *cobra.Command, args []string) err
|
|||
|
||||
mapper, _ := f.Object()
|
||||
// TODO: use resource.Builder instead
|
||||
mapping, namespace, name, err := util.ResourceFromArgs(cmd, args, mapper, cmdNamespace)
|
||||
mapping, namespace, name, err := cmdutil.ResourceFromArgs(cmd, args, mapper, cmdNamespace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -85,8 +85,8 @@ func RunResize(f *Factory, out io.Writer, cmd *cobra.Command, args []string) err
|
|||
return err
|
||||
}
|
||||
|
||||
resourceVersion := util.GetFlagString(cmd, "resource-version")
|
||||
currentSize := util.GetFlagInt(cmd, "current-replicas")
|
||||
resourceVersion := cmdutil.GetFlagString(cmd, "resource-version")
|
||||
currentSize := cmdutil.GetFlagInt(cmd, "current-replicas")
|
||||
precondition := &kubectl.ResizePrecondition{currentSize, resourceVersion}
|
||||
cond := kubectl.ResizeCondition(resizer, precondition, namespace, name, uint(count))
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ import (
|
|||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
@ -44,7 +44,7 @@ $ kubectl rolling-update frontend-v1 -f frontend-v2.json
|
|||
$ cat frontend-v2.json | kubectl rolling-update frontend-v1 -f -`
|
||||
)
|
||||
|
||||
func (f *Factory) NewCmdRollingUpdate(out io.Writer) *cobra.Command {
|
||||
func NewCmdRollingUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "rolling-update OLD_CONTROLLER_NAME -f NEW_CONTROLLER_SPEC",
|
||||
// rollingupdate is deprecated.
|
||||
|
@ -54,7 +54,7 @@ func (f *Factory) NewCmdRollingUpdate(out io.Writer) *cobra.Command {
|
|||
Example: rollingUpdate_example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunRollingUpdate(f, out, cmd, args)
|
||||
util.CheckErr(err)
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
cmd.Flags().String("update-period", updatePeriod, `Time to wait between updating pods. Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".`)
|
||||
|
@ -64,20 +64,20 @@ func (f *Factory) NewCmdRollingUpdate(out io.Writer) *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func RunRollingUpdate(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
func RunRollingUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
if os.Args[1] == "rollingupdate" {
|
||||
printDeprecationWarning("rolling-update", "rollingupdate")
|
||||
}
|
||||
|
||||
filename := util.GetFlagString(cmd, "filename")
|
||||
filename := cmdutil.GetFlagString(cmd, "filename")
|
||||
if len(filename) == 0 {
|
||||
return util.UsageError(cmd, "Must specify filename for new controller")
|
||||
return cmdutil.UsageError(cmd, "Must specify filename for new controller")
|
||||
}
|
||||
period := util.GetFlagDuration(cmd, "update-period")
|
||||
interval := util.GetFlagDuration(cmd, "poll-interval")
|
||||
timeout := util.GetFlagDuration(cmd, "timeout")
|
||||
period := cmdutil.GetFlagDuration(cmd, "update-period")
|
||||
interval := cmdutil.GetFlagDuration(cmd, "poll-interval")
|
||||
timeout := cmdutil.GetFlagDuration(cmd, "timeout")
|
||||
if len(args) != 1 {
|
||||
return util.UsageError(cmd, "Must specify the controller to update")
|
||||
return cmdutil.UsageError(cmd, "Must specify the controller to update")
|
||||
}
|
||||
oldName := args[0]
|
||||
|
||||
|
@ -98,11 +98,11 @@ func RunRollingUpdate(f *Factory, out io.Writer, cmd *cobra.Command, args []stri
|
|||
}
|
||||
newRc, ok := obj.(*api.ReplicationController)
|
||||
if !ok {
|
||||
return util.UsageError(cmd, "%s does not specify a valid ReplicationController", filename)
|
||||
return cmdutil.UsageError(cmd, "%s does not specify a valid ReplicationController", filename)
|
||||
}
|
||||
newName := newRc.Name
|
||||
if oldName == newName {
|
||||
return util.UsageError(cmd, "%s cannot have the same name as the existing ReplicationController %s",
|
||||
return cmdutil.UsageError(cmd, "%s cannot have the same name as the existing ReplicationController %s",
|
||||
filename, oldName)
|
||||
}
|
||||
|
||||
|
@ -127,7 +127,7 @@ func RunRollingUpdate(f *Factory, out io.Writer, cmd *cobra.Command, args []stri
|
|||
}
|
||||
}
|
||||
if !hasLabel {
|
||||
return util.UsageError(cmd, "%s must specify a matching key with non-equal value in Selector for %s",
|
||||
return cmdutil.UsageError(cmd, "%s must specify a matching key with non-equal value in Selector for %s",
|
||||
filename, oldName)
|
||||
}
|
||||
// TODO: handle resizes during rolling update
|
||||
|
|
|
@ -22,7 +22,7 @@ import (
|
|||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
@ -42,7 +42,7 @@ $ kubectl run-container nginx --image=dockerfile/nginx --dry-run
|
|||
$ kubectl run-container nginx --image=dockerfile/nginx --overrides='{ "apiVersion": "v1beta1", "desiredState": { ... } }'`
|
||||
)
|
||||
|
||||
func (f *Factory) NewCmdRunContainer(out io.Writer) *cobra.Command {
|
||||
func NewCmdRunContainer(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "run-container NAME --image=image [--port=port] [--replicas=replicas] [--dry-run=bool] [--overrides=inline-json]",
|
||||
Short: "Run a particular image on the cluster.",
|
||||
|
@ -50,10 +50,10 @@ func (f *Factory) NewCmdRunContainer(out io.Writer) *cobra.Command {
|
|||
Example: run_example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunRunContainer(f, out, cmd, args)
|
||||
util.CheckErr(err)
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
util.AddPrinterFlags(cmd)
|
||||
cmdutil.AddPrinterFlags(cmd)
|
||||
cmd.Flags().String("generator", "run-container/v1", "The name of the API generator to use. Default is 'run-container-controller/v1'.")
|
||||
cmd.Flags().String("image", "", "The image for the container to run.")
|
||||
cmd.Flags().IntP("replicas", "r", 1, "Number of replicas to create for this container. Default is 1.")
|
||||
|
@ -64,9 +64,9 @@ func (f *Factory) NewCmdRunContainer(out io.Writer) *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func RunRunContainer(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
func RunRunContainer(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
if len(args) != 1 {
|
||||
return util.UsageError(cmd, "NAME is required for run-container")
|
||||
return cmdutil.UsageError(cmd, "NAME is required for run-container")
|
||||
}
|
||||
|
||||
namespace, err := f.DefaultNamespace()
|
||||
|
@ -79,10 +79,10 @@ func RunRunContainer(f *Factory, out io.Writer, cmd *cobra.Command, args []strin
|
|||
return err
|
||||
}
|
||||
|
||||
generatorName := util.GetFlagString(cmd, "generator")
|
||||
generatorName := cmdutil.GetFlagString(cmd, "generator")
|
||||
generator, found := kubectl.Generators[generatorName]
|
||||
if !found {
|
||||
return util.UsageError(cmd, fmt.Sprintf("Generator: %s not found.", generator))
|
||||
return cmdutil.UsageError(cmd, fmt.Sprintf("Generator: %s not found.", generator))
|
||||
}
|
||||
names := generator.ParamNames()
|
||||
params := kubectl.MakeParams(cmd, names)
|
||||
|
@ -98,16 +98,16 @@ func RunRunContainer(f *Factory, out io.Writer, cmd *cobra.Command, args []strin
|
|||
return err
|
||||
}
|
||||
|
||||
inline := util.GetFlagString(cmd, "overrides")
|
||||
inline := cmdutil.GetFlagString(cmd, "overrides")
|
||||
if len(inline) > 0 {
|
||||
controller, err = util.Merge(controller, inline, "ReplicationController")
|
||||
controller, err = cmdutil.Merge(controller, inline, "ReplicationController")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: extract this flag to a central location, when such a location exists.
|
||||
if !util.GetFlagBool(cmd, "dry-run") {
|
||||
if !cmdutil.GetFlagBool(cmd, "dry-run") {
|
||||
controller, err = client.ReplicationControllers(namespace).Create(controller.(*api.ReplicationController))
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
|
@ -44,7 +44,7 @@ $ kubectl stop -f service.json
|
|||
$ kubectl stop -f path/to/resources`
|
||||
)
|
||||
|
||||
func (f *Factory) NewCmdStop(out io.Writer) *cobra.Command {
|
||||
func NewCmdStop(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
flags := &struct {
|
||||
Filenames util.StringList
|
||||
}{}
|
||||
|
|
|
@ -40,7 +40,7 @@ $ cat pod.json | kubectl update -f -
|
|||
$ kubectl update pods my-pod --patch='{ "apiVersion": "v1beta1", "desiredState": { "manifest": [{ "cpu": 100 }]}}'`
|
||||
)
|
||||
|
||||
func (f *Factory) NewCmdUpdate(out io.Writer) *cobra.Command {
|
||||
func NewCmdUpdate(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
var filenames util.StringList
|
||||
cmd := &cobra.Command{
|
||||
Use: "update -f FILENAME",
|
||||
|
@ -57,7 +57,7 @@ func (f *Factory) NewCmdUpdate(out io.Writer) *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func RunUpdate(f *Factory, out io.Writer, cmd *cobra.Command, args []string, filenames util.StringList) error {
|
||||
func RunUpdate(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, filenames util.StringList) error {
|
||||
schema, err := f.Validator()
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -117,7 +117,7 @@ func RunUpdate(f *Factory, out io.Writer, cmd *cobra.Command, args []string, fil
|
|||
|
||||
}
|
||||
|
||||
func updateWithPatch(cmd *cobra.Command, args []string, f *Factory, patch string) (string, error) {
|
||||
func updateWithPatch(cmd *cobra.Command, args []string, f *cmdutil.Factory, patch string) (string, error) {
|
||||
cmdNamespace, err := f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return "", err
|
||||
|
|
|
@ -47,7 +47,7 @@ func TestUpdateObject(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdUpdate(buf)
|
||||
cmd := NewCmdUpdate(f, buf)
|
||||
cmd.Flags().Set("filename", "../../../examples/guestbook/redis-master-controller.json")
|
||||
cmd.Run(cmd, []string{})
|
||||
|
||||
|
@ -83,7 +83,7 @@ func TestUpdateMultipleObject(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdUpdate(buf)
|
||||
cmd := NewCmdUpdate(f, buf)
|
||||
cmd.Flags().Set("filename", "../../../examples/guestbook/redis-master-controller.json")
|
||||
cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.json")
|
||||
cmd.Run(cmd, []string{})
|
||||
|
@ -115,7 +115,7 @@ func TestUpdateDirectory(t *testing.T) {
|
|||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
|
||||
cmd := f.NewCmdUpdate(buf)
|
||||
cmd := NewCmdUpdate(f, buf)
|
||||
cmd.Flags().Set("filename", "../../../examples/guestbook")
|
||||
cmd.Flags().Set("namespace", "test")
|
||||
cmd.Run(cmd, []string{})
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
|
||||
)
|
||||
|
||||
// clientCache caches previously loaded clients for reuse, and ensures MatchServerVersion
|
||||
// is invoked only once
|
||||
type clientCache struct {
|
||||
loader clientcmd.ClientConfig
|
||||
clients map[string]*client.Client
|
||||
defaultConfig *client.Config
|
||||
matchVersion bool
|
||||
}
|
||||
|
||||
// ClientConfigForVersion returns the correct config for a server
|
||||
func (c *clientCache) ClientConfigForVersion(version string) (*client.Config, error) {
|
||||
if c.defaultConfig == nil {
|
||||
config, err := c.loader.ClientConfig()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c.defaultConfig = config
|
||||
if c.matchVersion {
|
||||
if err := client.MatchesServerVersion(config); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO: have a better config copy method
|
||||
config := *c.defaultConfig
|
||||
if len(version) != 0 {
|
||||
config.Version = version
|
||||
}
|
||||
client.SetKubernetesDefaults(&config)
|
||||
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
// ClientForVersion initializes or reuses a client for the specified version, or returns an
|
||||
// error if that is not possible
|
||||
func (c *clientCache) ClientForVersion(version string) (*client.Client, error) {
|
||||
config, err := c.ClientConfigForVersion(version)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if client, ok := c.clients[config.Version]; ok {
|
||||
return client, nil
|
||||
}
|
||||
|
||||
client, err := client.New(config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
c.clients[config.Version] = client
|
||||
return client, nil
|
||||
}
|
|
@ -0,0 +1,391 @@
|
|||
/*
|
||||
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 util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/validation"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/resource"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||
)
|
||||
|
||||
const (
|
||||
FlagMatchBinaryVersion = "match-server-version"
|
||||
)
|
||||
|
||||
// Factory provides abstractions that allow the Kubectl command to be extended across multiple types
|
||||
// of resources and different API sets.
|
||||
// TODO: make the functions interfaces
|
||||
// TODO: pass the various interfaces on the factory directly into the command constructors (so the
|
||||
// commands are decoupled from the factory).
|
||||
type Factory struct {
|
||||
clients *clientCache
|
||||
flags *pflag.FlagSet
|
||||
|
||||
// Returns interfaces for dealing with arbitrary runtime.Objects.
|
||||
Object func() (meta.RESTMapper, runtime.ObjectTyper)
|
||||
// Returns a client for accessing Kubernetes resources or an error.
|
||||
Client func() (*client.Client, error)
|
||||
// Returns a client.Config for accessing the Kubernetes server.
|
||||
ClientConfig func() (*client.Config, error)
|
||||
// Returns a RESTClient for working with the specified RESTMapping or an error. This is intended
|
||||
// for working with arbitrary resources and is not guaranteed to point to a Kubernetes APIServer.
|
||||
RESTClient func(mapping *meta.RESTMapping) (resource.RESTClient, error)
|
||||
// Returns a Describer for displaying the specified RESTMapping type or an error.
|
||||
Describer func(mapping *meta.RESTMapping) (kubectl.Describer, error)
|
||||
// Returns a Printer for formatting objects of the given type or an error.
|
||||
Printer func(mapping *meta.RESTMapping, noHeaders bool) (kubectl.ResourcePrinter, error)
|
||||
// Returns a Resizer for changing the size of the specified RESTMapping type or an error
|
||||
Resizer func(mapping *meta.RESTMapping) (kubectl.Resizer, error)
|
||||
// Returns a Reaper for gracefully shutting down resources.
|
||||
Reaper func(mapping *meta.RESTMapping) (kubectl.Reaper, error)
|
||||
// PodSelectorForResource returns the pod selector associated with the provided resource name
|
||||
// or an error.
|
||||
PodSelectorForResource func(mapping *meta.RESTMapping, namespace, name string) (string, error)
|
||||
// PortForResource returns the ports associated with the provided resource name or an error
|
||||
PortsForResource func(mapping *meta.RESTMapping, namespace, name string) ([]string, error)
|
||||
// Returns a schema that can validate objects stored on disk.
|
||||
Validator func() (validation.Schema, error)
|
||||
// Returns the default namespace to use in cases where no other namespace is specified
|
||||
DefaultNamespace func() (string, error)
|
||||
}
|
||||
|
||||
// NewFactory creates a factory with the default Kubernetes resources defined
|
||||
// if optionalClientConfig is nil, then flags will be bound to a new clientcmd.ClientConfig.
|
||||
// if optionalClientConfig is not nil, then this factory will make use of it.
|
||||
func NewFactory(optionalClientConfig clientcmd.ClientConfig) *Factory {
|
||||
mapper := kubectl.ShortcutExpander{latest.RESTMapper}
|
||||
|
||||
flags := pflag.NewFlagSet("", pflag.ContinueOnError)
|
||||
|
||||
clientConfig := optionalClientConfig
|
||||
if optionalClientConfig == nil {
|
||||
clientConfig = DefaultClientConfig(flags)
|
||||
}
|
||||
|
||||
clients := &clientCache{
|
||||
clients: make(map[string]*client.Client),
|
||||
loader: clientConfig,
|
||||
}
|
||||
|
||||
return &Factory{
|
||||
clients: clients,
|
||||
flags: flags,
|
||||
|
||||
Object: func() (meta.RESTMapper, runtime.ObjectTyper) {
|
||||
cfg, err := clientConfig.ClientConfig()
|
||||
CheckErr(err)
|
||||
cmdApiVersion := cfg.Version
|
||||
|
||||
return kubectl.OutputVersionMapper{mapper, cmdApiVersion}, api.Scheme
|
||||
},
|
||||
Client: func() (*client.Client, error) {
|
||||
return clients.ClientForVersion("")
|
||||
},
|
||||
ClientConfig: func() (*client.Config, error) {
|
||||
return clients.ClientConfigForVersion("")
|
||||
},
|
||||
RESTClient: func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
|
||||
client, err := clients.ClientForVersion(mapping.APIVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return client.RESTClient, nil
|
||||
},
|
||||
Describer: func(mapping *meta.RESTMapping) (kubectl.Describer, error) {
|
||||
client, err := clients.ClientForVersion(mapping.APIVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
describer, ok := kubectl.DescriberFor(mapping.Kind, client)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("no description has been implemented for %q", mapping.Kind)
|
||||
}
|
||||
return describer, nil
|
||||
},
|
||||
Printer: func(mapping *meta.RESTMapping, noHeaders bool) (kubectl.ResourcePrinter, error) {
|
||||
return kubectl.NewHumanReadablePrinter(noHeaders), nil
|
||||
},
|
||||
PodSelectorForResource: func(mapping *meta.RESTMapping, namespace, name string) (string, error) {
|
||||
// TODO: replace with a swagger schema based approach (identify pod selector via schema introspection)
|
||||
client, err := clients.ClientForVersion("")
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
switch mapping.Kind {
|
||||
case "ReplicationController":
|
||||
rc, err := client.ReplicationControllers(namespace).Get(name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
return kubectl.MakeLabels(rc.Spec.Selector), nil
|
||||
case "Pod":
|
||||
rc, err := client.Pods(namespace).Get(name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if len(rc.Labels) == 0 {
|
||||
return "", fmt.Errorf("the pod has no labels and cannot be exposed")
|
||||
}
|
||||
return kubectl.MakeLabels(rc.Labels), nil
|
||||
case "Service":
|
||||
rc, err := client.ReplicationControllers(namespace).Get(name)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
if rc.Spec.Selector == nil {
|
||||
return "", fmt.Errorf("the service has no pod selector set")
|
||||
}
|
||||
return kubectl.MakeLabels(rc.Spec.Selector), nil
|
||||
default:
|
||||
return "", fmt.Errorf("it is not possible to get a pod selector from %s", mapping.Kind)
|
||||
}
|
||||
},
|
||||
PortsForResource: func(mapping *meta.RESTMapping, namespace, name string) ([]string, error) {
|
||||
// TODO: replace with a swagger schema based approach (identify pod selector via schema introspection)
|
||||
client, err := clients.ClientForVersion("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch mapping.Kind {
|
||||
case "ReplicationController":
|
||||
rc, err := client.ReplicationControllers(namespace).Get(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return getPorts(rc.Spec.Template.Spec), nil
|
||||
case "Pod":
|
||||
pod, err := client.Pods(namespace).Get(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return getPorts(pod.Spec), nil
|
||||
default:
|
||||
return nil, fmt.Errorf("it is not possible to get ports from %s", mapping.Kind)
|
||||
}
|
||||
},
|
||||
Resizer: func(mapping *meta.RESTMapping) (kubectl.Resizer, error) {
|
||||
client, err := clients.ClientForVersion(mapping.APIVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return kubectl.ResizerFor(mapping.Kind, client)
|
||||
},
|
||||
Reaper: func(mapping *meta.RESTMapping) (kubectl.Reaper, error) {
|
||||
client, err := clients.ClientForVersion(mapping.APIVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return kubectl.ReaperFor(mapping.Kind, client)
|
||||
},
|
||||
Validator: func() (validation.Schema, error) {
|
||||
if flags.Lookup("validate").Value.String() == "true" {
|
||||
client, err := clients.ClientForVersion("")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &clientSwaggerSchema{client, api.Scheme}, nil
|
||||
}
|
||||
return validation.NullSchema{}, nil
|
||||
},
|
||||
DefaultNamespace: func() (string, error) {
|
||||
return clientConfig.Namespace()
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// BindFlags adds any flags that are common to all kubectl sub commands.
|
||||
func (f *Factory) BindFlags(flags *pflag.FlagSet) {
|
||||
// any flags defined by external projects (not part of pflags)
|
||||
util.AddAllFlagsToPFlagSet(flags)
|
||||
|
||||
// This is necessary as github.com/spf13/cobra doesn't support "global"
|
||||
// pflags currently. See https://github.com/spf13/cobra/issues/44.
|
||||
util.AddPFlagSetToPFlagSet(pflag.CommandLine, flags)
|
||||
|
||||
// Hack for global access to validation flag.
|
||||
// TODO: Refactor out after configuration flag overhaul.
|
||||
if f.flags.Lookup("validate") == nil {
|
||||
f.flags.Bool("validate", false, "If true, use a schema to validate the input before sending it")
|
||||
}
|
||||
|
||||
if f.flags != nil {
|
||||
f.flags.VisitAll(func(flag *pflag.Flag) {
|
||||
flags.AddFlag(flag)
|
||||
})
|
||||
}
|
||||
|
||||
// Globally persistent flags across all subcommands.
|
||||
// TODO Change flag names to consts to allow safer lookup from subcommands.
|
||||
// TODO Add a verbose flag that turns on glog logging. Probably need a way
|
||||
// to do that automatically for every subcommand.
|
||||
flags.BoolVar(&f.clients.matchVersion, FlagMatchBinaryVersion, false, "Require server version to match client version")
|
||||
}
|
||||
|
||||
func getPorts(spec api.PodSpec) []string {
|
||||
result := []string{}
|
||||
for _, container := range spec.Containers {
|
||||
for _, port := range container.Ports {
|
||||
result = append(result, strconv.Itoa(port.ContainerPort))
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
type clientSwaggerSchema struct {
|
||||
c *client.Client
|
||||
t runtime.ObjectTyper
|
||||
}
|
||||
|
||||
func (c *clientSwaggerSchema) ValidateBytes(data []byte) error {
|
||||
version, _, err := c.t.DataVersionAndKind(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
schemaData, err := c.c.RESTClient.Get().
|
||||
AbsPath("/swaggerapi/api", version).
|
||||
Do().
|
||||
Raw()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
schema, err := validation.NewSwaggerSchemaFromBytes(schemaData)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return schema.ValidateBytes(data)
|
||||
}
|
||||
|
||||
// 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:
|
||||
// 1. CommandLineLocation - this parsed from the command line, so it must be late bound
|
||||
// 2. EnvVarLocation
|
||||
// 3. CurrentDirectoryLocation
|
||||
// 4. HomeDirectoryLocation
|
||||
// Empty filenames are ignored. Files with non-deserializable content produced errors.
|
||||
// The first file to set a particular value or map key wins and the value or map key is never changed.
|
||||
// This means that the first file to set CurrentContext will have its context preserved. It also means
|
||||
// that if two files specify a "red-user", only values from the first file's red-user are used. Even
|
||||
// non-conflicting entries from the second file's "red-user" are discarded.
|
||||
// 2. Determine the context to use based on the first hit in this chain
|
||||
// 1. command line argument - again, parsed from the command line, so it must be late bound
|
||||
// 2. CurrentContext from the merged kubeconfig file
|
||||
// 3. Empty is allowed at this stage
|
||||
// 3. Determine the cluster info and auth info to use. At this point, we may or may not have a context. They
|
||||
// are built based on the first hit in this chain. (run it twice, once for auth, once for cluster)
|
||||
// 1. command line argument
|
||||
// 2. If context is present, then use the context value
|
||||
// 3. Empty is allowed
|
||||
// 4. Determine the actual cluster info to use. At this point, we may or may not have a cluster info. Build
|
||||
// each piece of the cluster info based on the chain:
|
||||
// 1. command line argument
|
||||
// 2. If cluster info is present and a value for the attribute is present, use it.
|
||||
// 3. If you don't have a server location, bail.
|
||||
// 5. Auth info is build using the same rules as cluster info, EXCEPT that you can only have one authentication
|
||||
// technique per auth info. The following conditions result in an error:
|
||||
// 1. If there are two conflicting techniques specified from the command line, fail.
|
||||
// 2. If the command line does not specify one, and the auth info has conflicting techniques, fail.
|
||||
// 3. If the command line specifies one and the auth info specifies another, honor the command line technique.
|
||||
// 2. Use default values and potentially prompt for auth information
|
||||
func DefaultClientConfig(flags *pflag.FlagSet) clientcmd.ClientConfig {
|
||||
loadingRules := clientcmd.NewDefaultClientConfigLoadingRules()
|
||||
flags.StringVar(&loadingRules.ExplicitPath, "kubeconfig", "", "Path to the kubeconfig file to use for CLI requests.")
|
||||
|
||||
overrides := &clientcmd.ConfigOverrides{}
|
||||
flagNames := clientcmd.RecommendedConfigOverrideFlags("")
|
||||
// short flagnames are disabled by default. These are here for compatibility with existing scripts
|
||||
flagNames.AuthOverrideFlags.AuthPathShort = "a"
|
||||
flagNames.ClusterOverrideFlags.APIServerShort = "s"
|
||||
|
||||
clientcmd.BindOverrideFlags(overrides, flags, flagNames)
|
||||
clientConfig := clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, overrides, os.Stdin)
|
||||
|
||||
return clientConfig
|
||||
}
|
||||
|
||||
// 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()
|
||||
_, 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 := PrinterForCommand(cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if ok {
|
||||
clientConfig, err := f.ClientConfig()
|
||||
if err != nil {
|
||||
return nil, 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(mapping, GetFlagBool(cmd, "no-headers"))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return printer, nil
|
||||
}
|
||||
|
||||
// ClientMapperForCommand returns a ClientMapper for the factory.
|
||||
func (f *Factory) ClientMapperForCommand() resource.ClientMapper {
|
||||
return resource.ClientMapperFunc(func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
|
||||
return f.RESTClient(mapping)
|
||||
})
|
||||
}
|
|
@ -14,7 +14,7 @@ See the License for the specific language governing permissions and
|
|||
limitations under the License.
|
||||
*/
|
||||
|
||||
package cmd
|
||||
package util
|
||||
|
||||
import (
|
||||
"testing"
|
|
@ -22,24 +22,24 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||
)
|
||||
|
||||
func (f *Factory) NewCmdVersion(out io.Writer) *cobra.Command {
|
||||
func NewCmdVersion(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "version",
|
||||
Short: "Print the client and server version information.",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunVersion(f, out, cmd)
|
||||
util.CheckErr(err)
|
||||
cmdutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
cmd.Flags().BoolP("client", "c", false, "Client version only (no server required).")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func RunVersion(f *Factory, out io.Writer, cmd *cobra.Command) error {
|
||||
if util.GetFlagBool(cmd, "client") {
|
||||
func RunVersion(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command) error {
|
||||
if cmdutil.GetFlagBool(cmd, "client") {
|
||||
kubectl.GetClientVersion(out)
|
||||
return nil
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue