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"
|
"strings"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd"
|
||||||
|
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -139,7 +140,7 @@ func main() {
|
||||||
// regardless of where we run.
|
// regardless of where we run.
|
||||||
os.Setenv("HOME", "/home/username")
|
os.Setenv("HOME", "/home/username")
|
||||||
//TODO os.Stdin should really be something like ioutil.Discard, but a Reader
|
//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)
|
genMarkdown(kubectl, "", docsDir)
|
||||||
for _, c := range kubectl.Commands() {
|
for _, c := range kubectl.Commands() {
|
||||||
genMarkdown(c, "kubectl", docsDir)
|
genMarkdown(c, "kubectl", docsDir)
|
||||||
|
|
|
@ -25,6 +25,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd"
|
||||||
|
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"github.com/cpuguy83/go-md2man/mangen"
|
"github.com/cpuguy83/go-md2man/mangen"
|
||||||
"github.com/russross/blackfriday"
|
"github.com/russross/blackfriday"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -63,7 +64,7 @@ func main() {
|
||||||
// regardless of where we run.
|
// regardless of where we run.
|
||||||
os.Setenv("HOME", "/home/username")
|
os.Setenv("HOME", "/home/username")
|
||||||
//TODO os.Stdin should really be something like ioutil.Discard, but a Reader
|
//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)
|
genMarkdown(kubectl, "", docsDir)
|
||||||
for _, c := range kubectl.Commands() {
|
for _, c := range kubectl.Commands() {
|
||||||
genMarkdown(c, "kubectl", docsDir)
|
genMarkdown(c, "kubectl", docsDir)
|
||||||
|
|
|
@ -21,11 +21,12 @@ import (
|
||||||
"runtime"
|
"runtime"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd"
|
||||||
|
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
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 {
|
if err := cmd.Execute(); err != nil {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,10 +23,10 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"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{
|
cmd := &cobra.Command{
|
||||||
Use: "api-versions",
|
Use: "api-versions",
|
||||||
// apiversions is deprecated.
|
// apiversions is deprecated.
|
||||||
|
@ -34,13 +34,13 @@ func (f *Factory) NewCmdApiVersions(out io.Writer) *cobra.Command {
|
||||||
Short: "Print available API versions.",
|
Short: "Print available API versions.",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
err := RunApiVersions(f, out)
|
err := RunApiVersions(f, out)
|
||||||
util.CheckErr(err)
|
cmdutil.CheckErr(err)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunApiVersions(f *Factory, out io.Writer) error {
|
func RunApiVersions(f *cmdutil.Factory, out io.Writer) error {
|
||||||
if os.Args[1] == "apiversions" {
|
if os.Args[1] == "apiversions" {
|
||||||
printDeprecationWarning("api-versions", "apiversions")
|
printDeprecationWarning("api-versions", "apiversions")
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,14 +23,14 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"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/kubectl/resource"
|
||||||
|
|
||||||
"github.com/daviddengcn/go-colortext"
|
"github.com/daviddengcn/go-colortext"
|
||||||
"github.com/spf13/cobra"
|
"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{
|
cmd := &cobra.Command{
|
||||||
Use: "cluster-info",
|
Use: "cluster-info",
|
||||||
// clusterinfo is deprecated.
|
// 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",
|
Long: "Display addresses of the master and services with label kubernetes.io/cluster-service=true",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
err := RunClusterInfo(f, out, cmd)
|
err := RunClusterInfo(f, out, cmd)
|
||||||
util.CheckErr(err)
|
cmdutil.CheckErr(err)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return cmd
|
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" {
|
if os.Args[1] == "clusterinfo" {
|
||||||
printDeprecationWarning("cluster-info", "clusterinfo")
|
printDeprecationWarning("cluster-info", "clusterinfo")
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,254 +17,17 @@ limitations under the License.
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
"io"
|
"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"
|
cmdconfig "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/config"
|
||||||
cmdutil "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/GoogleCloudPlatform/kubernetes/pkg/util"
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"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.
|
// 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.
|
// Parent command to which all subcommands are added.
|
||||||
cmds := &cobra.Command{
|
cmds := &cobra.Command{
|
||||||
Use: "kubectl",
|
Use: "kubectl",
|
||||||
|
@ -277,223 +40,39 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`,
|
||||||
|
|
||||||
f.BindFlags(cmds.PersistentFlags())
|
f.BindFlags(cmds.PersistentFlags())
|
||||||
|
|
||||||
cmds.AddCommand(f.NewCmdGet(out))
|
cmds.AddCommand(NewCmdGet(f, out))
|
||||||
cmds.AddCommand(f.NewCmdDescribe(out))
|
cmds.AddCommand(NewCmdDescribe(f, out))
|
||||||
cmds.AddCommand(f.NewCmdCreate(out))
|
cmds.AddCommand(NewCmdCreate(f, out))
|
||||||
cmds.AddCommand(f.NewCmdUpdate(out))
|
cmds.AddCommand(NewCmdUpdate(f, out))
|
||||||
cmds.AddCommand(f.NewCmdDelete(out))
|
cmds.AddCommand(NewCmdDelete(f, out))
|
||||||
|
|
||||||
cmds.AddCommand(NewCmdNamespace(out))
|
cmds.AddCommand(NewCmdNamespace(out))
|
||||||
cmds.AddCommand(f.NewCmdLog(out))
|
cmds.AddCommand(NewCmdLog(f, out))
|
||||||
cmds.AddCommand(f.NewCmdRollingUpdate(out))
|
cmds.AddCommand(NewCmdRollingUpdate(f, out))
|
||||||
cmds.AddCommand(f.NewCmdResize(out))
|
cmds.AddCommand(NewCmdResize(f, out))
|
||||||
|
|
||||||
cmds.AddCommand(f.NewCmdExec(in, out, err))
|
cmds.AddCommand(NewCmdExec(f, in, out, err))
|
||||||
cmds.AddCommand(f.NewCmdPortForward())
|
cmds.AddCommand(NewCmdPortForward(f))
|
||||||
cmds.AddCommand(f.NewCmdProxy(out))
|
cmds.AddCommand(NewCmdProxy(f, out))
|
||||||
|
|
||||||
cmds.AddCommand(f.NewCmdRunContainer(out))
|
cmds.AddCommand(NewCmdRunContainer(f, out))
|
||||||
cmds.AddCommand(f.NewCmdStop(out))
|
cmds.AddCommand(NewCmdStop(f, out))
|
||||||
cmds.AddCommand(f.NewCmdExposeService(out))
|
cmds.AddCommand(NewCmdExposeService(f, out))
|
||||||
|
|
||||||
cmds.AddCommand(f.NewCmdLabel(out))
|
cmds.AddCommand(NewCmdLabel(f, out))
|
||||||
|
|
||||||
cmds.AddCommand(cmdconfig.NewCmdConfig(out))
|
cmds.AddCommand(cmdconfig.NewCmdConfig(f, out))
|
||||||
cmds.AddCommand(f.NewCmdClusterInfo(out))
|
cmds.AddCommand(NewCmdClusterInfo(f, out))
|
||||||
cmds.AddCommand(f.NewCmdApiVersions(out))
|
cmds.AddCommand(NewCmdApiVersions(f, out))
|
||||||
cmds.AddCommand(f.NewCmdVersion(out))
|
cmds.AddCommand(NewCmdVersion(f, out))
|
||||||
|
|
||||||
return cmds
|
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) {
|
func runHelp(cmd *cobra.Command, args []string) {
|
||||||
cmd.Help()
|
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) {
|
func printDeprecationWarning(command, alias string) {
|
||||||
glog.Warningf("%s is DEPRECATED and will be removed in a future version. Use %s instead.", alias, command)
|
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/api/validation"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"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/kubectl/resource"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||||
)
|
)
|
||||||
|
@ -109,14 +110,14 @@ type testFactory struct {
|
||||||
Err error
|
Err error
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewTestFactory() (*Factory, *testFactory, runtime.Codec) {
|
func NewTestFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) {
|
||||||
scheme, mapper, codec := newExternalScheme()
|
scheme, mapper, codec := newExternalScheme()
|
||||||
t := &testFactory{
|
t := &testFactory{
|
||||||
Validator: validation.NullSchema{},
|
Validator: validation.NullSchema{},
|
||||||
Mapper: mapper,
|
Mapper: mapper,
|
||||||
Typer: scheme,
|
Typer: scheme,
|
||||||
}
|
}
|
||||||
return &Factory{
|
return &cmdutil.Factory{
|
||||||
Object: func() (meta.RESTMapper, runtime.ObjectTyper) {
|
Object: func() (meta.RESTMapper, runtime.ObjectTyper) {
|
||||||
return t.Mapper, t.Typer
|
return t.Mapper, t.Typer
|
||||||
},
|
},
|
||||||
|
@ -141,11 +142,11 @@ func NewTestFactory() (*Factory, *testFactory, runtime.Codec) {
|
||||||
}, t, codec
|
}, t, codec
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAPIFactory() (*Factory, *testFactory, runtime.Codec) {
|
func NewAPIFactory() (*cmdutil.Factory, *testFactory, runtime.Codec) {
|
||||||
t := &testFactory{
|
t := &testFactory{
|
||||||
Validator: validation.NullSchema{},
|
Validator: validation.NullSchema{},
|
||||||
}
|
}
|
||||||
return &Factory{
|
return &cmdutil.Factory{
|
||||||
Object: func() (meta.RESTMapper, runtime.ObjectTyper) {
|
Object: func() (meta.RESTMapper, runtime.ObjectTyper) {
|
||||||
return latest.RESTMapper, api.Scheme
|
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
|
// Verify that resource.RESTClients constructed from a factory respect mapping.APIVersion
|
||||||
func TestClientVersions(t *testing.T) {
|
func TestClientVersions(t *testing.T) {
|
||||||
f := NewFactory(nil)
|
f := cmdutil.NewFactory(nil)
|
||||||
|
|
||||||
versions := []string{
|
versions := []string{
|
||||||
"v1beta1",
|
"v1beta1",
|
||||||
|
@ -209,7 +210,7 @@ func ExamplePrintReplicationController() {
|
||||||
Codec: codec,
|
Codec: codec,
|
||||||
Client: nil,
|
Client: nil,
|
||||||
}
|
}
|
||||||
cmd := f.NewCmdRunContainer(os.Stdout)
|
cmd := NewCmdRunContainer(f, os.Stdout)
|
||||||
ctrl := &api.ReplicationController{
|
ctrl := &api.ReplicationController{
|
||||||
ObjectMeta: api.ObjectMeta{
|
ObjectMeta: api.ObjectMeta{
|
||||||
Name: "foo",
|
Name: "foo",
|
||||||
|
|
|
@ -27,6 +27,7 @@ import (
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
|
||||||
clientcmdapi "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd/api"
|
clientcmdapi "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd/api"
|
||||||
|
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
type pathOptions struct {
|
type pathOptions struct {
|
||||||
|
@ -36,7 +37,7 @@ type pathOptions struct {
|
||||||
specifiedFile string
|
specifiedFile string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCmdConfig(out io.Writer) *cobra.Command {
|
func NewCmdConfig(f *cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||||
pathOptions := &pathOptions{}
|
pathOptions := &pathOptions{}
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
|
|
|
@ -26,6 +26,7 @@ import (
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
|
||||||
clientcmdapi "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd/api"
|
clientcmdapi "github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd/api"
|
||||||
|
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -618,8 +619,9 @@ func testConfigCommand(args []string, startingConfig clientcmdapi.Config) (strin
|
||||||
argsToUse = append(argsToUse, args...)
|
argsToUse = append(argsToUse, args...)
|
||||||
|
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
f := cmdutil.NewFactory(nil)
|
||||||
|
|
||||||
cmd := NewCmdConfig(buf)
|
cmd := NewCmdConfig(f, buf)
|
||||||
cmd.SetArgs(argsToUse)
|
cmd.SetArgs(argsToUse)
|
||||||
cmd.Execute()
|
cmd.Execute()
|
||||||
|
|
||||||
|
|
|
@ -38,7 +38,7 @@ $ kubectl create -f pod.json
|
||||||
$ cat pod.json | kubectl create -f -`
|
$ 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
|
var filenames util.StringList
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "create -f FILENAME",
|
Use: "create -f FILENAME",
|
||||||
|
@ -61,7 +61,7 @@ func ValidateArgs(cmd *cobra.Command, args []string) error {
|
||||||
return nil
|
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()
|
schema, err := f.Validator()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -28,7 +28,7 @@ func TestExtraArgsFail(t *testing.T) {
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
f, _, _ := NewAPIFactory()
|
f, _, _ := NewAPIFactory()
|
||||||
c := f.NewCmdCreate(buf)
|
c := NewCmdCreate(f, buf)
|
||||||
if ValidateArgs(c, []string{"rc"}) == nil {
|
if ValidateArgs(c, []string{"rc"}) == nil {
|
||||||
t.Errorf("unexpected non-error")
|
t.Errorf("unexpected non-error")
|
||||||
}
|
}
|
||||||
|
@ -55,7 +55,7 @@ func TestCreateObject(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
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/redis-master-controller.json")
|
||||||
cmd.Run(cmd, []string{})
|
cmd.Run(cmd, []string{})
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ func TestCreateMultipleObject(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
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/redis-master-controller.json")
|
||||||
cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.json")
|
cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.json")
|
||||||
cmd.Run(cmd, []string{})
|
cmd.Run(cmd, []string{})
|
||||||
|
@ -121,7 +121,7 @@ func TestCreateDirectory(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
cmd := f.NewCmdCreate(buf)
|
cmd := NewCmdCreate(f, buf)
|
||||||
cmd.Flags().Set("filename", "../../../examples/guestbook")
|
cmd.Flags().Set("filename", "../../../examples/guestbook")
|
||||||
cmd.Run(cmd, []string{})
|
cmd.Run(cmd, []string{})
|
||||||
|
|
||||||
|
|
|
@ -55,7 +55,7 @@ $ kubectl delete pod 1234-56-7890-234234-456456
|
||||||
$ kubectl delete pods --all`
|
$ 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
|
var filenames util.StringList
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "delete ([-f FILENAME] | (RESOURCE [(ID | -l label | --all)]",
|
Use: "delete ([-f FILENAME] | (RESOURCE [(ID | -l label | --all)]",
|
||||||
|
@ -73,7 +73,7 @@ func (f *Factory) NewCmdDelete(out io.Writer) *cobra.Command {
|
||||||
return cmd
|
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()
|
cmdNamespace, err := f.DefaultNamespace()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -47,7 +47,7 @@ func TestDeleteObject(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
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/redis-master-controller.json")
|
||||||
cmd.Run(cmd, []string{})
|
cmd.Run(cmd, []string{})
|
||||||
|
|
||||||
|
@ -75,7 +75,7 @@ func TestDeleteObjectIgnoreNotFound(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
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/redis-master-controller.json")
|
||||||
cmd.Run(cmd, []string{})
|
cmd.Run(cmd, []string{})
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ func TestDeleteMultipleObject(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
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/redis-master-controller.json")
|
||||||
cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.json")
|
cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.json")
|
||||||
cmd.Run(cmd, []string{})
|
cmd.Run(cmd, []string{})
|
||||||
|
@ -138,7 +138,7 @@ func TestDeleteMultipleObjectIgnoreMissing(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
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/redis-master-controller.json")
|
||||||
cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.json")
|
cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.json")
|
||||||
cmd.Run(cmd, []string{})
|
cmd.Run(cmd, []string{})
|
||||||
|
@ -170,7 +170,7 @@ func TestDeleteDirectory(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
cmd := f.NewCmdDelete(buf)
|
cmd := NewCmdDelete(f, buf)
|
||||||
cmd.Flags().Set("filename", "../../../examples/guestbook")
|
cmd.Flags().Set("filename", "../../../examples/guestbook")
|
||||||
cmd.Run(cmd, []string{})
|
cmd.Run(cmd, []string{})
|
||||||
|
|
||||||
|
@ -211,7 +211,7 @@ func TestDeleteMultipleSelector(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
cmd := f.NewCmdDelete(buf)
|
cmd := NewCmdDelete(f, buf)
|
||||||
cmd.Flags().Set("selector", "a=b")
|
cmd.Flags().Set("selector", "a=b")
|
||||||
cmd.Run(cmd, []string{"pods,services"})
|
cmd.Run(cmd, []string{"pods,services"})
|
||||||
|
|
||||||
|
|
|
@ -20,11 +20,11 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
cmdutil "github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd/util"
|
||||||
"github.com/spf13/cobra"
|
"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{
|
cmd := &cobra.Command{
|
||||||
Use: "describe RESOURCE ID",
|
Use: "describe RESOURCE ID",
|
||||||
Short: "Show details of a specific resource",
|
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.`,
|
given resource.`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
err := RunDescribe(f, out, cmd, args)
|
err := RunDescribe(f, out, cmd, args)
|
||||||
util.CheckErr(err)
|
cmdutil.CheckErr(err)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
return cmd
|
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()
|
cmdNamespace, err := f.DefaultNamespace()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -48,7 +48,7 @@ func RunDescribe(f *Factory, out io.Writer, cmd *cobra.Command, args []string) e
|
||||||
|
|
||||||
mapper, _ := f.Object()
|
mapper, _ := f.Object()
|
||||||
// TODO: use resource.Builder instead
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ func TestDescribeUnknownSchemaObject(t *testing.T) {
|
||||||
tf.Namespace = "non-default"
|
tf.Namespace = "non-default"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
cmd := f.NewCmdDescribe(buf)
|
cmd := NewCmdDescribe(f, buf)
|
||||||
cmd.Run(cmd, []string{"type", "foo"})
|
cmd.Run(cmd, []string{"type", "foo"})
|
||||||
|
|
||||||
if d.Name != "foo" || d.Namespace != "non-default" {
|
if d.Name != "foo" || d.Namespace != "non-default" {
|
||||||
|
|
|
@ -24,7 +24,7 @@ import (
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/remotecommand"
|
"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/docker/docker/pkg/term"
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/spf13/cobra"
|
"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`
|
$ 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{
|
cmd := &cobra.Command{
|
||||||
Use: "exec -p POD -c CONTAINER -- COMMAND [args...]",
|
Use: "exec -p POD -c CONTAINER -- COMMAND [args...]",
|
||||||
Short: "Execute a command in a container.",
|
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,
|
Example: exec_example,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
err := RunExec(f, cmdIn, cmdOut, cmdErr, cmd, args)
|
err := RunExec(f, cmdIn, cmdOut, cmdErr, cmd, args)
|
||||||
util.CheckErr(err)
|
cmdutil.CheckErr(err)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmd.Flags().StringP("pod", "p", "", "Pod name")
|
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
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunExec(f *Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cobra.Command, args []string) error {
|
func RunExec(f *cmdutil.Factory, cmdIn io.Reader, cmdOut, cmdErr io.Writer, cmd *cobra.Command, args []string) error {
|
||||||
podName := util.GetFlagString(cmd, "pod")
|
podName := cmdutil.GetFlagString(cmd, "pod")
|
||||||
if len(podName) == 0 {
|
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 {
|
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()
|
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)
|
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 {
|
if len(containerName) == 0 {
|
||||||
containerName = pod.Spec.Containers[0].Name
|
containerName = pod.Spec.Containers[0].Name
|
||||||
}
|
}
|
||||||
|
|
||||||
var stdin io.Reader
|
var stdin io.Reader
|
||||||
tty := util.GetFlagBool(cmd, "tty")
|
tty := cmdutil.GetFlagBool(cmd, "tty")
|
||||||
if util.GetFlagBool(cmd, "stdin") {
|
if cmdutil.GetFlagBool(cmd, "stdin") {
|
||||||
stdin = cmdIn
|
stdin = cmdIn
|
||||||
if tty {
|
if tty {
|
||||||
if file, ok := cmdIn.(*os.File); ok {
|
if file, ok := cmdIn.(*os.File); ok {
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"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"
|
"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`
|
$ 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{
|
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]",
|
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",
|
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,
|
Example: expose_example,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
err := RunExpose(f, out, cmd, args)
|
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("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().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.")
|
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
|
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
|
var name, resource string
|
||||||
switch l := len(args); {
|
switch l := len(args); {
|
||||||
case l == 2:
|
case l == 2:
|
||||||
resource, name = args[0], args[1]
|
resource, name = args[0], args[1]
|
||||||
default:
|
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()
|
namespace, err := f.DefaultNamespace()
|
||||||
|
@ -87,20 +87,20 @@ func RunExpose(f *Factory, out io.Writer, cmd *cobra.Command, args []string) err
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
generatorName := util.GetFlagString(cmd, "generator")
|
generatorName := cmdutil.GetFlagString(cmd, "generator")
|
||||||
|
|
||||||
generator, found := kubectl.Generators[generatorName]
|
generator, found := kubectl.Generators[generatorName]
|
||||||
if !found {
|
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()
|
names := generator.ParamNames()
|
||||||
params := kubectl.MakeParams(cmd, names)
|
params := kubectl.MakeParams(cmd, names)
|
||||||
if len(util.GetFlagString(cmd, "service-name")) == 0 {
|
if len(cmdutil.GetFlagString(cmd, "service-name")) == 0 {
|
||||||
params["name"] = name
|
params["name"] = name
|
||||||
} else {
|
} 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()
|
mapper, _ := f.Object()
|
||||||
v, k, err := mapper.VersionAndKindForResource(resource)
|
v, k, err := mapper.VersionAndKindForResource(resource)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -117,21 +117,21 @@ func RunExpose(f *Factory, out io.Writer, cmd *cobra.Command, args []string) err
|
||||||
}
|
}
|
||||||
params["selector"] = s
|
params["selector"] = s
|
||||||
}
|
}
|
||||||
if util.GetFlagInt(cmd, "port") < 0 {
|
if cmdutil.GetFlagInt(cmd, "port") < 0 {
|
||||||
ports, err := f.PortsForResource(mapping, namespace, name)
|
ports, err := f.PortsForResource(mapping, namespace, name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(ports) == 0 {
|
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 {
|
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]
|
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"
|
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
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
inline := util.GetFlagString(cmd, "overrides")
|
inline := cmdutil.GetFlagString(cmd, "overrides")
|
||||||
if len(inline) > 0 {
|
if len(inline) > 0 {
|
||||||
service, err = util.Merge(service, inline, "Service")
|
service, err = cmdutil.Merge(service, inline, "Service")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: extract this flag to a central location, when such a location exists.
|
// 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))
|
service, err = client.Services(namespace).Create(service.(*api.Service))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -23,7 +23,7 @@ import (
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"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/kubectl/resource"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/watch"
|
"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
|
// NewCmdGet creates a command object for the generic "get" action, which
|
||||||
// retrieves one or more resources from a server.
|
// 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{
|
cmd := &cobra.Command{
|
||||||
Use: "get [(-o|--output=)json|yaml|template|...] (RESOURCE [NAME] | RESOURCE/NAME ...)",
|
Use: "get [(-o|--output=)json|yaml|template|...] (RESOURCE [NAME] | RESOURCE/NAME ...)",
|
||||||
Short: "Display one or many resources",
|
Short: "Display one or many resources",
|
||||||
|
@ -67,10 +67,10 @@ func (f *Factory) NewCmdGet(out io.Writer) *cobra.Command {
|
||||||
Example: get_example,
|
Example: get_example,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
err := RunGet(f, out, cmd, args)
|
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().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().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.")
|
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
|
// RunGet implements the generic Get command
|
||||||
// TODO: convert all direct flag accessors to a struct and pass that instead of cmd
|
// 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 {
|
func RunGet(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||||
selector := util.GetFlagString(cmd, "selector")
|
selector := cmdutil.GetFlagString(cmd, "selector")
|
||||||
mapper, typer := f.Object()
|
mapper, typer := f.Object()
|
||||||
|
|
||||||
cmdNamespace, err := f.DefaultNamespace()
|
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
|
// 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 {
|
if isWatch || isWatchOnly {
|
||||||
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
|
r := resource.NewBuilder(mapper, typer, f.ClientMapperForCommand()).
|
||||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||||
|
@ -146,7 +146,7 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error
|
||||||
ResourceTypeOrNameArgs(true, args...).
|
ResourceTypeOrNameArgs(true, args...).
|
||||||
ContinueOnError().
|
ContinueOnError().
|
||||||
Latest()
|
Latest()
|
||||||
printer, generic, err := util.PrinterForCommand(cmd)
|
printer, generic, err := cmdutil.PrinterForCommand(cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -159,7 +159,7 @@ func RunGet(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error
|
||||||
defaultVersion := clientConfig.Version
|
defaultVersion := clientConfig.Version
|
||||||
|
|
||||||
// the outermost object will be converted to the output-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()
|
r := b.Flatten().Do()
|
||||||
obj, err := r.Object()
|
obj, err := r.Object()
|
||||||
|
|
|
@ -99,7 +99,7 @@ func TestGetUnknownSchemaObject(t *testing.T) {
|
||||||
tf.ClientConfig = &client.Config{Version: latest.Version}
|
tf.ClientConfig = &client.Config{Version: latest.Version}
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
cmd := f.NewCmdGet(buf)
|
cmd := NewCmdGet(f, buf)
|
||||||
cmd.SetOutput(buf)
|
cmd.SetOutput(buf)
|
||||||
cmd.Run(cmd, []string{"type", "foo"})
|
cmd.Run(cmd, []string{"type", "foo"})
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ func TestGetSchemaObject(t *testing.T) {
|
||||||
tf.ClientConfig = &client.Config{Version: "v1beta3"}
|
tf.ClientConfig = &client.Config{Version: "v1beta3"}
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
cmd := f.NewCmdGet(buf)
|
cmd := NewCmdGet(f, buf)
|
||||||
cmd.Run(cmd, []string{"replicationcontrollers", "foo"})
|
cmd.Run(cmd, []string{"replicationcontrollers", "foo"})
|
||||||
|
|
||||||
if !strings.Contains(buf.String(), "\"foo\"") {
|
if !strings.Contains(buf.String(), "\"foo\"") {
|
||||||
|
@ -148,7 +148,7 @@ func TestGetObjects(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
cmd := f.NewCmdGet(buf)
|
cmd := NewCmdGet(f, buf)
|
||||||
cmd.SetOutput(buf)
|
cmd.SetOutput(buf)
|
||||||
cmd.Run(cmd, []string{"pods", "foo"})
|
cmd.Run(cmd, []string{"pods", "foo"})
|
||||||
|
|
||||||
|
@ -174,7 +174,7 @@ func TestGetListObjects(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
cmd := f.NewCmdGet(buf)
|
cmd := NewCmdGet(f, buf)
|
||||||
cmd.SetOutput(buf)
|
cmd.SetOutput(buf)
|
||||||
cmd.Run(cmd, []string{"pods"})
|
cmd.Run(cmd, []string{"pods"})
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ func TestGetMultipleTypeObjects(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
cmd := f.NewCmdGet(buf)
|
cmd := NewCmdGet(f, buf)
|
||||||
cmd.SetOutput(buf)
|
cmd.SetOutput(buf)
|
||||||
cmd.Run(cmd, []string{"pods,services"})
|
cmd.Run(cmd, []string{"pods,services"})
|
||||||
|
|
||||||
|
@ -247,7 +247,7 @@ func TestGetMultipleTypeObjectsAsList(t *testing.T) {
|
||||||
tf.ClientConfig = &client.Config{Version: "v1beta1"}
|
tf.ClientConfig = &client.Config{Version: "v1beta1"}
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
cmd := f.NewCmdGet(buf)
|
cmd := NewCmdGet(f, buf)
|
||||||
cmd.SetOutput(buf)
|
cmd.SetOutput(buf)
|
||||||
|
|
||||||
cmd.Flags().Set("output", "json")
|
cmd.Flags().Set("output", "json")
|
||||||
|
@ -298,7 +298,7 @@ func TestGetMultipleTypeObjectsWithSelector(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
cmd := f.NewCmdGet(buf)
|
cmd := NewCmdGet(f, buf)
|
||||||
cmd.SetOutput(buf)
|
cmd.SetOutput(buf)
|
||||||
|
|
||||||
cmd.Flags().Set("selector", "a=b")
|
cmd.Flags().Set("selector", "a=b")
|
||||||
|
@ -344,7 +344,7 @@ func TestGetMultipleTypeObjectsWithDirectReference(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
cmd := f.NewCmdGet(buf)
|
cmd := NewCmdGet(f, buf)
|
||||||
cmd.SetOutput(buf)
|
cmd.SetOutput(buf)
|
||||||
|
|
||||||
cmd.Run(cmd, []string{"services/bar", "node/foo"})
|
cmd.Run(cmd, []string{"services/bar", "node/foo"})
|
||||||
|
@ -430,7 +430,7 @@ func TestWatchSelector(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
cmd := f.NewCmdGet(buf)
|
cmd := NewCmdGet(f, buf)
|
||||||
cmd.SetOutput(buf)
|
cmd.SetOutput(buf)
|
||||||
|
|
||||||
cmd.Flags().Set("watch", "true")
|
cmd.Flags().Set("watch", "true")
|
||||||
|
@ -469,7 +469,7 @@ func TestWatchResource(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
cmd := f.NewCmdGet(buf)
|
cmd := NewCmdGet(f, buf)
|
||||||
cmd.SetOutput(buf)
|
cmd.SetOutput(buf)
|
||||||
|
|
||||||
cmd.Flags().Set("watch", "true")
|
cmd.Flags().Set("watch", "true")
|
||||||
|
@ -507,7 +507,7 @@ func TestWatchOnlyResource(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
cmd := f.NewCmdGet(buf)
|
cmd := NewCmdGet(f, buf)
|
||||||
cmd.SetOutput(buf)
|
cmd.SetOutput(buf)
|
||||||
|
|
||||||
cmd.Flags().Set("watch-only", "true")
|
cmd.Flags().Set("watch-only", "true")
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"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/kubectl/resource"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/runtime"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
@ -50,7 +50,7 @@ $ kubectl label pods foo status=unhealthy --resource-version=1
|
||||||
$ kubectl label pods foo bar-`
|
$ 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{
|
cmd := &cobra.Command{
|
||||||
Use: "label [--overwrite] RESOURCE NAME KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]",
|
Use: "label [--overwrite] RESOURCE NAME KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]",
|
||||||
Short: "Update the labels on a resource",
|
Short: "Update the labels on a resource",
|
||||||
|
@ -58,10 +58,10 @@ func (f *Factory) NewCmdLabel(out io.Writer) *cobra.Command {
|
||||||
Example: label_example,
|
Example: label_example,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
err := RunLabel(f, out, cmd, args)
|
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().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().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")
|
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
|
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{}
|
resources, labelArgs := []string{}, []string{}
|
||||||
first := true
|
first := true
|
||||||
for _, s := range args {
|
for _, s := range args {
|
||||||
|
@ -163,20 +163,20 @@ func RunLabel(f *Factory, out io.Writer, cmd *cobra.Command, args []string) erro
|
||||||
case first && !isLabel:
|
case first && !isLabel:
|
||||||
resources = append(resources, s)
|
resources = append(resources, s)
|
||||||
case !first && !isLabel:
|
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 {
|
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 {
|
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")
|
selector := cmdutil.GetFlagString(cmd, "selector")
|
||||||
all := util.GetFlagBool(cmd, "all")
|
all := cmdutil.GetFlagBool(cmd, "all")
|
||||||
overwrite := util.GetFlagBool(cmd, "overwrite")
|
overwrite := cmdutil.GetFlagBool(cmd, "overwrite")
|
||||||
resourceVersion := util.GetFlagString(cmd, "resource-version")
|
resourceVersion := cmdutil.GetFlagString(cmd, "resource-version")
|
||||||
|
|
||||||
cmdNamespace, err := f.DefaultNamespace()
|
cmdNamespace, err := f.DefaultNamespace()
|
||||||
if err != nil {
|
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
|
// only apply resource version locking on a single resource
|
||||||
if !one && len(resourceVersion) > 0 {
|
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
|
// TODO: support bulk generic output a la Get
|
||||||
|
|
|
@ -294,7 +294,7 @@ func TestLabelErrors(t *testing.T) {
|
||||||
tf.ClientConfig = &client.Config{Version: "v1beta1"}
|
tf.ClientConfig = &client.Config{Version: "v1beta1"}
|
||||||
|
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
cmd := f.NewCmdLabel(buf)
|
cmd := NewCmdLabel(f, buf)
|
||||||
cmd.SetOutput(buf)
|
cmd.SetOutput(buf)
|
||||||
|
|
||||||
for k, v := range testCase.flags {
|
for k, v := range testCase.flags {
|
||||||
|
@ -351,7 +351,7 @@ func TestLabelMultipleObjects(t *testing.T) {
|
||||||
tf.ClientConfig = &client.Config{Version: "v1beta1"}
|
tf.ClientConfig = &client.Config{Version: "v1beta1"}
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
cmd := f.NewCmdLabel(buf)
|
cmd := NewCmdLabel(f, buf)
|
||||||
|
|
||||||
cmd.Flags().Set("all", "true")
|
cmd.Flags().Set("all", "true")
|
||||||
if err := RunLabel(f, buf, cmd, []string{"pods", "a=b"}); err != nil {
|
if err := RunLabel(f, buf, cmd, []string{"pods", "a=b"}); err != nil {
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"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"
|
libutil "github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||||
"github.com/spf13/cobra"
|
"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{
|
cmd := &cobra.Command{
|
||||||
Use: "log [-f] POD [CONTAINER]",
|
Use: "log [-f] POD [CONTAINER]",
|
||||||
Short: "Print the logs for a container in a pod.",
|
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,
|
Example: log_example,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
err := RunLog(f, out, cmd, args)
|
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.")
|
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
|
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 {
|
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 {
|
if len(args) > 2 {
|
||||||
return util.UsageError(cmd, "log POD [CONTAINER]")
|
return cmdutil.UsageError(cmd, "log POD [CONTAINER]")
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace, err := f.DefaultNamespace()
|
namespace, err := f.DefaultNamespace()
|
||||||
|
@ -109,7 +109,7 @@ func RunLog(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
follow := false
|
follow := false
|
||||||
if util.GetFlagBool(cmd, "follow") {
|
if cmdutil.GetFlagBool(cmd, "follow") {
|
||||||
follow = true
|
follow = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/portforward"
|
"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/golang/glog"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
@ -42,7 +42,7 @@ $ kubectl port-forward -p mypod :5000
|
||||||
$ kubectl port-forward -p mypod 0:5000`
|
$ kubectl port-forward -p mypod 0:5000`
|
||||||
)
|
)
|
||||||
|
|
||||||
func (f *Factory) NewCmdPortForward() *cobra.Command {
|
func NewCmdPortForward(f *cmdutil.Factory) *cobra.Command {
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "port-forward -p POD [LOCAL_PORT:]REMOTE_PORT [...[LOCAL_PORT_N:]REMOTE_PORT_N]",
|
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.",
|
Short: "Forward one or more local ports to a pod.",
|
||||||
|
@ -50,7 +50,7 @@ func (f *Factory) NewCmdPortForward() *cobra.Command {
|
||||||
Example: portforward_example,
|
Example: portforward_example,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
err := RunPortForward(f, cmd, args)
|
err := RunPortForward(f, cmd, args)
|
||||||
util.CheckErr(err)
|
cmdutil.CheckErr(err)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmd.Flags().StringP("pod", "p", "", "Pod name")
|
cmd.Flags().StringP("pod", "p", "", "Pod name")
|
||||||
|
@ -58,14 +58,14 @@ func (f *Factory) NewCmdPortForward() *cobra.Command {
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunPortForward(f *Factory, cmd *cobra.Command, args []string) error {
|
func RunPortForward(f *cmdutil.Factory, cmd *cobra.Command, args []string) error {
|
||||||
podName := util.GetFlagString(cmd, "pod")
|
podName := cmdutil.GetFlagString(cmd, "pod")
|
||||||
if len(podName) == 0 {
|
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 {
|
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()
|
namespace, err := f.DefaultNamespace()
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"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/golang/glog"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
@ -36,7 +36,7 @@ $ kubectl proxy --port=8011 --www=./local/www/
|
||||||
$ kubectl proxy --api-prefix=k8s-api`
|
$ 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{
|
cmd := &cobra.Command{
|
||||||
Use: "proxy [--port=PORT] [--www=static-dir] [--www-prefix=prefix] [--api-prefix=prefix]",
|
Use: "proxy [--port=PORT] [--www=static-dir] [--www-prefix=prefix] [--api-prefix=prefix]",
|
||||||
Short: "Run a proxy to the Kubernetes API server",
|
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,
|
Example: proxy_example,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
err := RunProxy(f, out, cmd)
|
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.")
|
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
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunProxy(f *Factory, out io.Writer, cmd *cobra.Command) error {
|
func RunProxy(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command) error {
|
||||||
port := util.GetFlagInt(cmd, "port")
|
port := cmdutil.GetFlagInt(cmd, "port")
|
||||||
fmt.Fprintf(out, "Starting to serve on localhost:%d", port)
|
fmt.Fprintf(out, "Starting to serve on localhost:%d", port)
|
||||||
|
|
||||||
clientConfig, err := f.ClientConfig()
|
clientConfig, err := f.ClientConfig()
|
||||||
|
@ -63,16 +63,16 @@ func RunProxy(f *Factory, out io.Writer, cmd *cobra.Command) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
staticPrefix := util.GetFlagString(cmd, "www-prefix")
|
staticPrefix := cmdutil.GetFlagString(cmd, "www-prefix")
|
||||||
if !strings.HasSuffix(staticPrefix, "/") {
|
if !strings.HasSuffix(staticPrefix, "/") {
|
||||||
staticPrefix += "/"
|
staticPrefix += "/"
|
||||||
}
|
}
|
||||||
|
|
||||||
apiProxyPrefix := util.GetFlagString(cmd, "api-prefix")
|
apiProxyPrefix := cmdutil.GetFlagString(cmd, "api-prefix")
|
||||||
if !strings.HasSuffix(apiProxyPrefix, "/") {
|
if !strings.HasSuffix(apiProxyPrefix, "/") {
|
||||||
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ import (
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/controller"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/controller"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"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/GoogleCloudPlatform/kubernetes/pkg/util/wait"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
@ -45,7 +45,7 @@ $ kubectl resize --current-replicas=2 --replicas=3 replicationcontrollers foo`
|
||||||
retryTimeout = 10 * time.Second
|
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{
|
cmd := &cobra.Command{
|
||||||
Use: "resize [--resource-version=version] [--current-replicas=count] --replicas=COUNT RESOURCE ID",
|
Use: "resize [--resource-version=version] [--current-replicas=count] --replicas=COUNT RESOURCE ID",
|
||||||
Short: "Set a new size for a Replication Controller.",
|
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,
|
Example: resize_example,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
err := RunResize(f, out, cmd, args)
|
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.")
|
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
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunResize(f *Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
func RunResize(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||||
count := util.GetFlagInt(cmd, "replicas")
|
count := cmdutil.GetFlagInt(cmd, "replicas")
|
||||||
if len(args) != 2 || count < 0 {
|
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()
|
cmdNamespace, err := f.DefaultNamespace()
|
||||||
|
@ -75,7 +75,7 @@ func RunResize(f *Factory, out io.Writer, cmd *cobra.Command, args []string) err
|
||||||
|
|
||||||
mapper, _ := f.Object()
|
mapper, _ := f.Object()
|
||||||
// TODO: use resource.Builder instead
|
// 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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -85,8 +85,8 @@ func RunResize(f *Factory, out io.Writer, cmd *cobra.Command, args []string) err
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
resourceVersion := util.GetFlagString(cmd, "resource-version")
|
resourceVersion := cmdutil.GetFlagString(cmd, "resource-version")
|
||||||
currentSize := util.GetFlagInt(cmd, "current-replicas")
|
currentSize := cmdutil.GetFlagInt(cmd, "current-replicas")
|
||||||
precondition := &kubectl.ResizePrecondition{currentSize, resourceVersion}
|
precondition := &kubectl.ResizePrecondition{currentSize, resourceVersion}
|
||||||
cond := kubectl.ResizeCondition(resizer, precondition, namespace, name, uint(count))
|
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/api"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"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/kubectl/resource"
|
||||||
"github.com/spf13/cobra"
|
"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 -`
|
$ 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{
|
cmd := &cobra.Command{
|
||||||
Use: "rolling-update OLD_CONTROLLER_NAME -f NEW_CONTROLLER_SPEC",
|
Use: "rolling-update OLD_CONTROLLER_NAME -f NEW_CONTROLLER_SPEC",
|
||||||
// rollingupdate is deprecated.
|
// rollingupdate is deprecated.
|
||||||
|
@ -54,7 +54,7 @@ func (f *Factory) NewCmdRollingUpdate(out io.Writer) *cobra.Command {
|
||||||
Example: rollingUpdate_example,
|
Example: rollingUpdate_example,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
err := RunRollingUpdate(f, out, cmd, args)
|
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".`)
|
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
|
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" {
|
if os.Args[1] == "rollingupdate" {
|
||||||
printDeprecationWarning("rolling-update", "rollingupdate")
|
printDeprecationWarning("rolling-update", "rollingupdate")
|
||||||
}
|
}
|
||||||
|
|
||||||
filename := util.GetFlagString(cmd, "filename")
|
filename := cmdutil.GetFlagString(cmd, "filename")
|
||||||
if len(filename) == 0 {
|
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")
|
period := cmdutil.GetFlagDuration(cmd, "update-period")
|
||||||
interval := util.GetFlagDuration(cmd, "poll-interval")
|
interval := cmdutil.GetFlagDuration(cmd, "poll-interval")
|
||||||
timeout := util.GetFlagDuration(cmd, "timeout")
|
timeout := cmdutil.GetFlagDuration(cmd, "timeout")
|
||||||
if len(args) != 1 {
|
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]
|
oldName := args[0]
|
||||||
|
|
||||||
|
@ -98,11 +98,11 @@ func RunRollingUpdate(f *Factory, out io.Writer, cmd *cobra.Command, args []stri
|
||||||
}
|
}
|
||||||
newRc, ok := obj.(*api.ReplicationController)
|
newRc, ok := obj.(*api.ReplicationController)
|
||||||
if !ok {
|
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
|
newName := newRc.Name
|
||||||
if oldName == newName {
|
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)
|
filename, oldName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,7 +127,7 @@ func RunRollingUpdate(f *Factory, out io.Writer, cmd *cobra.Command, args []stri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !hasLabel {
|
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)
|
filename, oldName)
|
||||||
}
|
}
|
||||||
// TODO: handle resizes during rolling update
|
// TODO: handle resizes during rolling update
|
||||||
|
|
|
@ -22,7 +22,7 @@ import (
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"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"
|
"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": { ... } }'`
|
$ 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{
|
cmd := &cobra.Command{
|
||||||
Use: "run-container NAME --image=image [--port=port] [--replicas=replicas] [--dry-run=bool] [--overrides=inline-json]",
|
Use: "run-container NAME --image=image [--port=port] [--replicas=replicas] [--dry-run=bool] [--overrides=inline-json]",
|
||||||
Short: "Run a particular image on the cluster.",
|
Short: "Run a particular image on the cluster.",
|
||||||
|
@ -50,10 +50,10 @@ func (f *Factory) NewCmdRunContainer(out io.Writer) *cobra.Command {
|
||||||
Example: run_example,
|
Example: run_example,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
err := RunRunContainer(f, out, cmd, args)
|
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("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().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.")
|
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
|
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 {
|
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()
|
namespace, err := f.DefaultNamespace()
|
||||||
|
@ -79,10 +79,10 @@ func RunRunContainer(f *Factory, out io.Writer, cmd *cobra.Command, args []strin
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
generatorName := util.GetFlagString(cmd, "generator")
|
generatorName := cmdutil.GetFlagString(cmd, "generator")
|
||||||
generator, found := kubectl.Generators[generatorName]
|
generator, found := kubectl.Generators[generatorName]
|
||||||
if !found {
|
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()
|
names := generator.ParamNames()
|
||||||
params := kubectl.MakeParams(cmd, names)
|
params := kubectl.MakeParams(cmd, names)
|
||||||
|
@ -98,16 +98,16 @@ func RunRunContainer(f *Factory, out io.Writer, cmd *cobra.Command, args []strin
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
inline := util.GetFlagString(cmd, "overrides")
|
inline := cmdutil.GetFlagString(cmd, "overrides")
|
||||||
if len(inline) > 0 {
|
if len(inline) > 0 {
|
||||||
controller, err = util.Merge(controller, inline, "ReplicationController")
|
controller, err = cmdutil.Merge(controller, inline, "ReplicationController")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: extract this flag to a central location, when such a location exists.
|
// 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))
|
controller, err = client.ReplicationControllers(namespace).Create(controller.(*api.ReplicationController))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -44,7 +44,7 @@ $ kubectl stop -f service.json
|
||||||
$ kubectl stop -f path/to/resources`
|
$ 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 {
|
flags := &struct {
|
||||||
Filenames util.StringList
|
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 }]}}'`
|
$ 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
|
var filenames util.StringList
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "update -f FILENAME",
|
Use: "update -f FILENAME",
|
||||||
|
@ -57,7 +57,7 @@ func (f *Factory) NewCmdUpdate(out io.Writer) *cobra.Command {
|
||||||
return cmd
|
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()
|
schema, err := f.Validator()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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()
|
cmdNamespace, err := f.DefaultNamespace()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
|
|
|
@ -47,7 +47,7 @@ func TestUpdateObject(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
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/redis-master-controller.json")
|
||||||
cmd.Run(cmd, []string{})
|
cmd.Run(cmd, []string{})
|
||||||
|
|
||||||
|
@ -83,7 +83,7 @@ func TestUpdateMultipleObject(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
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/redis-master-controller.json")
|
||||||
cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.json")
|
cmd.Flags().Set("filename", "../../../examples/guestbook/frontend-service.json")
|
||||||
cmd.Run(cmd, []string{})
|
cmd.Run(cmd, []string{})
|
||||||
|
@ -115,7 +115,7 @@ func TestUpdateDirectory(t *testing.T) {
|
||||||
tf.Namespace = "test"
|
tf.Namespace = "test"
|
||||||
buf := bytes.NewBuffer([]byte{})
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
cmd := f.NewCmdUpdate(buf)
|
cmd := NewCmdUpdate(f, buf)
|
||||||
cmd.Flags().Set("filename", "../../../examples/guestbook")
|
cmd.Flags().Set("filename", "../../../examples/guestbook")
|
||||||
cmd.Flags().Set("namespace", "test")
|
cmd.Flags().Set("namespace", "test")
|
||||||
cmd.Run(cmd, []string{})
|
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.
|
limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package cmd
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
|
@ -22,24 +22,24 @@ import (
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"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{
|
cmd := &cobra.Command{
|
||||||
Use: "version",
|
Use: "version",
|
||||||
Short: "Print the client and server version information.",
|
Short: "Print the client and server version information.",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
err := RunVersion(f, out, cmd)
|
err := RunVersion(f, out, cmd)
|
||||||
util.CheckErr(err)
|
cmdutil.CheckErr(err)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmd.Flags().BoolP("client", "c", false, "Client version only (no server required).")
|
cmd.Flags().BoolP("client", "c", false, "Client version only (no server required).")
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
func RunVersion(f *Factory, out io.Writer, cmd *cobra.Command) error {
|
func RunVersion(f *cmdutil.Factory, out io.Writer, cmd *cobra.Command) error {
|
||||||
if util.GetFlagBool(cmd, "client") {
|
if cmdutil.GetFlagBool(cmd, "client") {
|
||||||
kubectl.GetClientVersion(out)
|
kubectl.GetClientVersion(out)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue