mirror of https://github.com/k3s-io/k3s
Make expandResourceShortcuts part of RESTMapper on client
parent
a1ee782df5
commit
8a4f225941
|
@ -19,11 +19,15 @@ package main
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client/clientcmd"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl/cmd"
|
||||||
|
|
||||||
|
"github.com/golang/glog"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
clientBuilder := clientcmd.NewInteractiveClientConfig(clientcmd.Config{}, "", &clientcmd.ConfigOverrides{}, os.Stdin)
|
cmd := cmd.NewFactory().NewKubectlCommand(os.Stdout)
|
||||||
cmd.NewFactory(clientBuilder).Run(os.Stdout)
|
if err := cmd.Execute(); err != nil {
|
||||||
|
glog.Errorf("error: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,7 @@ import (
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
"github.com/spf13/pflag"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -42,55 +43,108 @@ const (
|
||||||
// Factory provides abstractions that allow the Kubectl command to be extended across multiple types
|
// Factory provides abstractions that allow the Kubectl command to be extended across multiple types
|
||||||
// of resources and different API sets.
|
// of resources and different API sets.
|
||||||
type Factory struct {
|
type Factory struct {
|
||||||
ClientConfig clientcmd.ClientConfig
|
clients *clientCache
|
||||||
Mapper meta.RESTMapper
|
flags *pflag.FlagSet
|
||||||
Typer runtime.ObjectTyper
|
|
||||||
Client func(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.RESTClient, error)
|
Mapper meta.RESTMapper
|
||||||
Describer func(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.Describer, error)
|
Typer runtime.ObjectTyper
|
||||||
Printer func(cmd *cobra.Command, mapping *meta.RESTMapping, noHeaders bool) (kubectl.ResourcePrinter, error)
|
|
||||||
Validator func(*cobra.Command) (validation.Schema, error)
|
// Returns a client for accessing Kubernetes resources or an error.
|
||||||
|
Client func(cmd *cobra.Command) (*client.Client, error)
|
||||||
|
// Returns a client.Config for accessing the Kubernetes server.
|
||||||
|
ClientConfig func(cmd *cobra.Command) (*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(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.RESTClient, error)
|
||||||
|
// Returns a Describer for displaying the specified RESTMapping type or an error.
|
||||||
|
Describer func(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.Describer, error)
|
||||||
|
// Returns a Printer for formatting objects of the given type or an error.
|
||||||
|
Printer func(cmd *cobra.Command, mapping *meta.RESTMapping, noHeaders bool) (kubectl.ResourcePrinter, error)
|
||||||
|
// Returns a schema that can validate objects stored on disk.
|
||||||
|
Validator func(*cobra.Command) (validation.Schema, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewFactory creates a factory with the default Kubernetes resources defined
|
// NewFactory creates a factory with the default Kubernetes resources defined
|
||||||
func NewFactory(clientConfig clientcmd.ClientConfig) *Factory {
|
func NewFactory() *Factory {
|
||||||
ret := &Factory{
|
mapper := kubectl.ShortcutExpander{latest.RESTMapper}
|
||||||
ClientConfig: clientConfig,
|
|
||||||
Mapper: latest.RESTMapper,
|
flags := pflag.NewFlagSet("", pflag.ContinueOnError)
|
||||||
Typer: api.Scheme,
|
clientConfig := DefaultClientConfig(flags)
|
||||||
Printer: func(cmd *cobra.Command, mapping *meta.RESTMapping, noHeaders bool) (kubectl.ResourcePrinter, error) {
|
clients := &clientCache{
|
||||||
return kubectl.NewHumanReadablePrinter(noHeaders), nil
|
clients: make(map[string]*client.Client),
|
||||||
},
|
loader: clientConfig,
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.Validator = func(cmd *cobra.Command) (validation.Schema, error) {
|
return &Factory{
|
||||||
if GetFlagBool(cmd, "validate") {
|
clients: clients,
|
||||||
client, err := getClient(ret.ClientConfig, GetFlagBool(cmd, FlagMatchBinaryVersion))
|
flags: flags,
|
||||||
|
|
||||||
|
Mapper: mapper,
|
||||||
|
Typer: api.Scheme,
|
||||||
|
|
||||||
|
Client: func(cmd *cobra.Command) (*client.Client, error) {
|
||||||
|
return clients.ClientForVersion("")
|
||||||
|
},
|
||||||
|
ClientConfig: func(cmd *cobra.Command) (*client.Config, error) {
|
||||||
|
return clients.ClientConfigForVersion("")
|
||||||
|
},
|
||||||
|
RESTClient: func(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.RESTClient, error) {
|
||||||
|
client, err := clients.ClientForVersion(mapping.APIVersion)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &clientSwaggerSchema{client, api.Scheme}, nil
|
return client.RESTClient, nil
|
||||||
} else {
|
},
|
||||||
|
Describer: func(cmd *cobra.Command, 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(cmd *cobra.Command, mapping *meta.RESTMapping, noHeaders bool) (kubectl.ResourcePrinter, error) {
|
||||||
|
return kubectl.NewHumanReadablePrinter(noHeaders), nil
|
||||||
|
},
|
||||||
|
Validator: func(cmd *cobra.Command) (validation.Schema, error) {
|
||||||
|
if GetFlagBool(cmd, "validate") {
|
||||||
|
client, err := clients.ClientForVersion("")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &clientSwaggerSchema{client, api.Scheme}, nil
|
||||||
|
}
|
||||||
return validation.NullSchema{}, nil
|
return validation.NullSchema{}, nil
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
ret.Client = func(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.RESTClient, error) {
|
|
||||||
return getClient(ret.ClientConfig, GetFlagBool(cmd, FlagMatchBinaryVersion))
|
|
||||||
}
|
|
||||||
ret.Describer = func(cmd *cobra.Command, mapping *meta.RESTMapping) (kubectl.Describer, error) {
|
|
||||||
client, err := getClient(ret.ClientConfig, GetFlagBool(cmd, FlagMatchBinaryVersion))
|
|
||||||
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
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Factory) Run(out io.Writer) {
|
// 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)
|
||||||
|
|
||||||
|
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")
|
||||||
|
flags.String("ns-path", os.Getenv("HOME")+"/.kubernetes_ns", "Path to the namespace info file that holds the namespace context to use for CLI requests.")
|
||||||
|
flags.StringP("namespace", "n", "", "If present, the namespace scope for this CLI request.")
|
||||||
|
flags.Bool("validate", false, "If true, use a schema to validate the input before sending it")
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewKubectlCommand creates the `kubectl` command and its nested children.
|
||||||
|
func (f *Factory) NewKubectlCommand(out 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",
|
||||||
|
@ -101,15 +155,7 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`,
|
||||||
Run: runHelp,
|
Run: runHelp,
|
||||||
}
|
}
|
||||||
|
|
||||||
util.AddAllFlagsToPFlagSet(cmds.PersistentFlags())
|
f.BindFlags(cmds.PersistentFlags())
|
||||||
f.ClientConfig = getClientConfig(cmds)
|
|
||||||
|
|
||||||
// Globally persistent flags across all subcommands.
|
|
||||||
// TODO Change flag names to consts to allow safer lookup from subcommands.
|
|
||||||
cmds.PersistentFlags().Bool(FlagMatchBinaryVersion, false, "Require server version to match client version")
|
|
||||||
cmds.PersistentFlags().String("ns-path", os.Getenv("HOME")+"/.kubernetes_ns", "Path to the namespace info file that holds the namespace context to use for CLI requests.")
|
|
||||||
cmds.PersistentFlags().StringP("namespace", "n", "", "If present, the namespace scope for this CLI request.")
|
|
||||||
cmds.PersistentFlags().Bool("validate", false, "If true, use a schema to validate the input before sending it")
|
|
||||||
|
|
||||||
cmds.AddCommand(f.NewCmdVersion(out))
|
cmds.AddCommand(f.NewCmdVersion(out))
|
||||||
cmds.AddCommand(f.NewCmdProxy(out))
|
cmds.AddCommand(f.NewCmdProxy(out))
|
||||||
|
@ -125,12 +171,10 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`,
|
||||||
cmds.AddCommand(f.NewCmdLog(out))
|
cmds.AddCommand(f.NewCmdLog(out))
|
||||||
cmds.AddCommand(f.NewCmdRollingUpdate(out))
|
cmds.AddCommand(f.NewCmdRollingUpdate(out))
|
||||||
|
|
||||||
if err := cmds.Execute(); err != nil {
|
return cmds
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// getClientBuilder creates a clientcmd.ClientConfig that has a hierarchy like this:
|
// 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. 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. 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
|
// 1. CommandLineLocation - this parsed from the command line, so it must be late bound
|
||||||
|
@ -162,13 +206,13 @@ Find more information at https://github.com/GoogleCloudPlatform/kubernetes.`,
|
||||||
// 2. If the command line does not specify one, and the auth info has conflicting techniques, 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.
|
// 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
|
// 2. Use default values and potentially prompt for auth information
|
||||||
func getClientConfig(cmd *cobra.Command) clientcmd.ClientConfig {
|
func DefaultClientConfig(flags *pflag.FlagSet) clientcmd.ClientConfig {
|
||||||
loadingRules := clientcmd.NewClientConfigLoadingRules()
|
loadingRules := clientcmd.NewClientConfigLoadingRules()
|
||||||
loadingRules.EnvVarPath = os.Getenv(clientcmd.RecommendedConfigPathEnvVar)
|
loadingRules.EnvVarPath = os.Getenv(clientcmd.RecommendedConfigPathEnvVar)
|
||||||
cmd.PersistentFlags().StringVar(&loadingRules.CommandLinePath, "kubeconfig", "", "Path to the kubeconfig file to use for CLI requests.")
|
flags.StringVar(&loadingRules.CommandLinePath, "kubeconfig", "", "Path to the kubeconfig file to use for CLI requests.")
|
||||||
|
|
||||||
overrides := &clientcmd.ConfigOverrides{}
|
overrides := &clientcmd.ConfigOverrides{}
|
||||||
overrides.BindFlags(cmd.PersistentFlags(), clientcmd.RecommendedConfigOverrideFlags(""))
|
overrides.BindFlags(flags, clientcmd.RecommendedConfigOverrideFlags(""))
|
||||||
clientConfig := clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, overrides, os.Stdin)
|
clientConfig := clientcmd.NewInteractiveDeferredLoadingClientConfig(loadingRules, overrides, os.Stdin)
|
||||||
|
|
||||||
return clientConfig
|
return clientConfig
|
||||||
|
@ -246,18 +290,55 @@ func (c *clientSwaggerSchema) ValidateBytes(data []byte) error {
|
||||||
return schema.ValidateBytes(data)
|
return schema.ValidateBytes(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Need to only run server version match once per client host creation
|
// clientCache caches previously loaded clients for reuse, and ensures MatchServerVersion
|
||||||
func getClient(clientConfig clientcmd.ClientConfig, matchServerVersion bool) (*client.Client, error) {
|
// is invoked only once
|
||||||
config, err := clientConfig.ClientConfig()
|
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: remove when SetKubernetesDefaults gets added
|
||||||
|
if len(version) == 0 {
|
||||||
|
version = c.defaultConfig.Version
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: have a better config copy method
|
||||||
|
config := *c.defaultConfig
|
||||||
|
|
||||||
|
// TODO: call new client.SetKubernetesDefaults method
|
||||||
|
// instead of doing this
|
||||||
|
config.Version = version
|
||||||
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if matchServerVersion {
|
if client, ok := c.clients[config.Version]; ok {
|
||||||
err := client.MatchesServerVersion(config)
|
return client, nil
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
client, err := client.New(config)
|
client, err := client.New(config)
|
||||||
|
@ -265,5 +346,6 @@ func getClient(clientConfig clientcmd.ClientConfig, matchServerVersion bool) (*c
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
c.clients[config.Version] = client
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -100,7 +100,7 @@ func NewTestFactory() (*Factory, *testFactory, runtime.Codec) {
|
||||||
return &Factory{
|
return &Factory{
|
||||||
Mapper: mapper,
|
Mapper: mapper,
|
||||||
Typer: scheme,
|
Typer: scheme,
|
||||||
Client: func(*cobra.Command, *meta.RESTMapping) (kubectl.RESTClient, error) {
|
RESTClient: func(*cobra.Command, *meta.RESTMapping) (kubectl.RESTClient, error) {
|
||||||
return t.Client, t.Err
|
return t.Client, t.Err
|
||||||
},
|
},
|
||||||
Describer: func(*cobra.Command, *meta.RESTMapping) (kubectl.Describer, error) {
|
Describer: func(*cobra.Command, *meta.RESTMapping) (kubectl.Describer, error) {
|
||||||
|
|
|
@ -46,7 +46,7 @@ Examples:
|
||||||
schema, err := f.Validator(cmd)
|
schema, err := f.Validator(cmd)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
mapping, namespace, name, data := ResourceFromFile(cmd, filename, f.Typer, f.Mapper, schema)
|
mapping, namespace, name, data := ResourceFromFile(cmd, filename, f.Typer, f.Mapper, schema)
|
||||||
client, err := f.Client(cmd, mapping)
|
client, err := f.RESTClient(cmd, mapping)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
// use the default namespace if not specified, or check for conflict with the file's namespace
|
// use the default namespace if not specified, or check for conflict with the file's namespace
|
||||||
|
|
|
@ -79,7 +79,7 @@ Examples:
|
||||||
<creates all resources listed in config.json>`,
|
<creates all resources listed in config.json>`,
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
clientFunc := func(mapper *meta.RESTMapping) (config.RESTClientPoster, error) {
|
clientFunc := func(mapper *meta.RESTMapping) (config.RESTClientPoster, error) {
|
||||||
client, err := f.Client(cmd, mapper)
|
client, err := f.RESTClient(cmd, mapper)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
return client, nil
|
return client, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ Examples:
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
selector := GetFlagString(cmd, "selector")
|
selector := GetFlagString(cmd, "selector")
|
||||||
found := 0
|
found := 0
|
||||||
ResourcesFromArgsOrFile(cmd, args, filename, selector, f.Typer, f.Mapper, f.Client, schema).Visit(func(r *resource.Info) error {
|
ResourcesFromArgsOrFile(cmd, args, filename, selector, f.Typer, f.Mapper, f.RESTClient, schema).Visit(func(r *resource.Info) error {
|
||||||
found++
|
found++
|
||||||
if err := resource.NewHelper(r.Client, r.Mapping).Delete(r.Namespace, r.Name); err != nil {
|
if err := resource.NewHelper(r.Client, r.Mapping).Delete(r.Namespace, r.Name); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
|
@ -56,7 +56,7 @@ Examples:
|
||||||
labelSelector, err := labels.ParseSelector(selector)
|
labelSelector, err := labels.ParseSelector(selector)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
client, err := f.Client(cmd, mapping)
|
client, err := f.RESTClient(cmd, mapping)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
outputFormat := GetFlagString(cmd, "output")
|
outputFormat := GetFlagString(cmd, "output")
|
||||||
|
|
|
@ -21,8 +21,6 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (f *Factory) NewCmdLog(out io.Writer) *cobra.Command {
|
func (f *Factory) NewCmdLog(out io.Writer) *cobra.Command {
|
||||||
|
@ -46,9 +44,7 @@ Examples:
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace := GetKubeNamespace(cmd)
|
namespace := GetKubeNamespace(cmd)
|
||||||
config, err := f.ClientConfig.ClientConfig()
|
client, err := f.Client(cmd)
|
||||||
checkErr(err)
|
|
||||||
client, err := client.New(config)
|
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
podID := args[0]
|
podID := args[0]
|
||||||
|
|
|
@ -33,7 +33,7 @@ func (f *Factory) NewCmdProxy(out io.Writer) *cobra.Command {
|
||||||
port := GetFlagInt(cmd, "port")
|
port := GetFlagInt(cmd, "port")
|
||||||
glog.Infof("Starting to serve on localhost:%d", port)
|
glog.Infof("Starting to serve on localhost:%d", port)
|
||||||
|
|
||||||
clientConfig, err := f.ClientConfig.ClientConfig()
|
clientConfig, err := f.ClientConfig(cmd)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
server, err := kubectl.NewProxyServer(GetFlagString(cmd, "www"), clientConfig, port)
|
server, err := kubectl.NewProxyServer(GetFlagString(cmd, "www"), clientConfig, port)
|
||||||
|
|
|
@ -63,7 +63,7 @@ func ResourcesFromArgsOrFile(
|
||||||
}
|
}
|
||||||
types := SplitResourceArgument(args[0])
|
types := SplitResourceArgument(args[0])
|
||||||
for _, arg := range types {
|
for _, arg := range types {
|
||||||
resourceName := kubectl.ExpandResourceShortcut(arg)
|
resourceName := arg
|
||||||
if len(resourceName) == 0 {
|
if len(resourceName) == 0 {
|
||||||
usageError(cmd, "Unknown resource %s", resourceName)
|
usageError(cmd, "Unknown resource %s", resourceName)
|
||||||
}
|
}
|
||||||
|
@ -91,7 +91,7 @@ func ResourceFromArgsOrFile(cmd *cobra.Command, args []string, filename string,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(args) == 2 {
|
if len(args) == 2 {
|
||||||
resource := kubectl.ExpandResourceShortcut(args[0])
|
resource := args[0]
|
||||||
namespace = GetKubeNamespace(cmd)
|
namespace = GetKubeNamespace(cmd)
|
||||||
name = args[1]
|
name = args[1]
|
||||||
if len(name) == 0 || len(resource) == 0 {
|
if len(name) == 0 || len(resource) == 0 {
|
||||||
|
@ -129,7 +129,7 @@ func ResourceFromArgs(cmd *cobra.Command, args []string, mapper meta.RESTMapper)
|
||||||
usageError(cmd, "Must provide resource and name command line params")
|
usageError(cmd, "Must provide resource and name command line params")
|
||||||
}
|
}
|
||||||
|
|
||||||
resource := kubectl.ExpandResourceShortcut(args[0])
|
resource := args[0]
|
||||||
namespace = GetKubeNamespace(cmd)
|
namespace = GetKubeNamespace(cmd)
|
||||||
name = args[1]
|
name = args[1]
|
||||||
if len(name) == 0 || len(resource) == 0 {
|
if len(name) == 0 || len(resource) == 0 {
|
||||||
|
@ -152,7 +152,7 @@ func ResourceOrTypeFromArgs(cmd *cobra.Command, args []string, mapper meta.RESTM
|
||||||
usageError(cmd, "Must provide resource or a resource and name as command line params")
|
usageError(cmd, "Must provide resource or a resource and name as command line params")
|
||||||
}
|
}
|
||||||
|
|
||||||
resource := kubectl.ExpandResourceShortcut(args[0])
|
resource := args[0]
|
||||||
if len(resource) == 0 {
|
if len(resource) == 0 {
|
||||||
usageError(cmd, "Must provide resource or a resource and name as command line params")
|
usageError(cmd, "Must provide resource or a resource and name as command line params")
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ import (
|
||||||
"io"
|
"io"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
@ -69,9 +68,7 @@ $ cat frontend-v2.json | kubectl rollingupdate frontend-v1 -f -
|
||||||
err = CompareNamespaceFromFile(cmd, namespace)
|
err = CompareNamespaceFromFile(cmd, namespace)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
config, err := f.ClientConfig.ClientConfig()
|
client, err := f.Client(cmd)
|
||||||
checkErr(err)
|
|
||||||
client, err := client.New(config)
|
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
obj, err := mapping.Codec.Decode(data)
|
obj, err := mapping.Codec.Decode(data)
|
||||||
|
|
|
@ -46,7 +46,7 @@ Examples:
|
||||||
schema, err := f.Validator(cmd)
|
schema, err := f.Validator(cmd)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
mapping, namespace, name, data := ResourceFromFile(cmd, filename, f.Typer, f.Mapper, schema)
|
mapping, namespace, name, data := ResourceFromFile(cmd, filename, f.Typer, f.Mapper, schema)
|
||||||
client, err := f.Client(cmd, mapping)
|
client, err := f.RESTClient(cmd, mapping)
|
||||||
checkErr(err)
|
checkErr(err)
|
||||||
|
|
||||||
err = CompareNamespaceFromFile(cmd, namespace)
|
err = CompareNamespaceFromFile(cmd, namespace)
|
||||||
|
|
|
@ -21,7 +21,6 @@ import (
|
||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/kubectl"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,14 +31,13 @@ func (f *Factory) NewCmdVersion(out io.Writer) *cobra.Command {
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
if GetFlagBool(cmd, "client") {
|
if GetFlagBool(cmd, "client") {
|
||||||
kubectl.GetClientVersion(out)
|
kubectl.GetClientVersion(out)
|
||||||
} else {
|
return
|
||||||
config, err := f.ClientConfig.ClientConfig()
|
|
||||||
checkErr(err)
|
|
||||||
client, err := client.New(config)
|
|
||||||
checkErr(err)
|
|
||||||
|
|
||||||
kubectl.GetVersion(out, client)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
client, err := f.Client(cmd)
|
||||||
|
checkErr(err)
|
||||||
|
|
||||||
|
kubectl.GetVersion(out, client)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmd.Flags().BoolP("client", "c", false, "Client version only (no server required)")
|
cmd.Flags().BoolP("client", "c", false, "Client version only (no server required)")
|
||||||
|
|
|
@ -26,6 +26,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api"
|
||||||
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/meta"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/client"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/labels"
|
||||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
"github.com/GoogleCloudPlatform/kubernetes/pkg/util"
|
||||||
|
@ -111,12 +112,23 @@ func makeImageList(spec *api.PodSpec) string {
|
||||||
return strings.Join(listOfImages(spec), ",")
|
return strings.Join(listOfImages(spec), ",")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExpandResourceShortcut will return the expanded version of resource
|
// ShortcutExpander is a RESTMapper that can be used for Kubernetes
|
||||||
|
// resources.
|
||||||
|
type ShortcutExpander struct {
|
||||||
|
meta.RESTMapper
|
||||||
|
}
|
||||||
|
|
||||||
|
// VersionAndKindForResource implements meta.RESTMapper. It expands the resource first, then invokes the wrapped
|
||||||
|
// mapper.
|
||||||
|
func (e ShortcutExpander) VersionAndKindForResource(resource string) (defaultVersion, kind string, err error) {
|
||||||
|
resource = expandResourceShortcut(resource)
|
||||||
|
return e.RESTMapper.VersionAndKindForResource(resource)
|
||||||
|
}
|
||||||
|
|
||||||
|
// expandResourceShortcut will return the expanded version of resource
|
||||||
// (something that a pkg/api/meta.RESTMapper can understand), if it is
|
// (something that a pkg/api/meta.RESTMapper can understand), if it is
|
||||||
// indeed a shortcut. Otherwise, will return resource unmodified.
|
// indeed a shortcut. Otherwise, will return resource unmodified.
|
||||||
// TODO: Combine with RESTMapper stuff to provide a general solution
|
func expandResourceShortcut(resource string) string {
|
||||||
// to this problem.
|
|
||||||
func ExpandResourceShortcut(resource string) string {
|
|
||||||
shortForms := map[string]string{
|
shortForms := map[string]string{
|
||||||
"po": "pods",
|
"po": "pods",
|
||||||
"rc": "replicationcontrollers",
|
"rc": "replicationcontrollers",
|
||||||
|
|
Loading…
Reference in New Issue