mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-22 19:31:44 +00:00
Remove Factory from more Run commands
This commit is contained in:
parent
03c5f298f3
commit
b7d4f15965
@ -3132,7 +3132,7 @@ run_deployment_tests() {
|
||||
# Set env of deployments for all container
|
||||
kubectl set env deployment nginx-deployment env=prod "${kube_flags[@]}"
|
||||
# Set env of deployments for specific container
|
||||
kubectl set env deployment nginx-deployment env=prod -c=nginx "${kube_flags[@]}"
|
||||
kubectl set env deployment nginx-deployment superenv=superprod -c=nginx "${kube_flags[@]}"
|
||||
# Set env of deployments by configmap
|
||||
kubectl set env deployment nginx-deployment --from=configmap/test-set-env-config "${kube_flags[@]}"
|
||||
# Set env of deployments by secret
|
||||
|
@ -59,10 +59,15 @@ type AnnotateOptions struct {
|
||||
outputFormat string
|
||||
|
||||
// results of arg parsing
|
||||
resources []string
|
||||
newAnnotations map[string]string
|
||||
removeAnnotations []string
|
||||
Recorder genericclioptions.Recorder
|
||||
resources []string
|
||||
newAnnotations map[string]string
|
||||
removeAnnotations []string
|
||||
Recorder genericclioptions.Recorder
|
||||
namespace string
|
||||
enforceNamespace bool
|
||||
builder *resource.Builder
|
||||
unstructuredClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error)
|
||||
includeUninitialized bool
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -74,7 +79,7 @@ var (
|
||||
All Kubernetes objects support the ability to store additional data with the object as
|
||||
annotations. Annotations are key/value pairs that can be larger than labels and include
|
||||
arbitrary string values such as structured JSON. Tools and system extensions may use
|
||||
annotations to store their own data.
|
||||
annotations to store their own data.
|
||||
|
||||
Attempting to set an annotation that already exists will fail unless --overwrite is set.
|
||||
If --resource-version is specified and does not match the current resource version on
|
||||
@ -123,13 +128,9 @@ func NewCmdAnnotate(parent string, f cmdutil.Factory, ioStreams genericclioption
|
||||
Long: annotateLong + "\n\n" + cmdutil.SuggestApiResources(parent),
|
||||
Example: annotateExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := o.Complete(f, cmd, args); err != nil {
|
||||
cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, "%v", err))
|
||||
}
|
||||
if err := o.Validate(); err != nil {
|
||||
cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, "%v", err))
|
||||
}
|
||||
cmdutil.CheckErr(o.RunAnnotate(f, cmd))
|
||||
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
||||
cmdutil.CheckErr(o.Validate())
|
||||
cmdutil.CheckErr(o.RunAnnotate())
|
||||
},
|
||||
ValidArgs: validArgs,
|
||||
ArgAliases: kubectl.ResourceAliases(validArgs),
|
||||
@ -176,6 +177,14 @@ func (o *AnnotateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [
|
||||
return printer.PrintObj(obj, out)
|
||||
}
|
||||
|
||||
o.namespace, o.enforceNamespace, err = f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.includeUninitialized = cmdutil.ShouldIncludeUninitialized(cmd, false)
|
||||
o.builder = f.NewBuilder()
|
||||
o.unstructuredClientForMapping = f.UnstructuredClientForMapping
|
||||
|
||||
// retrieves resource and annotation args from args
|
||||
// also checks args to verify that all resources are specified before annotations
|
||||
resources, annotationArgs, err := cmdutil.GetResourcesAndPairs(args, "annotation")
|
||||
@ -184,7 +193,11 @@ func (o *AnnotateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [
|
||||
}
|
||||
o.resources = resources
|
||||
o.newAnnotations, o.removeAnnotations, err = parseAnnotations(annotationArgs)
|
||||
return err
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate checks to the AnnotateOptions to see if there is sufficient information run the command.
|
||||
@ -202,20 +215,14 @@ func (o AnnotateOptions) Validate() error {
|
||||
}
|
||||
|
||||
// RunAnnotate does the work
|
||||
func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
namespace, enforceNamespace, err := f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false)
|
||||
b := f.NewBuilder().
|
||||
func (o AnnotateOptions) RunAnnotate() error {
|
||||
b := o.builder.
|
||||
Unstructured().
|
||||
LocalParam(o.local).
|
||||
ContinueOnError().
|
||||
NamespaceParam(namespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
IncludeUninitialized(includeUninitialized).
|
||||
NamespaceParam(o.namespace).DefaultNamespace().
|
||||
FilenameParam(o.enforceNamespace, &o.FilenameOptions).
|
||||
IncludeUninitialized(o.includeUninitialized).
|
||||
Flatten()
|
||||
|
||||
if !o.local {
|
||||
@ -276,7 +283,7 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro
|
||||
}
|
||||
|
||||
mapping := info.ResourceMapping()
|
||||
client, err := f.UnstructuredClientForMapping(mapping)
|
||||
client, err := o.unstructuredClientForMapping(mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -499,7 +499,7 @@ func TestAnnotateObject(t *testing.T) {
|
||||
if err := options.Validate(); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if err := options.RunAnnotate(tf, cmd); err != nil {
|
||||
if err := options.RunAnnotate(); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
@ -554,7 +554,7 @@ func TestAnnotateObjectFromFile(t *testing.T) {
|
||||
if err := options.Validate(); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if err := options.RunAnnotate(tf, cmd); err != nil {
|
||||
if err := options.RunAnnotate(); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
@ -586,7 +586,7 @@ func TestAnnotateLocal(t *testing.T) {
|
||||
if err := options.Validate(); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if err := options.RunAnnotate(tf, cmd); err != nil {
|
||||
if err := options.RunAnnotate(); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
@ -642,7 +642,7 @@ func TestAnnotateMultipleObjects(t *testing.T) {
|
||||
if err := options.Validate(); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
if err := options.RunAnnotate(tf, cmd); err != nil {
|
||||
if err := options.RunAnnotate(); err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
}
|
||||
|
@ -18,14 +18,15 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"sort"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/discovery"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
|
||||
)
|
||||
|
||||
@ -35,37 +36,54 @@ var (
|
||||
kubectl api-versions`))
|
||||
)
|
||||
|
||||
func NewCmdApiVersions(f cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
type ApiVersionsOptions struct {
|
||||
discoveryClient discovery.CachedDiscoveryInterface
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
|
||||
func NewApiVersionsOptions(ioStreams genericclioptions.IOStreams) *ApiVersionsOptions {
|
||||
return &ApiVersionsOptions{
|
||||
IOStreams: ioStreams,
|
||||
}
|
||||
}
|
||||
|
||||
func NewCmdApiVersions(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := NewApiVersionsOptions(ioStreams)
|
||||
cmd := &cobra.Command{
|
||||
Use: "api-versions",
|
||||
Short: "Print the supported API versions on the server, in the form of \"group/version\"",
|
||||
Long: "Print the supported API versions on the server, in the form of \"group/version\"",
|
||||
Example: apiversionsExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
err := RunApiVersions(f, out)
|
||||
cmdutil.CheckErr(err)
|
||||
cmdutil.CheckErr(o.Complete(f))
|
||||
cmdutil.CheckErr(o.RunApiVersions())
|
||||
},
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
|
||||
func RunApiVersions(f cmdutil.Factory, w io.Writer) error {
|
||||
discoveryclient, err := f.DiscoveryClient()
|
||||
func (o *ApiVersionsOptions) Complete(f cmdutil.Factory) error {
|
||||
var err error
|
||||
o.discoveryClient, err = f.DiscoveryClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *ApiVersionsOptions) RunApiVersions() error {
|
||||
// Always request fresh data from the server
|
||||
discoveryclient.Invalidate()
|
||||
o.discoveryClient.Invalidate()
|
||||
|
||||
groupList, err := discoveryclient.ServerGroups()
|
||||
groupList, err := o.discoveryClient.ServerGroups()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Couldn't get available api versions from server: %v\n", err)
|
||||
}
|
||||
apiVersions := metav1.ExtractGroupVersions(groupList)
|
||||
sort.Strings(apiVersions)
|
||||
for _, v := range apiVersions {
|
||||
fmt.Fprintln(w, v)
|
||||
fmt.Fprintln(o.Out, v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -18,19 +18,14 @@ package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
apijson "k8s.io/apimachinery/pkg/util/json"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
@ -39,21 +34,27 @@ import (
|
||||
"k8s.io/kubernetes/pkg/kubectl/resource"
|
||||
"k8s.io/kubernetes/pkg/kubectl/scheme"
|
||||
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
)
|
||||
|
||||
type SetLastAppliedOptions struct {
|
||||
FilenameOptions resource.FilenameOptions
|
||||
Selector string
|
||||
InfoList []*resource.Info
|
||||
Mapper meta.RESTMapper
|
||||
Namespace string
|
||||
EnforceNamespace bool
|
||||
DryRun bool
|
||||
ShortOutput bool
|
||||
CreateAnnotation bool
|
||||
Output string
|
||||
PatchBufferList []PatchBuffer
|
||||
Factory cmdutil.Factory
|
||||
|
||||
PrintFlags *printers.PrintFlags
|
||||
PrintObj printers.ResourcePrinterFunc
|
||||
|
||||
FilenameOptions resource.FilenameOptions
|
||||
|
||||
infoList []*resource.Info
|
||||
mapper meta.RESTMapper
|
||||
namespace string
|
||||
enforceNamespace bool
|
||||
dryRun bool
|
||||
shortOutput bool
|
||||
output string
|
||||
patchBufferList []PatchBuffer
|
||||
builder *resource.Builder
|
||||
unstructuredClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error)
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -83,12 +84,13 @@ var (
|
||||
|
||||
func NewSetLastAppliedOptions(ioStreams genericclioptions.IOStreams) *SetLastAppliedOptions {
|
||||
return &SetLastAppliedOptions{
|
||||
IOStreams: ioStreams,
|
||||
PrintFlags: printers.NewPrintFlags("configured"),
|
||||
IOStreams: ioStreams,
|
||||
}
|
||||
}
|
||||
|
||||
func NewCmdApplySetLastApplied(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
options := NewSetLastAppliedOptions(ioStreams)
|
||||
o := NewSetLastAppliedOptions(ioStreams)
|
||||
cmd := &cobra.Command{
|
||||
Use: "set-last-applied -f FILENAME",
|
||||
DisableFlagsInUseLine: true,
|
||||
@ -96,38 +98,55 @@ func NewCmdApplySetLastApplied(f cmdutil.Factory, ioStreams genericclioptions.IO
|
||||
Long: applySetLastAppliedLong,
|
||||
Example: applySetLastAppliedExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(options.Complete(f, cmd))
|
||||
cmdutil.CheckErr(options.Validate(f, cmd))
|
||||
cmdutil.CheckErr(options.RunSetLastApplied(f, cmd))
|
||||
cmdutil.CheckErr(o.Complete(f, cmd))
|
||||
cmdutil.CheckErr(o.Validate())
|
||||
cmdutil.CheckErr(o.RunSetLastApplied())
|
||||
},
|
||||
}
|
||||
|
||||
cmdutil.AddDryRunFlag(cmd)
|
||||
cmdutil.AddPrinterFlags(cmd)
|
||||
cmd.Flags().BoolVar(&options.CreateAnnotation, "create-annotation", options.CreateAnnotation, "Will create 'last-applied-configuration' annotations if current objects doesn't have one")
|
||||
usage := "that contains the last-applied-configuration annotations"
|
||||
kubectl.AddJsonFilenameFlag(cmd, &options.FilenameOptions.Filenames, "Filename, directory, or URL to files "+usage)
|
||||
cmd.Flags().BoolVar(&o.CreateAnnotation, "create-annotation", o.CreateAnnotation, "Will create 'last-applied-configuration' annotations if current objects doesn't have one")
|
||||
kubectl.AddJsonFilenameFlag(cmd, &o.FilenameOptions.Filenames, "Filename, directory, or URL to files that contains the last-applied-configuration annotations")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (o *SetLastAppliedOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
o.DryRun = cmdutil.GetDryRunFlag(cmd)
|
||||
o.Output = cmdutil.GetFlagString(cmd, "output")
|
||||
o.ShortOutput = o.Output == "name"
|
||||
|
||||
o.Mapper = f.RESTMapper()
|
||||
o.dryRun = cmdutil.GetDryRunFlag(cmd)
|
||||
o.output = cmdutil.GetFlagString(cmd, "output")
|
||||
o.shortOutput = o.output == "name"
|
||||
|
||||
o.mapper = f.RESTMapper()
|
||||
var err error
|
||||
o.Namespace, o.EnforceNamespace, err = f.DefaultNamespace()
|
||||
return err
|
||||
o.namespace, o.enforceNamespace, err = f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.builder = f.NewBuilder()
|
||||
o.unstructuredClientForMapping = f.UnstructuredClientForMapping
|
||||
|
||||
if o.dryRun {
|
||||
// TODO(juanvallejo): This can be cleaned up even further by creating
|
||||
// a PrintFlags struct that binds the --dry-run flag, and whose
|
||||
// ToPrinter method returns a printer that understands how to print
|
||||
// this success message.
|
||||
o.PrintFlags.Complete("%s (dry run)")
|
||||
}
|
||||
printer, err := o.PrintFlags.ToPrinter()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.PrintObj = printer.PrintObj
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *SetLastAppliedOptions) Validate(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
r := f.NewBuilder().
|
||||
func (o *SetLastAppliedOptions) Validate() error {
|
||||
r := o.builder.
|
||||
Unstructured().
|
||||
NamespaceParam(o.Namespace).DefaultNamespace().
|
||||
FilenameParam(o.EnforceNamespace, &o.FilenameOptions).
|
||||
NamespaceParam(o.namespace).DefaultNamespace().
|
||||
FilenameParam(o.enforceNamespace, &o.FilenameOptions).
|
||||
Flatten().
|
||||
Do()
|
||||
|
||||
@ -153,14 +172,14 @@ func (o *SetLastAppliedOptions) Validate(f cmdutil.Factory, cmd *cobra.Command)
|
||||
return cmdutil.AddSourceToErr(fmt.Sprintf("retrieving current configuration of:\n%s\nfrom server for:", info.String()), info.Source, err)
|
||||
}
|
||||
if originalBuf == nil && !o.CreateAnnotation {
|
||||
return cmdutil.UsageErrorf(cmd, "no last-applied-configuration annotation found on resource: %s, to create the annotation, run the command with --create-annotation", info.Name)
|
||||
return fmt.Errorf("no last-applied-configuration annotation found on resource: %s, to create the annotation, run the command with --create-annotation", info.Name)
|
||||
}
|
||||
|
||||
//only add to PatchBufferList when changed
|
||||
if !bytes.Equal(cmdutil.StripComments(originalBuf), cmdutil.StripComments(diffBuf)) {
|
||||
p := PatchBuffer{Patch: patchBuf, PatchType: patchType}
|
||||
o.PatchBufferList = append(o.PatchBufferList, p)
|
||||
o.InfoList = append(o.InfoList, info)
|
||||
o.patchBufferList = append(o.patchBufferList, p)
|
||||
o.infoList = append(o.infoList, info)
|
||||
} else {
|
||||
fmt.Fprintf(o.Out, "set-last-applied %s: no changes required.\n", info.Name)
|
||||
}
|
||||
@ -170,68 +189,25 @@ func (o *SetLastAppliedOptions) Validate(f cmdutil.Factory, cmd *cobra.Command)
|
||||
return err
|
||||
}
|
||||
|
||||
func (o *SetLastAppliedOptions) RunSetLastApplied(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
for i, patch := range o.PatchBufferList {
|
||||
info := o.InfoList[i]
|
||||
if !o.DryRun {
|
||||
func (o *SetLastAppliedOptions) RunSetLastApplied() error {
|
||||
for i, patch := range o.patchBufferList {
|
||||
info := o.infoList[i]
|
||||
if !o.dryRun {
|
||||
mapping := info.ResourceMapping()
|
||||
client, err := f.UnstructuredClientForMapping(mapping)
|
||||
client, err := o.unstructuredClientForMapping(mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
helper := resource.NewHelper(client, mapping)
|
||||
patchedObj, err := helper.Patch(o.Namespace, info.Name, patch.PatchType, patch.Patch)
|
||||
patchedObj, err := helper.Patch(o.namespace, info.Name, patch.PatchType, patch.Patch)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(o.Output) > 0 && !o.ShortOutput {
|
||||
info.Refresh(patchedObj, false)
|
||||
return cmdutil.PrintObject(cmd, info.Object, o.Out)
|
||||
}
|
||||
cmdutil.PrintSuccess(o.ShortOutput, o.Out, info.Object, o.DryRun, "configured")
|
||||
|
||||
} else {
|
||||
err := o.formatPrinter(o.Output, patch.Patch, o.Out)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cmdutil.PrintSuccess(o.ShortOutput, o.Out, info.Object, o.DryRun, "configured")
|
||||
info.Refresh(patchedObj, false)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *SetLastAppliedOptions) formatPrinter(output string, buf []byte, w io.Writer) error {
|
||||
yamlOutput, err := yaml.JSONToYAML(buf)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
switch output {
|
||||
case "json":
|
||||
jsonBuffer := &bytes.Buffer{}
|
||||
err = json.Indent(jsonBuffer, buf, "", " ")
|
||||
if err != nil {
|
||||
if err := o.PrintObj(info.AsVersioned(legacyscheme.Scheme), o.Out); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintf(w, "%s\n", jsonBuffer.String())
|
||||
case "yaml":
|
||||
fmt.Fprintf(w, "%s\n", string(yamlOutput))
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *SetLastAppliedOptions) getPatch(info *resource.Info) ([]byte, []byte, error) {
|
||||
objMap := map[string]map[string]map[string]string{}
|
||||
metadataMap := map[string]map[string]string{}
|
||||
annotationsMap := map[string]string{}
|
||||
localFile, err := runtime.Encode(scheme.DefaultJSONEncoder(), info.Object)
|
||||
if err != nil {
|
||||
return nil, localFile, err
|
||||
}
|
||||
annotationsMap[api.LastAppliedConfigAnnotation] = string(localFile)
|
||||
metadataMap["annotations"] = annotationsMap
|
||||
objMap["metadata"] = metadataMap
|
||||
jsonString, err := apijson.Marshal(objMap)
|
||||
return jsonString, localFile, err
|
||||
}
|
||||
|
@ -1121,7 +1121,7 @@ func TestRunApplySetLastApplied(t *testing.T) {
|
||||
name: "set with exist object",
|
||||
filePath: filenameRC,
|
||||
expectedErr: "",
|
||||
expectedOut: "replicationcontroller/test-rc\n",
|
||||
expectedOut: "replicationcontroller/test-rc configured\n",
|
||||
output: "name",
|
||||
},
|
||||
{
|
||||
@ -1134,7 +1134,7 @@ func TestRunApplySetLastApplied(t *testing.T) {
|
||||
{
|
||||
name: "set for the annotation does not exist on the live object",
|
||||
filePath: filenameRCNoAnnotation,
|
||||
expectedErr: "error: no last-applied-configuration annotation found on resource: no-annotation, to create the annotation, run the command with --create-annotation\nSee 'set-last-applied -h' for help and examples.",
|
||||
expectedErr: "error: no last-applied-configuration annotation found on resource: no-annotation, to create the annotation, run the command with --create-annotation",
|
||||
expectedOut: "",
|
||||
output: "name",
|
||||
},
|
||||
@ -1142,14 +1142,14 @@ func TestRunApplySetLastApplied(t *testing.T) {
|
||||
name: "set with exist object output json",
|
||||
filePath: filenameRCJSON,
|
||||
expectedErr: "",
|
||||
expectedOut: "replicationcontroller/test-rc\n",
|
||||
expectedOut: "replicationcontroller/test-rc configured\n",
|
||||
output: "name",
|
||||
},
|
||||
{
|
||||
name: "set test for a directory of files",
|
||||
filePath: dirName,
|
||||
expectedErr: "",
|
||||
expectedOut: "replicationcontroller/test-rc\nreplicationcontroller/test-rc\n",
|
||||
expectedOut: "replicationcontroller/test-rc configured\nreplicationcontroller/test-rc configured\n",
|
||||
output: "name",
|
||||
},
|
||||
}
|
||||
|
@ -24,7 +24,6 @@ import (
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/kubectl"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
@ -59,20 +58,22 @@ type AutoscaleOptions struct {
|
||||
PrintFlags *printers.PrintFlags
|
||||
ToPrinter func(string) (printers.ResourcePrinterFunc, error)
|
||||
|
||||
Builder *resource.Builder
|
||||
CanBeAutoscaled func(kind schema.GroupKind) error
|
||||
Name string
|
||||
Generator string
|
||||
Min int32
|
||||
Max int32
|
||||
CpuPercent int32
|
||||
|
||||
CreateAnnotation bool
|
||||
DryRun bool
|
||||
EnforceNamespace bool
|
||||
|
||||
Mapper meta.RESTMapper
|
||||
ClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error)
|
||||
|
||||
GeneratorFunc func(string, *meta.RESTMapping) (kubectl.StructuredGenerator, error)
|
||||
|
||||
Namespace string
|
||||
BuilderArgs []string
|
||||
createAnnotation bool
|
||||
args []string
|
||||
enforceNamespace bool
|
||||
namespace string
|
||||
dryRun bool
|
||||
builder *resource.Builder
|
||||
mapper meta.RESTMapper
|
||||
canBeAutoscaled func(kind schema.GroupKind) error
|
||||
clientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error)
|
||||
generatorFunc func(string, *meta.RESTMapping) (kubectl.StructuredGenerator, error)
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -102,7 +103,7 @@ func NewCmdAutoscale(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *
|
||||
Example: autoscaleExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
||||
cmdutil.CheckErr(o.Validate(cmd))
|
||||
cmdutil.CheckErr(o.Validate())
|
||||
cmdutil.CheckErr(o.Run())
|
||||
},
|
||||
ValidArgs: validArgs,
|
||||
@ -113,27 +114,26 @@ func NewCmdAutoscale(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *
|
||||
o.RecordFlags.AddFlags(cmd)
|
||||
o.PrintFlags.AddFlags(cmd)
|
||||
|
||||
cmd.Flags().String("generator", cmdutil.HorizontalPodAutoscalerV1GeneratorName, i18n.T("The name of the API generator to use. Currently there is only 1 generator."))
|
||||
cmd.Flags().Int32("min", -1, "The lower limit for the number of pods that can be set by the autoscaler. If it's not specified or negative, the server will apply a default value.")
|
||||
cmd.Flags().Int32("max", -1, "The upper limit for the number of pods that can be set by the autoscaler. Required.")
|
||||
cmd.Flags().StringVar(&o.Generator, "generator", cmdutil.HorizontalPodAutoscalerV1GeneratorName, i18n.T("The name of the API generator to use. Currently there is only 1 generator."))
|
||||
cmd.Flags().Int32Var(&o.Min, "min", -1, "The lower limit for the number of pods that can be set by the autoscaler. If it's not specified or negative, the server will apply a default value.")
|
||||
cmd.Flags().Int32Var(&o.Max, "max", -1, "The upper limit for the number of pods that can be set by the autoscaler. Required.")
|
||||
cmd.MarkFlagRequired("max")
|
||||
cmd.Flags().Int32("cpu-percent", -1, fmt.Sprintf("The target average CPU utilization (represented as a percent of requested CPU) over all the pods. If it's not specified or negative, a default autoscaling policy will be used."))
|
||||
cmd.Flags().String("name", "", i18n.T("The name for the newly created object. If not specified, the name of the input resource will be used."))
|
||||
cmd.Flags().Int32Var(&o.CpuPercent, "cpu-percent", -1, fmt.Sprintf("The target average CPU utilization (represented as a percent of requested CPU) over all the pods. If it's not specified or negative, a default autoscaling policy will be used."))
|
||||
cmd.Flags().StringVar(&o.Name, "name", "", i18n.T("The name for the newly created object. If not specified, the name of the input resource will be used."))
|
||||
cmdutil.AddDryRunFlag(cmd)
|
||||
usage := "identifying the resource to autoscale."
|
||||
cmdutil.AddFilenameOptionFlags(cmd, o.FilenameOptions, usage)
|
||||
cmdutil.AddFilenameOptionFlags(cmd, o.FilenameOptions, "identifying the resource to autoscale.")
|
||||
cmdutil.AddApplyAnnotationFlags(cmd)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (o *AutoscaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
|
||||
o.DryRun = cmdutil.GetFlagBool(cmd, "dry-run")
|
||||
o.CreateAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
|
||||
o.Builder = f.NewBuilder()
|
||||
o.CanBeAutoscaled = f.CanBeAutoscaled
|
||||
o.Mapper = f.RESTMapper()
|
||||
o.ClientForMapping = f.ClientForMapping
|
||||
o.BuilderArgs = args
|
||||
o.dryRun = cmdutil.GetFlagBool(cmd, "dry-run")
|
||||
o.createAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
|
||||
o.builder = f.NewBuilder()
|
||||
o.canBeAutoscaled = f.CanBeAutoscaled
|
||||
o.mapper = f.RESTMapper()
|
||||
o.clientForMapping = f.ClientForMapping
|
||||
o.args = args
|
||||
o.RecordFlags.Complete(f.Command(cmd, false))
|
||||
|
||||
var err error
|
||||
@ -143,34 +143,31 @@ func (o *AutoscaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
|
||||
}
|
||||
|
||||
// get the generator
|
||||
o.GeneratorFunc = func(name string, mapping *meta.RESTMapping) (kubectl.StructuredGenerator, error) {
|
||||
var generator kubectl.StructuredGenerator
|
||||
switch generatorName := cmdutil.GetFlagString(cmd, "generator"); generatorName {
|
||||
o.generatorFunc = func(name string, mapping *meta.RESTMapping) (kubectl.StructuredGenerator, error) {
|
||||
switch o.Generator {
|
||||
case cmdutil.HorizontalPodAutoscalerV1GeneratorName:
|
||||
generator = &kubectl.HorizontalPodAutoscalerGeneratorV1{
|
||||
return &kubectl.HorizontalPodAutoscalerGeneratorV1{
|
||||
Name: name,
|
||||
MinReplicas: cmdutil.GetFlagInt32(cmd, "min"),
|
||||
MaxReplicas: cmdutil.GetFlagInt32(cmd, "max"),
|
||||
CPUPercent: cmdutil.GetFlagInt32(cmd, "cpu-percent"),
|
||||
MinReplicas: o.Min,
|
||||
MaxReplicas: o.Max,
|
||||
CPUPercent: o.CpuPercent,
|
||||
ScaleRefName: name,
|
||||
ScaleRefKind: mapping.GroupVersionKind.Kind,
|
||||
ScaleRefApiVersion: mapping.GroupVersionKind.GroupVersion().String(),
|
||||
}
|
||||
}, nil
|
||||
default:
|
||||
return nil, cmdutil.UsageErrorf(cmd, "Generator %s not supported. ", generatorName)
|
||||
return nil, cmdutil.UsageErrorf(cmd, "Generator %s not supported. ", o.Generator)
|
||||
}
|
||||
|
||||
return generator, nil
|
||||
}
|
||||
|
||||
o.Namespace, o.EnforceNamespace, err = f.DefaultNamespace()
|
||||
o.namespace, o.enforceNamespace, err = f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.ToPrinter = func(operation string) (printers.ResourcePrinterFunc, error) {
|
||||
o.PrintFlags.NamePrintFlags.Operation = operation
|
||||
if o.DryRun {
|
||||
if o.dryRun {
|
||||
o.PrintFlags.Complete("%s (dry run)")
|
||||
}
|
||||
|
||||
@ -185,21 +182,24 @@ func (o *AutoscaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *AutoscaleOptions) Validate(cmd *cobra.Command) error {
|
||||
if err := validateFlags(cmd); err != nil {
|
||||
return err
|
||||
func (o *AutoscaleOptions) Validate() error {
|
||||
if o.Max < 1 {
|
||||
return fmt.Errorf("--max=MAXPODS is required and must be at least 1, max: %d", o.Max)
|
||||
}
|
||||
if o.Max < o.Min {
|
||||
return fmt.Errorf("--max=MAXPODS must be larger or equal to --min=MINPODS, max: %d, min: %d", o.Max, o.Min)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *AutoscaleOptions) Run() error {
|
||||
r := o.Builder.
|
||||
r := o.builder.
|
||||
Internal(legacyscheme.Scheme).
|
||||
ContinueOnError().
|
||||
NamespaceParam(o.Namespace).DefaultNamespace().
|
||||
FilenameParam(o.EnforceNamespace, o.FilenameOptions).
|
||||
ResourceTypeOrNameArgs(false, o.BuilderArgs...).
|
||||
NamespaceParam(o.namespace).DefaultNamespace().
|
||||
FilenameParam(o.enforceNamespace, o.FilenameOptions).
|
||||
ResourceTypeOrNameArgs(false, o.args...).
|
||||
Flatten().
|
||||
Do()
|
||||
if err := r.Err(); err != nil {
|
||||
@ -213,11 +213,11 @@ func (o *AutoscaleOptions) Run() error {
|
||||
}
|
||||
|
||||
mapping := info.ResourceMapping()
|
||||
if err := o.CanBeAutoscaled(mapping.GroupVersionKind.GroupKind()); err != nil {
|
||||
if err := o.canBeAutoscaled(mapping.GroupVersionKind.GroupKind()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
generator, err := o.GeneratorFunc(info.Name, mapping)
|
||||
generator, err := o.generatorFunc(info.Name, mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -229,8 +229,8 @@ func (o *AutoscaleOptions) Run() error {
|
||||
}
|
||||
|
||||
resourceMapper := &resource.Mapper{
|
||||
RESTMapper: o.Mapper,
|
||||
ClientMapper: resource.ClientMapperFunc(o.ClientForMapping),
|
||||
RESTMapper: o.mapper,
|
||||
ClientMapper: resource.ClientMapperFunc(o.clientForMapping),
|
||||
Decoder: cmdutil.InternalVersionDecoder(),
|
||||
}
|
||||
hpa, err := resourceMapper.InfoForObject(object, legacyscheme.Scheme, nil)
|
||||
@ -242,7 +242,7 @@ func (o *AutoscaleOptions) Run() error {
|
||||
}
|
||||
object = hpa.Object
|
||||
|
||||
if o.DryRun {
|
||||
if o.dryRun {
|
||||
count++
|
||||
|
||||
printer, err := o.ToPrinter("created")
|
||||
@ -252,11 +252,11 @@ func (o *AutoscaleOptions) Run() error {
|
||||
return printer.PrintObj(hpa.AsVersioned(legacyscheme.Scheme), o.Out)
|
||||
}
|
||||
|
||||
if err := kubectl.CreateOrUpdateAnnotation(o.CreateAnnotation, hpa.Object, cmdutil.InternalVersionJSONEncoder()); err != nil {
|
||||
if err := kubectl.CreateOrUpdateAnnotation(o.createAnnotation, hpa.Object, cmdutil.InternalVersionJSONEncoder()); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err = resource.NewHelper(hpa.Client, hpa.Mapping).Create(o.Namespace, false, object)
|
||||
_, err = resource.NewHelper(hpa.Client, hpa.Mapping).Create(o.namespace, false, object)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -276,15 +276,3 @@ func (o *AutoscaleOptions) Run() error {
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func validateFlags(cmd *cobra.Command) error {
|
||||
errs := []error{}
|
||||
max, min := cmdutil.GetFlagInt32(cmd, "max"), cmdutil.GetFlagInt32(cmd, "min")
|
||||
if max < 1 {
|
||||
errs = append(errs, fmt.Errorf("--max=MAXPODS is required and must be at least 1, max: %d", max))
|
||||
}
|
||||
if max < min {
|
||||
errs = append(errs, fmt.Errorf("--max=MAXPODS must be larger or equal to --min=MINPODS, max: %d, min: %d", max, min))
|
||||
}
|
||||
return utilerrors.NewAggregate(errs)
|
||||
}
|
||||
|
@ -21,11 +21,15 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
"k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
@ -37,6 +41,15 @@ type ClusterInfoDumpOptions struct {
|
||||
PrintFlags *printers.PrintFlags
|
||||
PrintObj printers.ResourcePrinterFunc
|
||||
|
||||
OutputDir string
|
||||
AllNamespaces bool
|
||||
Namespaces []string
|
||||
|
||||
timeout time.Duration
|
||||
clientset internalclientset.Interface
|
||||
namespace string
|
||||
logsForObject func(object, options runtime.Object, timeout time.Duration) (*restclient.Request, error)
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
|
||||
@ -54,13 +67,13 @@ func NewCmdClusterInfoDump(f cmdutil.Factory, ioStreams genericclioptions.IOStre
|
||||
Long: dumpLong,
|
||||
Example: dumpExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(o.Complete())
|
||||
cmdutil.CheckErr(o.Run(f, cmd))
|
||||
cmdutil.CheckErr(o.Complete(f, cmd))
|
||||
cmdutil.CheckErr(o.Run())
|
||||
},
|
||||
}
|
||||
cmd.Flags().String("output-directory", "", i18n.T("Where to output the files. If empty or '-' uses stdout, otherwise creates a directory hierarchy in that directory"))
|
||||
cmd.Flags().StringSlice("namespaces", []string{}, "A comma separated list of namespaces to dump.")
|
||||
cmd.Flags().Bool("all-namespaces", false, "If true, dump all namespaces. If true, --namespaces is ignored.")
|
||||
cmd.Flags().StringVar(&o.OutputDir, "output-directory", "", i18n.T("Where to output the files. If empty or '-' uses stdout, otherwise creates a directory hierarchy in that directory"))
|
||||
cmd.Flags().StringSliceVar(&o.Namespaces, "namespaces", []string{}, "A comma separated list of namespaces to dump.")
|
||||
cmd.Flags().BoolVar(&o.AllNamespaces, "all-namespaces", false, "If true, dump all namespaces. If true, --namespaces is ignored.")
|
||||
cmdutil.AddPodRunningTimeoutFlag(cmd, defaultPodLogsTimeout)
|
||||
return cmd
|
||||
}
|
||||
@ -89,8 +102,7 @@ var (
|
||||
kubectl cluster-info dump --namespaces default,kube-system --output-directory=/path/to/cluster-state`))
|
||||
)
|
||||
|
||||
func setupOutputWriter(cmd *cobra.Command, defaultWriter io.Writer, filename string) io.Writer {
|
||||
dir := cmdutil.GetFlagString(cmd, "output-directory")
|
||||
func setupOutputWriter(dir string, defaultWriter io.Writer, filename string) io.Writer {
|
||||
if len(dir) == 0 || dir == "-" {
|
||||
return defaultWriter
|
||||
}
|
||||
@ -103,7 +115,7 @@ func setupOutputWriter(cmd *cobra.Command, defaultWriter io.Writer, filename str
|
||||
return file
|
||||
}
|
||||
|
||||
func (o *ClusterInfoDumpOptions) Complete() error {
|
||||
func (o *ClusterInfoDumpOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
printer, err := o.PrintFlags.ToPrinter()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -113,32 +125,36 @@ func (o *ClusterInfoDumpOptions) Complete() error {
|
||||
o.PrintFlags.OutputFormat = &jsonOutputFmt
|
||||
o.PrintObj = printer.PrintObj
|
||||
|
||||
o.timeout, err = cmdutil.GetPodRunningTimeoutFlag(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.clientset, err = f.ClientSet()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.namespace, _, err = f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.logsForObject = f.LogsForObject
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *ClusterInfoDumpOptions) Run(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
timeout, err := cmdutil.GetPodRunningTimeoutFlag(cmd)
|
||||
if err != nil {
|
||||
return cmdutil.UsageErrorf(cmd, err.Error())
|
||||
}
|
||||
|
||||
clientset, err := f.ClientSet()
|
||||
func (o *ClusterInfoDumpOptions) Run() error {
|
||||
nodes, err := o.clientset.Core().Nodes().List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
nodes, err := clientset.Core().Nodes().List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := o.PrintObj(nodes, setupOutputWriter(cmd, o.Out, "nodes.json")); err != nil {
|
||||
if err := o.PrintObj(nodes, setupOutputWriter(o.OutputDir, o.Out, "nodes.json")); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var namespaces []string
|
||||
if cmdutil.GetFlagBool(cmd, "all-namespaces") {
|
||||
namespaceList, err := clientset.Core().Namespaces().List(metav1.ListOptions{})
|
||||
if o.AllNamespaces {
|
||||
namespaceList, err := o.clientset.Core().Namespaces().List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -146,75 +162,70 @@ func (o *ClusterInfoDumpOptions) Run(f cmdutil.Factory, cmd *cobra.Command) erro
|
||||
namespaces = append(namespaces, namespaceList.Items[ix].Name)
|
||||
}
|
||||
} else {
|
||||
namespaces = cmdutil.GetFlagStringSlice(cmd, "namespaces")
|
||||
if len(namespaces) == 0 {
|
||||
cmdNamespace, _, err := f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if len(o.Namespaces) == 0 {
|
||||
namespaces = []string{
|
||||
metav1.NamespaceSystem,
|
||||
cmdNamespace,
|
||||
o.namespace,
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, namespace := range namespaces {
|
||||
// TODO: this is repetitive in the extreme. Use reflection or
|
||||
// something to make this a for loop.
|
||||
events, err := clientset.Core().Events(namespace).List(metav1.ListOptions{})
|
||||
events, err := o.clientset.Core().Events(namespace).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.PrintObj(events, setupOutputWriter(cmd, o.Out, path.Join(namespace, "events.json"))); err != nil {
|
||||
if err := o.PrintObj(events, setupOutputWriter(o.OutputDir, o.Out, path.Join(namespace, "events.json"))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rcs, err := clientset.Core().ReplicationControllers(namespace).List(metav1.ListOptions{})
|
||||
rcs, err := o.clientset.Core().ReplicationControllers(namespace).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.PrintObj(rcs, setupOutputWriter(cmd, o.Out, path.Join(namespace, "replication-controllers.json"))); err != nil {
|
||||
if err := o.PrintObj(rcs, setupOutputWriter(o.OutputDir, o.Out, path.Join(namespace, "replication-controllers.json"))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
svcs, err := clientset.Core().Services(namespace).List(metav1.ListOptions{})
|
||||
svcs, err := o.clientset.Core().Services(namespace).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.PrintObj(svcs, setupOutputWriter(cmd, o.Out, path.Join(namespace, "services.json"))); err != nil {
|
||||
if err := o.PrintObj(svcs, setupOutputWriter(o.OutputDir, o.Out, path.Join(namespace, "services.json"))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
sets, err := clientset.Extensions().DaemonSets(namespace).List(metav1.ListOptions{})
|
||||
sets, err := o.clientset.Extensions().DaemonSets(namespace).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.PrintObj(sets, setupOutputWriter(cmd, o.Out, path.Join(namespace, "daemonsets.json"))); err != nil {
|
||||
if err := o.PrintObj(sets, setupOutputWriter(o.OutputDir, o.Out, path.Join(namespace, "daemonsets.json"))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
deps, err := clientset.Extensions().Deployments(namespace).List(metav1.ListOptions{})
|
||||
deps, err := o.clientset.Extensions().Deployments(namespace).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.PrintObj(deps, setupOutputWriter(cmd, o.Out, path.Join(namespace, "deployments.json"))); err != nil {
|
||||
if err := o.PrintObj(deps, setupOutputWriter(o.OutputDir, o.Out, path.Join(namespace, "deployments.json"))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
rps, err := clientset.Extensions().ReplicaSets(namespace).List(metav1.ListOptions{})
|
||||
rps, err := o.clientset.Extensions().ReplicaSets(namespace).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := o.PrintObj(rps, setupOutputWriter(cmd, o.Out, path.Join(namespace, "replicasets.json"))); err != nil {
|
||||
if err := o.PrintObj(rps, setupOutputWriter(o.OutputDir, o.Out, path.Join(namespace, "replicasets.json"))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
pods, err := clientset.Core().Pods(namespace).List(metav1.ListOptions{})
|
||||
pods, err := o.clientset.Core().Pods(namespace).List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := o.PrintObj(pods, setupOutputWriter(cmd, o.Out, path.Join(namespace, "pods.json"))); err != nil {
|
||||
if err := o.PrintObj(pods, setupOutputWriter(o.OutputDir, o.Out, path.Join(namespace, "pods.json"))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@ -222,7 +233,7 @@ func (o *ClusterInfoDumpOptions) Run(f cmdutil.Factory, cmd *cobra.Command) erro
|
||||
writer.Write([]byte(fmt.Sprintf("==== START logs for container %s of pod %s/%s ====\n", container.Name, pod.Namespace, pod.Name)))
|
||||
defer writer.Write([]byte(fmt.Sprintf("==== END logs for container %s of pod %s/%s ====\n", container.Name, pod.Namespace, pod.Name)))
|
||||
|
||||
request, err := f.LogsForObject(pod, &api.PodLogOptions{Container: container.Name}, timeout)
|
||||
request, err := o.logsForObject(pod, &api.PodLogOptions{Container: container.Name}, timeout)
|
||||
if err != nil {
|
||||
// Print error and return.
|
||||
writer.Write([]byte(fmt.Sprintf("Create log request error: %s\n", err.Error())))
|
||||
@ -241,19 +252,15 @@ func (o *ClusterInfoDumpOptions) Run(f cmdutil.Factory, cmd *cobra.Command) erro
|
||||
for ix := range pods.Items {
|
||||
pod := &pods.Items[ix]
|
||||
containers := pod.Spec.Containers
|
||||
writer := setupOutputWriter(cmd, o.Out, path.Join(namespace, pod.Name, "logs.txt"))
|
||||
writer := setupOutputWriter(o.OutputDir, o.Out, path.Join(namespace, pod.Name, "logs.txt"))
|
||||
|
||||
for i := range containers {
|
||||
printContainer(writer, containers[i], pod)
|
||||
}
|
||||
}
|
||||
}
|
||||
dir := cmdutil.GetFlagString(cmd, "output-directory")
|
||||
if len(dir) == 0 {
|
||||
dir = "standard output"
|
||||
}
|
||||
if dir != "-" {
|
||||
fmt.Fprintf(o.Out, "Cluster info dumped to %s\n", dir)
|
||||
if o.OutputDir != "-" {
|
||||
fmt.Fprintf(o.Out, "Cluster info dumped to %s\n", o.OutputDir)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
@ -33,9 +33,7 @@ func TestSetupOutputWriterNoOp(t *testing.T) {
|
||||
f := cmdtesting.NewTestFactory()
|
||||
defer f.Cleanup()
|
||||
|
||||
cmd := NewCmdClusterInfoDump(f, genericclioptions.NewTestIOStreamsDiscard())
|
||||
cmd.Flag("output-directory").Value.Set(test)
|
||||
writer := setupOutputWriter(cmd, buf, "/some/file/that/should/be/ignored")
|
||||
writer := setupOutputWriter(test, buf, "/some/file/that/should/be/ignored")
|
||||
if writer != buf {
|
||||
t.Errorf("expected: %v, saw: %v", buf, writer)
|
||||
}
|
||||
@ -55,9 +53,7 @@ func TestSetupOutputWriterFile(t *testing.T) {
|
||||
f := cmdtesting.NewTestFactory()
|
||||
defer f.Cleanup()
|
||||
|
||||
cmd := NewCmdClusterInfoDump(f, genericclioptions.NewTestIOStreamsDiscard())
|
||||
cmd.Flag("output-directory").Value.Set(dir)
|
||||
writer := setupOutputWriter(cmd, buf, file)
|
||||
writer := setupOutputWriter(dir, buf, file)
|
||||
if writer == buf {
|
||||
t.Errorf("expected: %v, saw: %v", buf, writer)
|
||||
}
|
||||
|
@ -308,7 +308,7 @@ func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob
|
||||
Message: "Advanced Commands:",
|
||||
Commands: []*cobra.Command{
|
||||
NewCmdApply("kubectl", f, ioStreams),
|
||||
NewCmdPatch(f, out),
|
||||
NewCmdPatch(f, ioStreams),
|
||||
NewCmdReplace(f, out, err),
|
||||
NewCmdConvert(f, ioStreams),
|
||||
},
|
||||
@ -349,8 +349,8 @@ func NewKubectlCommand(f cmdutil.Factory, in io.Reader, out, err io.Writer) *cob
|
||||
cmds.AddCommand(alpha)
|
||||
cmds.AddCommand(cmdconfig.NewCmdConfig(f, clientcmd.NewDefaultPathOptions(), out, err))
|
||||
cmds.AddCommand(NewCmdPlugin(f, in, out, err))
|
||||
cmds.AddCommand(NewCmdVersion(f, out))
|
||||
cmds.AddCommand(NewCmdApiVersions(f, out))
|
||||
cmds.AddCommand(NewCmdVersion(f, ioStreams))
|
||||
cmds.AddCommand(NewCmdApiVersions(f, ioStreams))
|
||||
cmds.AddCommand(NewCmdApiResources(f, ioStreams))
|
||||
cmds.AddCommand(NewCmdOptions(out))
|
||||
|
||||
|
@ -68,6 +68,12 @@ type LabelOptions struct {
|
||||
|
||||
Recorder genericclioptions.Recorder
|
||||
|
||||
namespace string
|
||||
enforceNamespace bool
|
||||
includeUninitialized bool
|
||||
builder *resource.Builder
|
||||
unstructuredClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error)
|
||||
|
||||
// Common shared fields
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -125,13 +131,9 @@ func NewCmdLabel(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobr
|
||||
Long: fmt.Sprintf(labelLong, validation.LabelValueMaxLength),
|
||||
Example: labelExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := o.Complete(f, cmd, args); err != nil {
|
||||
cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, err.Error()))
|
||||
}
|
||||
if err := o.Validate(); err != nil {
|
||||
cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, err.Error()))
|
||||
}
|
||||
cmdutil.CheckErr(o.RunLabel(f, cmd))
|
||||
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
||||
cmdutil.CheckErr(o.Validate())
|
||||
cmdutil.CheckErr(o.RunLabel())
|
||||
},
|
||||
ValidArgs: validArgs,
|
||||
ArgAliases: kubectl.ResourceAliases(validArgs),
|
||||
@ -188,10 +190,18 @@ func (o *LabelOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
|
||||
o.newLabels, o.removeLabels, err = parseLabels(labelArgs)
|
||||
|
||||
if o.list && len(o.outputFormat) > 0 {
|
||||
return cmdutil.UsageErrorf(cmd, "--list and --output may not be specified together")
|
||||
return fmt.Errorf("--list and --output may not be specified together")
|
||||
}
|
||||
|
||||
return err
|
||||
o.namespace, o.enforceNamespace, err = f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.includeUninitialized = cmdutil.ShouldIncludeUninitialized(cmd, false)
|
||||
o.builder = f.NewBuilder()
|
||||
o.unstructuredClientForMapping = f.UnstructuredClientForMapping
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Validate checks to the LabelOptions to see if there is sufficient information run the command.
|
||||
@ -209,20 +219,14 @@ func (o *LabelOptions) Validate() error {
|
||||
}
|
||||
|
||||
// RunLabel does the work
|
||||
func (o *LabelOptions) RunLabel(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false)
|
||||
b := f.NewBuilder().
|
||||
func (o *LabelOptions) RunLabel() error {
|
||||
b := o.builder.
|
||||
Unstructured().
|
||||
LocalParam(o.local).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
IncludeUninitialized(includeUninitialized).
|
||||
NamespaceParam(o.namespace).DefaultNamespace().
|
||||
FilenameParam(o.enforceNamespace, &o.FilenameOptions).
|
||||
IncludeUninitialized(o.includeUninitialized).
|
||||
Flatten()
|
||||
|
||||
if !o.local {
|
||||
@ -294,7 +298,7 @@ func (o *LabelOptions) RunLabel(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
}
|
||||
|
||||
mapping := info.ResourceMapping()
|
||||
client, err := f.UnstructuredClientForMapping(mapping)
|
||||
client, err := o.unstructuredClientForMapping(mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -342,7 +342,7 @@ func TestLabelErrors(t *testing.T) {
|
||||
err = opts.Validate()
|
||||
}
|
||||
if err == nil {
|
||||
err = opts.RunLabel(tf, cmd)
|
||||
err = opts.RunLabel()
|
||||
}
|
||||
if !testCase.errFn(err) {
|
||||
t.Errorf("%s: unexpected error: %v", k, err)
|
||||
@ -400,7 +400,7 @@ func TestLabelForResourceFromFile(t *testing.T) {
|
||||
err = opts.Validate()
|
||||
}
|
||||
if err == nil {
|
||||
err = opts.RunLabel(tf, cmd)
|
||||
err = opts.RunLabel()
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
@ -434,7 +434,7 @@ func TestLabelLocal(t *testing.T) {
|
||||
err = opts.Validate()
|
||||
}
|
||||
if err == nil {
|
||||
err = opts.RunLabel(tf, cmd)
|
||||
err = opts.RunLabel()
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
@ -491,7 +491,7 @@ func TestLabelMultipleObjects(t *testing.T) {
|
||||
err = opts.Validate()
|
||||
}
|
||||
if err == nil {
|
||||
err = opts.RunLabel(tf, cmd)
|
||||
err = opts.RunLabel()
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
|
@ -18,7 +18,6 @@ package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
@ -26,6 +25,7 @@ import (
|
||||
"github.com/golang/glog"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
@ -49,16 +49,25 @@ var patchTypes = map[string]types.PatchType{"json": types.JSONPatchType, "merge"
|
||||
// referencing the cmd.Flags()
|
||||
type PatchOptions struct {
|
||||
resource.FilenameOptions
|
||||
|
||||
RecordFlags *genericclioptions.RecordFlags
|
||||
PrintFlags *printers.PrintFlags
|
||||
ToPrinter func(string) (printers.ResourcePrinterFunc, error)
|
||||
Recorder genericclioptions.Recorder
|
||||
|
||||
Local bool
|
||||
DryRun bool
|
||||
Local bool
|
||||
PatchType string
|
||||
Patch string
|
||||
|
||||
Recorder genericclioptions.Recorder
|
||||
namespace string
|
||||
enforceNamespace bool
|
||||
dryRun bool
|
||||
outputFormat string
|
||||
args []string
|
||||
builder *resource.Builder
|
||||
unstructuredClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error)
|
||||
|
||||
OutputFormat string
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
|
||||
var (
|
||||
@ -86,16 +95,17 @@ var (
|
||||
kubectl patch pod valid-pod --type='json' -p='[{"op": "replace", "path": "/spec/containers/0/image", "value":"new image"}]'`))
|
||||
)
|
||||
|
||||
func NewPatchOptions() *PatchOptions {
|
||||
func NewPatchOptions(ioStreams genericclioptions.IOStreams) *PatchOptions {
|
||||
return &PatchOptions{
|
||||
RecordFlags: genericclioptions.NewRecordFlags(),
|
||||
Recorder: genericclioptions.NoopRecorder{},
|
||||
PrintFlags: printers.NewPrintFlags("patched"),
|
||||
IOStreams: ioStreams,
|
||||
}
|
||||
}
|
||||
|
||||
func NewCmdPatch(f cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
o := NewPatchOptions()
|
||||
func NewCmdPatch(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := NewPatchOptions(ioStreams)
|
||||
validArgs := cmdutil.ValidArgList(f)
|
||||
|
||||
cmd := &cobra.Command{
|
||||
@ -105,8 +115,9 @@ func NewCmdPatch(f cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
Long: patchLong,
|
||||
Example: patchExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(o.Complete(f, cmd))
|
||||
cmdutil.CheckErr(o.RunPatch(f, out, cmd, args))
|
||||
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
||||
cmdutil.CheckErr(o.Validate())
|
||||
cmdutil.CheckErr(o.RunPatch())
|
||||
},
|
||||
ValidArgs: validArgs,
|
||||
ArgAliases: kubectl.ResourceAliases(validArgs),
|
||||
@ -115,34 +126,30 @@ func NewCmdPatch(f cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
o.RecordFlags.AddFlags(cmd)
|
||||
o.PrintFlags.AddFlags(cmd)
|
||||
|
||||
cmd.Flags().StringP("patch", "p", "", "The patch to be applied to the resource JSON file.")
|
||||
cmd.Flags().StringVarP(&o.Patch, "patch", "p", "", "The patch to be applied to the resource JSON file.")
|
||||
cmd.MarkFlagRequired("patch")
|
||||
cmd.Flags().String("type", "strategic", fmt.Sprintf("The type of patch being provided; one of %v", sets.StringKeySet(patchTypes).List()))
|
||||
cmd.Flags().StringVar(&o.PatchType, "type", "strategic", fmt.Sprintf("The type of patch being provided; one of %v", sets.StringKeySet(patchTypes).List()))
|
||||
cmdutil.AddDryRunFlag(cmd)
|
||||
|
||||
usage := "identifying the resource to update"
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage)
|
||||
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, "identifying the resource to update")
|
||||
cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, patch will operate on the content of the file, not the server-side resource.")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (o *PatchOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
func (o *PatchOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
|
||||
var err error
|
||||
|
||||
o.RecordFlags.Complete(f.Command(cmd, false))
|
||||
o.Recorder, err = o.RecordFlags.ToRecorder()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.OutputFormat = cmdutil.GetFlagString(cmd, "output")
|
||||
o.DryRun = cmdutil.GetFlagBool(cmd, "dry-run")
|
||||
o.outputFormat = cmdutil.GetFlagString(cmd, "output")
|
||||
o.dryRun = cmdutil.GetFlagBool(cmd, "dry-run")
|
||||
|
||||
o.ToPrinter = func(operation string) (printers.ResourcePrinterFunc, error) {
|
||||
o.PrintFlags.NamePrintFlags.Operation = operation
|
||||
if o.DryRun {
|
||||
if o.dryRun {
|
||||
o.PrintFlags.Complete("%s (dry run)")
|
||||
}
|
||||
|
||||
@ -153,46 +160,50 @@ func (o *PatchOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
return printer.PrintObj, nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func (o *PatchOptions) RunPatch(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
|
||||
switch {
|
||||
case o.Local && len(args) != 0:
|
||||
return fmt.Errorf("cannot specify --local and server resources")
|
||||
}
|
||||
|
||||
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
|
||||
o.namespace, o.enforceNamespace, err = f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.args = args
|
||||
o.builder = f.NewBuilder()
|
||||
o.unstructuredClientForMapping = f.UnstructuredClientForMapping
|
||||
|
||||
patchType := types.StrategicMergePatchType
|
||||
patchTypeString := strings.ToLower(cmdutil.GetFlagString(cmd, "type"))
|
||||
if len(patchTypeString) != 0 {
|
||||
ok := false
|
||||
patchType, ok = patchTypes[patchTypeString]
|
||||
if !ok {
|
||||
return cmdutil.UsageErrorf(cmd, "--type must be one of %v, not %q",
|
||||
sets.StringKeySet(patchTypes).List(), patchTypeString)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *PatchOptions) Validate() error {
|
||||
if o.Local && len(o.args) != 0 {
|
||||
return fmt.Errorf("cannot specify --local and server resources")
|
||||
}
|
||||
if len(o.Patch) == 0 {
|
||||
return fmt.Errorf("must specify -p to patch")
|
||||
}
|
||||
if len(o.PatchType) != 0 {
|
||||
if _, ok := patchTypes[strings.ToLower(o.PatchType)]; !ok {
|
||||
return fmt.Errorf("--type must be one of %v, not %q", sets.StringKeySet(patchTypes).List(), o.PatchType)
|
||||
}
|
||||
}
|
||||
|
||||
patch := cmdutil.GetFlagString(cmd, "patch")
|
||||
if len(patch) == 0 {
|
||||
return cmdutil.UsageErrorf(cmd, "Must specify -p to patch")
|
||||
}
|
||||
patchBytes, err := yaml.ToJSON([]byte(patch))
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to parse %q: %v", patch, err)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *PatchOptions) RunPatch() error {
|
||||
patchType := types.StrategicMergePatchType
|
||||
if len(o.PatchType) != 0 {
|
||||
patchType = patchTypes[strings.ToLower(o.PatchType)]
|
||||
}
|
||||
|
||||
r := f.NewBuilder().
|
||||
patchBytes, err := yaml.ToJSON([]byte(o.Patch))
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to parse %q: %v", o.Patch, err)
|
||||
}
|
||||
|
||||
r := o.builder.
|
||||
Unstructured().
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
ResourceTypeOrNameArgs(false, args...).
|
||||
NamespaceParam(o.namespace).DefaultNamespace().
|
||||
FilenameParam(o.enforceNamespace, &o.FilenameOptions).
|
||||
ResourceTypeOrNameArgs(false, o.args...).
|
||||
Flatten().
|
||||
Do()
|
||||
err = r.Err()
|
||||
@ -207,12 +218,12 @@ func (o *PatchOptions) RunPatch(f cmdutil.Factory, out io.Writer, cmd *cobra.Com
|
||||
}
|
||||
name, namespace := info.Name, info.Namespace
|
||||
mapping := info.ResourceMapping()
|
||||
client, err := f.UnstructuredClientForMapping(mapping)
|
||||
client, err := o.unstructuredClientForMapping(mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !o.Local && !o.DryRun {
|
||||
if !o.Local && !o.dryRun {
|
||||
helper := resource.NewHelper(client, mapping)
|
||||
patchedObj, err := helper.Patch(namespace, name, patchType, patchBytes)
|
||||
if err != nil {
|
||||
@ -242,7 +253,7 @@ func (o *PatchOptions) RunPatch(f cmdutil.Factory, out io.Writer, cmd *cobra.Com
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
printer.PrintObj(info.Object, out)
|
||||
printer.PrintObj(info.Object, o.Out)
|
||||
|
||||
// if object was not successfully patched, exit with error code 1
|
||||
if !didPatch {
|
||||
@ -285,7 +296,7 @@ func (o *PatchOptions) RunPatch(f cmdutil.Factory, out io.Writer, cmd *cobra.Com
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printer.PrintObj(info.Object, out)
|
||||
return printer.PrintObj(info.Object, o.Out)
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -17,7 +17,6 @@ limitations under the License.
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
@ -25,6 +24,7 @@ import (
|
||||
"k8s.io/client-go/rest/fake"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
cmdtesting "k8s.io/kubernetes/pkg/kubectl/cmd/testing"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
"k8s.io/kubernetes/pkg/kubectl/scheme"
|
||||
)
|
||||
|
||||
@ -56,9 +56,9 @@ func TestPatchObject(t *testing.T) {
|
||||
}),
|
||||
}
|
||||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
stream, _, buf, _ := genericclioptions.NewTestIOStreams()
|
||||
|
||||
cmd := NewCmdPatch(tf, buf)
|
||||
cmd := NewCmdPatch(tf, stream)
|
||||
cmd.Flags().Set("namespace", "test")
|
||||
cmd.Flags().Set("patch", `{"spec":{"type":"NodePort"}}`)
|
||||
cmd.Flags().Set("output", "name")
|
||||
@ -91,9 +91,9 @@ func TestPatchObjectFromFile(t *testing.T) {
|
||||
}),
|
||||
}
|
||||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
stream, _, buf, _ := genericclioptions.NewTestIOStreams()
|
||||
|
||||
cmd := NewCmdPatch(tf, buf)
|
||||
cmd := NewCmdPatch(tf, stream)
|
||||
cmd.Flags().Set("namespace", "test")
|
||||
cmd.Flags().Set("patch", `{"spec":{"type":"NodePort"}}`)
|
||||
cmd.Flags().Set("output", "name")
|
||||
@ -139,8 +139,8 @@ func TestPatchNoop(t *testing.T) {
|
||||
patchObject.Annotations = map[string]string{}
|
||||
}
|
||||
patchObject.Annotations["foo"] = "bar"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
cmd := NewCmdPatch(tf, buf)
|
||||
stream, _, buf, _ := genericclioptions.NewTestIOStreams()
|
||||
cmd := NewCmdPatch(tf, stream)
|
||||
cmd.Flags().Set("namespace", "test")
|
||||
cmd.Flags().Set("patch", `{"metadata":{"annotations":{"foo":"bar"}}}`)
|
||||
cmd.Run(cmd, []string{"services", "frontend"})
|
||||
@ -179,9 +179,9 @@ func TestPatchObjectFromFileOutput(t *testing.T) {
|
||||
}),
|
||||
}
|
||||
tf.Namespace = "test"
|
||||
buf := bytes.NewBuffer([]byte{})
|
||||
stream, _, buf, _ := genericclioptions.NewTestIOStreams()
|
||||
|
||||
cmd := NewCmdPatch(tf, buf)
|
||||
cmd := NewCmdPatch(tf, stream)
|
||||
cmd.Flags().Set("namespace", "test")
|
||||
cmd.Flags().Set("patch", `{"spec":{"type":"NodePort"}}`)
|
||||
cmd.Flags().Set("output", "yaml")
|
||||
|
@ -70,46 +70,40 @@ type ScaleOptions struct {
|
||||
PrintFlags *printers.PrintFlags
|
||||
PrintObj printers.ResourcePrinterFunc
|
||||
|
||||
BuilderArgs []string
|
||||
Namespace string
|
||||
EnforceNamespace bool
|
||||
|
||||
Builder *resource.Builder
|
||||
ClientSet internalclientset.Interface
|
||||
Scaler kubectl.Scaler
|
||||
|
||||
All bool
|
||||
Selector string
|
||||
|
||||
CmdParent string
|
||||
|
||||
Selector string
|
||||
All bool
|
||||
Replicas int
|
||||
ResourceVersion string
|
||||
CurrentReplicas int
|
||||
Replicas int
|
||||
Duration time.Duration
|
||||
Timeout time.Duration
|
||||
|
||||
ClientForMapping func(*meta.RESTMapping) (resource.RESTClient, error)
|
||||
|
||||
Recorder genericclioptions.Recorder
|
||||
Recorder genericclioptions.Recorder
|
||||
builder *resource.Builder
|
||||
namespace string
|
||||
enforceNamespace bool
|
||||
args []string
|
||||
shortOutput bool
|
||||
clientSet internalclientset.Interface
|
||||
scaler kubectl.Scaler
|
||||
unstructuredClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error)
|
||||
parent string
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
|
||||
func NewScaleOptions(ioStreams genericclioptions.IOStreams) *ScaleOptions {
|
||||
return &ScaleOptions{
|
||||
RecordFlags: genericclioptions.NewRecordFlags(),
|
||||
PrintFlags: printers.NewPrintFlags("scaled"),
|
||||
|
||||
RecordFlags: genericclioptions.NewRecordFlags(),
|
||||
PrintFlags: printers.NewPrintFlags("scaled"),
|
||||
CurrentReplicas: -1,
|
||||
|
||||
Recorder: genericclioptions.NoopRecorder{},
|
||||
IOStreams: ioStreams,
|
||||
Recorder: genericclioptions.NoopRecorder{},
|
||||
IOStreams: ioStreams,
|
||||
}
|
||||
}
|
||||
|
||||
// NewCmdScale returns a cobra command with the appropriate configuration and flags to run scale
|
||||
func NewCmdScale(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := NewScaleOptions(streams)
|
||||
func NewCmdScale(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := NewScaleOptions(ioStreams)
|
||||
|
||||
validArgs := []string{"deployment", "replicaset", "replicationcontroller", "statefulset"}
|
||||
argAliases := kubectl.ResourceAliases(validArgs)
|
||||
@ -122,7 +116,7 @@ func NewCmdScale(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.
|
||||
Example: scaleExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
||||
cmdutil.CheckErr(cmdutil.ValidateOutputArgs(cmd))
|
||||
cmdutil.CheckErr(o.Validate(cmd))
|
||||
cmdutil.CheckErr(o.RunScale())
|
||||
},
|
||||
ValidArgs: validArgs,
|
||||
@ -138,71 +132,68 @@ func NewCmdScale(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.
|
||||
cmd.Flags().IntVar(&o.CurrentReplicas, "current-replicas", o.CurrentReplicas, "Precondition for current size. Requires that the current size of the resource match this value in order to scale.")
|
||||
cmd.Flags().IntVar(&o.Replicas, "replicas", o.Replicas, "The new desired number of replicas. Required.")
|
||||
cmd.MarkFlagRequired("replicas")
|
||||
cmd.Flags().DurationVar(&o.Duration, "timeout", o.Duration, "The length of time to wait before giving up on a scale operation, zero means don't wait. Any other values should contain a corresponding time unit (e.g. 1s, 2m, 3h).")
|
||||
|
||||
usage := "identifying the resource to set a new size"
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage)
|
||||
cmd.Flags().DurationVar(&o.Timeout, "timeout", 0, "The length of time to wait before giving up on a scale operation, zero means don't wait. Any other values should contain a corresponding time unit (e.g. 1s, 2m, 3h).")
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, "identifying the resource to set a new size")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (o *ScaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
|
||||
var err error
|
||||
o.Namespace, o.EnforceNamespace, err = f.DefaultNamespace()
|
||||
o.RecordFlags.Complete(f.Command(cmd, false))
|
||||
o.Recorder, err = o.RecordFlags.ToRecorder()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.CmdParent = cmd.Parent().Name()
|
||||
o.Builder = f.NewBuilder()
|
||||
|
||||
o.ClientSet, err = f.ClientSet()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.Scaler, err = f.Scaler()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.BuilderArgs = args
|
||||
o.ClientForMapping = f.UnstructuredClientForMapping
|
||||
|
||||
printer, err := o.PrintFlags.ToPrinter()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.PrintObj = printer.PrintObj
|
||||
|
||||
o.RecordFlags.Complete(f.Command(cmd, false))
|
||||
o.Recorder, err = o.RecordFlags.ToRecorder()
|
||||
o.namespace, o.enforceNamespace, err = f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.builder = f.NewBuilder()
|
||||
o.args = args
|
||||
o.shortOutput = cmdutil.GetFlagString(cmd, "output") == "name"
|
||||
o.clientSet, err = f.ClientSet()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.scaler, err = f.Scaler()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.unstructuredClientForMapping = f.UnstructuredClientForMapping
|
||||
o.parent = cmd.Parent().Name()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *ScaleOptions) Validate(cmd *cobra.Command) error {
|
||||
if err := cmdutil.ValidateOutputArgs(cmd); err != nil {
|
||||
return err
|
||||
}
|
||||
if o.Replicas < 0 {
|
||||
return fmt.Errorf("The --replicas=COUNT flag is required, and COUNT must be greater than or equal to 0")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunScale executes the scaling
|
||||
func (o *ScaleOptions) RunScale() error {
|
||||
|
||||
if o.Replicas < 0 {
|
||||
return fmt.Errorf("The --replicas=COUNT flag is required, and COUNT must be greater than or equal to 0")
|
||||
}
|
||||
|
||||
r := o.Builder.
|
||||
r := o.builder.
|
||||
Unstructured().
|
||||
ContinueOnError().
|
||||
NamespaceParam(o.Namespace).DefaultNamespace().
|
||||
FilenameParam(o.EnforceNamespace, &o.FilenameOptions).
|
||||
ResourceTypeOrNameArgs(o.All, o.BuilderArgs...).
|
||||
NamespaceParam(o.namespace).DefaultNamespace().
|
||||
FilenameParam(o.enforceNamespace, &o.FilenameOptions).
|
||||
ResourceTypeOrNameArgs(o.All, o.args...).
|
||||
Flatten().
|
||||
LabelSelectorParam(o.Selector).
|
||||
Do()
|
||||
err := r.Err()
|
||||
if resource.IsUsageError(err) {
|
||||
return fmt.Errorf("%v", err)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -219,12 +210,11 @@ func (o *ScaleOptions) RunScale() error {
|
||||
return fmt.Errorf("cannot use --resource-version with multiple resources")
|
||||
}
|
||||
|
||||
currentSize := o.CurrentReplicas
|
||||
precondition := &kubectl.ScalePrecondition{Size: currentSize, ResourceVersion: o.ResourceVersion}
|
||||
precondition := &kubectl.ScalePrecondition{Size: o.CurrentReplicas, ResourceVersion: o.ResourceVersion}
|
||||
retry := kubectl.NewRetryParams(kubectl.Interval, kubectl.Timeout)
|
||||
|
||||
var waitForReplicas *kubectl.RetryParams
|
||||
if timeout := o.Duration; timeout != 0 {
|
||||
if o.Timeout != 0 {
|
||||
waitForReplicas = kubectl.NewRetryParams(kubectl.Interval, timeout)
|
||||
}
|
||||
|
||||
@ -237,15 +227,15 @@ func (o *ScaleOptions) RunScale() error {
|
||||
mapping := info.ResourceMapping()
|
||||
if mapping.Resource == "jobs" {
|
||||
// go down the legacy jobs path. This can be removed in 3.14 For now, contain it.
|
||||
fmt.Fprintf(o.ErrOut, "%s scale job is DEPRECATED and will be removed in a future version.\n", o.CmdParent)
|
||||
fmt.Fprintf(o.ErrOut, "%s scale job is DEPRECATED and will be removed in a future version.\n", o.parent)
|
||||
|
||||
if err := ScaleJob(info, o.ClientSet.Batch(), uint(o.Replicas), precondition, retry, waitForReplicas); err != nil {
|
||||
if err := ScaleJob(info, o.clientSet.Batch(), uint(o.Replicas), precondition, retry, waitForReplicas); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
} else {
|
||||
gvk := mapping.GroupVersionKind.GroupVersion().WithResource(mapping.Resource)
|
||||
if err := o.Scaler.Scale(info.Namespace, info.Name, uint(o.Replicas), precondition, retry, waitForReplicas, gvk.GroupResource()); err != nil {
|
||||
if err := o.scaler.Scale(info.Namespace, info.Name, uint(o.Replicas), precondition, retry, waitForReplicas, gvk.GroupResource()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
@ -254,7 +244,7 @@ func (o *ScaleOptions) RunScale() error {
|
||||
if mergePatch, err := o.Recorder.MakeRecordMergePatch(info.Object); err != nil {
|
||||
glog.V(4).Infof("error recording current command: %v", err)
|
||||
} else if len(mergePatch) > 0 {
|
||||
client, err := o.ClientForMapping(mapping)
|
||||
client, err := o.unstructuredClientForMapping(mapping)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -24,19 +24,19 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
envutil "k8s.io/kubernetes/pkg/kubectl/cmd/util/env"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
"k8s.io/kubernetes/pkg/kubectl/resource"
|
||||
"k8s.io/kubernetes/pkg/printers"
|
||||
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -94,32 +94,30 @@ var (
|
||||
|
||||
type EnvOptions struct {
|
||||
PrintFlags *printers.PrintFlags
|
||||
|
||||
resource.FilenameOptions
|
||||
EnvParams []string
|
||||
EnvArgs []string
|
||||
Resources []string
|
||||
|
||||
All bool
|
||||
Resolve bool
|
||||
List bool
|
||||
Local bool
|
||||
Overwrite bool
|
||||
DryRun bool
|
||||
|
||||
ResourceVersion string
|
||||
EnvParams []string
|
||||
All bool
|
||||
Resolve bool
|
||||
List bool
|
||||
Local bool
|
||||
Overwrite bool
|
||||
ContainerSelector string
|
||||
Selector string
|
||||
Output string
|
||||
From string
|
||||
Prefix string
|
||||
|
||||
PrintObj printers.ResourcePrinterFunc
|
||||
|
||||
Builder *resource.Builder
|
||||
Infos []*resource.Info
|
||||
|
||||
UpdatePodSpecForObject func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error)
|
||||
envArgs []string
|
||||
resources []string
|
||||
output string
|
||||
dryRun bool
|
||||
builder func() *resource.Builder
|
||||
updatePodSpecForObject func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error)
|
||||
namespace string
|
||||
enforceNamespace bool
|
||||
clientset *kubernetes.Clientset
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -139,7 +137,7 @@ func NewEnvOptions(streams genericclioptions.IOStreams) *EnvOptions {
|
||||
|
||||
// NewCmdEnv implements the OpenShift cli env command
|
||||
func NewCmdEnv(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
|
||||
options := NewEnvOptions(streams)
|
||||
o := NewEnvOptions(streams)
|
||||
cmd := &cobra.Command{
|
||||
Use: "env RESOURCE/NAME KEY_1=VAL_1 ... KEY_N=VAL_N",
|
||||
DisableFlagsInUseLine: true,
|
||||
@ -147,24 +145,25 @@ func NewCmdEnv(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Co
|
||||
Long: envLong,
|
||||
Example: fmt.Sprintf(envExample),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(options.Complete(f, cmd, args))
|
||||
cmdutil.CheckErr(options.RunEnv(f))
|
||||
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
||||
cmdutil.CheckErr(o.Validate())
|
||||
cmdutil.CheckErr(o.RunEnv())
|
||||
},
|
||||
}
|
||||
usage := "the resource to update the env"
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
|
||||
cmd.Flags().StringVarP(&options.ContainerSelector, "containers", "c", options.ContainerSelector, "The names of containers in the selected pod templates to change - may use wildcards")
|
||||
cmd.Flags().StringP("from", "", "", "The name of a resource from which to inject environment variables")
|
||||
cmd.Flags().StringP("prefix", "", "", "Prefix to append to variable names")
|
||||
cmd.Flags().StringArrayVarP(&options.EnvParams, "env", "e", options.EnvParams, "Specify a key-value pair for an environment variable to set into each container.")
|
||||
cmd.Flags().BoolVar(&options.List, "list", options.List, "If true, display the environment and any changes in the standard format. this flag will removed when we have kubectl view env.")
|
||||
cmd.Flags().BoolVar(&options.Resolve, "resolve", options.Resolve, "If true, show secret or configmap references when listing variables")
|
||||
cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on")
|
||||
cmd.Flags().BoolVar(&options.Local, "local", options.Local, "If true, set env will NOT contact api-server but run locally.")
|
||||
cmd.Flags().BoolVar(&options.All, "all", options.All, "If true, select all resources in the namespace of the specified resource types")
|
||||
cmd.Flags().BoolVar(&options.Overwrite, "overwrite", options.Overwrite, "If true, allow environment to be overwritten, otherwise reject updates that overwrite existing environment.")
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage)
|
||||
cmd.Flags().StringVarP(&o.ContainerSelector, "containers", "c", o.ContainerSelector, "The names of containers in the selected pod templates to change - may use wildcards")
|
||||
cmd.Flags().StringVarP(&o.From, "from", "", "", "The name of a resource from which to inject environment variables")
|
||||
cmd.Flags().StringVarP(&o.Prefix, "prefix", "", "", "Prefix to append to variable names")
|
||||
cmd.Flags().StringArrayVarP(&o.EnvParams, "env", "e", o.EnvParams, "Specify a key-value pair for an environment variable to set into each container.")
|
||||
cmd.Flags().BoolVar(&o.List, "list", o.List, "If true, display the environment and any changes in the standard format. this flag will removed when we have kubectl view env.")
|
||||
cmd.Flags().BoolVar(&o.Resolve, "resolve", o.Resolve, "If true, show secret or configmap references when listing variables")
|
||||
cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on")
|
||||
cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, set env will NOT contact api-server but run locally.")
|
||||
cmd.Flags().BoolVar(&o.All, "all", o.All, "If true, select all resources in the namespace of the specified resource types")
|
||||
cmd.Flags().BoolVar(&o.Overwrite, "overwrite", o.Overwrite, "If true, allow environment to be overwritten, otherwise reject updates that overwrite existing environment.")
|
||||
|
||||
options.PrintFlags.AddFlags(cmd)
|
||||
o.PrintFlags.AddFlags(cmd)
|
||||
|
||||
cmdutil.AddDryRunFlag(cmd)
|
||||
return cmd
|
||||
@ -187,30 +186,17 @@ func (o *EnvOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []stri
|
||||
if o.All && len(o.Selector) > 0 {
|
||||
return fmt.Errorf("cannot set --all and --selector at the same time")
|
||||
}
|
||||
resources, envArgs, ok := envutil.SplitEnvironmentFromResources(args)
|
||||
ok := false
|
||||
o.resources, o.envArgs, ok = envutil.SplitEnvironmentFromResources(args)
|
||||
if !ok {
|
||||
return cmdutil.UsageErrorf(cmd, "all resources must be specified before environment changes: %s", strings.Join(args, " "))
|
||||
}
|
||||
if len(o.Filenames) == 0 && len(resources) < 1 {
|
||||
return cmdutil.UsageErrorf(cmd, "one or more resources must be specified as <resource> <name> or <resource>/<name>")
|
||||
return fmt.Errorf("all resources must be specified before environment changes: %s", strings.Join(args, " "))
|
||||
}
|
||||
|
||||
o.UpdatePodSpecForObject = f.UpdatePodSpecForObject
|
||||
o.ContainerSelector = cmdutil.GetFlagString(cmd, "containers")
|
||||
o.List = cmdutil.GetFlagBool(cmd, "list")
|
||||
o.Resolve = cmdutil.GetFlagBool(cmd, "resolve")
|
||||
o.Selector = cmdutil.GetFlagString(cmd, "selector")
|
||||
o.All = cmdutil.GetFlagBool(cmd, "all")
|
||||
o.Overwrite = cmdutil.GetFlagBool(cmd, "overwrite")
|
||||
o.Output = cmdutil.GetFlagString(cmd, "output")
|
||||
o.From = cmdutil.GetFlagString(cmd, "from")
|
||||
o.Prefix = cmdutil.GetFlagString(cmd, "prefix")
|
||||
o.DryRun = cmdutil.GetDryRunFlag(cmd)
|
||||
o.updatePodSpecForObject = f.UpdatePodSpecForObject
|
||||
o.output = cmdutil.GetFlagString(cmd, "output")
|
||||
o.dryRun = cmdutil.GetDryRunFlag(cmd)
|
||||
|
||||
o.EnvArgs = envArgs
|
||||
o.Resources = resources
|
||||
|
||||
if o.DryRun {
|
||||
if o.dryRun {
|
||||
// TODO(juanvallejo): This can be cleaned up even further by creating
|
||||
// a PrintFlags struct that binds the --dry-run flag, and whose
|
||||
// ToPrinter method returns a printer that understands how to print
|
||||
@ -223,41 +209,43 @@ func (o *EnvOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []stri
|
||||
}
|
||||
o.PrintObj = printer.PrintObj
|
||||
|
||||
if o.List && len(o.Output) > 0 {
|
||||
return cmdutil.UsageErrorf(cmd, "--list and --output may not be specified together")
|
||||
o.clientset, err = f.KubernetesClientSet()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.namespace, o.enforceNamespace, err = f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.builder = f.NewBuilder
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *EnvOptions) Validate() error {
|
||||
if len(o.Filenames) == 0 && len(o.resources) < 1 {
|
||||
return fmt.Errorf("one or more resources must be specified as <resource> <name> or <resource>/<name>")
|
||||
}
|
||||
if o.List && len(o.output) > 0 {
|
||||
return fmt.Errorf("--list and --output may not be specified together")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RunEnv contains all the necessary functionality for the OpenShift cli env command
|
||||
func (o *EnvOptions) RunEnv(f cmdutil.Factory) error {
|
||||
var kubeClient *kubernetes.Clientset
|
||||
if o.List {
|
||||
client, err := f.KubernetesClientSet()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
kubeClient = client
|
||||
}
|
||||
|
||||
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
env, remove, err := envutil.ParseEnv(append(o.EnvParams, o.EnvArgs...), o.In)
|
||||
func (o *EnvOptions) RunEnv() error {
|
||||
env, remove, err := envutil.ParseEnv(append(o.EnvParams, o.envArgs...), o.In)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if len(o.From) != 0 {
|
||||
b := f.NewBuilder().
|
||||
b := o.builder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
LocalParam(o.Local).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
NamespaceParam(o.namespace).DefaultNamespace().
|
||||
FilenameParam(o.enforceNamespace, &o.FilenameOptions).
|
||||
Flatten()
|
||||
|
||||
if !o.Local {
|
||||
@ -320,27 +308,27 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error {
|
||||
}
|
||||
}
|
||||
|
||||
b := f.NewBuilder().
|
||||
b := o.builder().
|
||||
Internal(legacyscheme.Scheme).
|
||||
LocalParam(o.Local).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
NamespaceParam(o.namespace).DefaultNamespace().
|
||||
FilenameParam(o.enforceNamespace, &o.FilenameOptions).
|
||||
Flatten()
|
||||
|
||||
if !o.Local {
|
||||
b.LabelSelectorParam(o.Selector).
|
||||
ResourceTypeOrNameArgs(o.All, o.Resources...).
|
||||
ResourceTypeOrNameArgs(o.All, o.resources...).
|
||||
Latest()
|
||||
}
|
||||
|
||||
o.Infos, err = b.Do().Infos()
|
||||
infos, err := b.Do().Infos()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
patches := CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), func(info *resource.Info) ([]byte, error) {
|
||||
patches := CalculatePatches(infos, cmdutil.InternalVersionJSONEncoder(), func(info *resource.Info) ([]byte, error) {
|
||||
info.Object = info.AsVersioned(legacyscheme.Scheme)
|
||||
_, err := o.UpdatePodSpecForObject(info.Object, func(spec *v1.PodSpec) error {
|
||||
_, err := o.updatePodSpecForObject(info.Object, func(spec *v1.PodSpec) error {
|
||||
resolutionErrorsEncountered := false
|
||||
containers, _ := selectContainers(spec.Containers, o.ContainerSelector)
|
||||
if len(containers) == 0 {
|
||||
@ -373,7 +361,7 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error {
|
||||
continue
|
||||
}
|
||||
|
||||
value, err := envutil.GetEnvVarRefValue(kubeClient, cmdNamespace, store, env.ValueFrom, info.Object, c)
|
||||
value, err := envutil.GetEnvVarRefValue(o.clientset, o.namespace, store, env.ValueFrom, info.Object, c)
|
||||
// Print the resolved value
|
||||
if err == nil {
|
||||
fmt.Fprintf(o.Out, "%s=%s\n", env.Name, value)
|
||||
@ -429,7 +417,7 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error {
|
||||
continue
|
||||
}
|
||||
|
||||
if o.Local || o.DryRun {
|
||||
if o.Local || o.dryRun {
|
||||
if err := o.PrintObj(patch.Info.AsVersioned(legacyscheme.Scheme), o.Out); err != nil {
|
||||
return err
|
||||
}
|
||||
@ -445,7 +433,7 @@ func (o *EnvOptions) RunEnv(f cmdutil.Factory) error {
|
||||
|
||||
// make sure arguments to set or replace environment variables are set
|
||||
// before returning a successful message
|
||||
if len(env) == 0 && len(o.EnvArgs) == 0 {
|
||||
if len(env) == 0 && len(o.envArgs) == 0 {
|
||||
return fmt.Errorf("at least one environment variable must be provided")
|
||||
}
|
||||
|
||||
|
@ -61,33 +61,28 @@ func TestSetEnvLocal(t *testing.T) {
|
||||
}
|
||||
tf.Namespace = "test"
|
||||
tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}}
|
||||
|
||||
outputFormat := "name"
|
||||
|
||||
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
|
||||
cmd := NewCmdEnv(tf, streams)
|
||||
cmd.SetOutput(buf)
|
||||
cmd.Flags().Set("output", outputFormat)
|
||||
cmd.Flags().Set("local", "true")
|
||||
|
||||
opts := EnvOptions{
|
||||
PrintFlags: &printers.PrintFlags{
|
||||
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
|
||||
NamePrintFlags: printers.NewNamePrintFlags(""),
|
||||
|
||||
OutputFormat: &outputFormat,
|
||||
},
|
||||
FilenameOptions: resource.FilenameOptions{
|
||||
Filenames: []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}},
|
||||
Local: true,
|
||||
IOStreams: streams,
|
||||
streams, _, buf, bufErr := genericclioptions.NewTestIOStreams()
|
||||
opts := NewEnvOptions(streams)
|
||||
opts.PrintFlags = &printers.PrintFlags{
|
||||
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
|
||||
NamePrintFlags: printers.NewNamePrintFlags(""),
|
||||
OutputFormat: &outputFormat,
|
||||
}
|
||||
err := opts.Complete(tf, cmd, []string{"env=prod"})
|
||||
if err == nil {
|
||||
err = opts.RunEnv(tf)
|
||||
opts.FilenameOptions = resource.FilenameOptions{
|
||||
Filenames: []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"},
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
opts.Local = true
|
||||
|
||||
err := opts.Complete(tf, NewCmdEnv(tf, streams), []string{"env=prod"})
|
||||
assert.NoError(t, err)
|
||||
err = opts.Validate()
|
||||
assert.NoError(t, err)
|
||||
err = opts.RunEnv()
|
||||
assert.NoError(t, err)
|
||||
if bufErr.Len() > 0 {
|
||||
t.Errorf("unexpected error: %s", string(bufErr.String()))
|
||||
}
|
||||
if !strings.Contains(buf.String(), "replicationcontroller/cassandra") {
|
||||
t.Errorf("did not set env: %s", buf.String())
|
||||
@ -99,7 +94,6 @@ func TestSetMultiResourcesEnvLocal(t *testing.T) {
|
||||
defer tf.Cleanup()
|
||||
|
||||
ns := legacyscheme.Codecs
|
||||
|
||||
tf.Client = &fake.RESTClient{
|
||||
GroupVersion: schema.GroupVersion{Version: ""},
|
||||
NegotiatedSerializer: ns,
|
||||
@ -112,33 +106,27 @@ func TestSetMultiResourcesEnvLocal(t *testing.T) {
|
||||
tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}}
|
||||
|
||||
outputFormat := "name"
|
||||
|
||||
streams, _, buf, _ := genericclioptions.NewTestIOStreams()
|
||||
cmd := NewCmdEnv(tf, streams)
|
||||
cmd.SetOutput(buf)
|
||||
cmd.Flags().Set("output", outputFormat)
|
||||
cmd.Flags().Set("local", "true")
|
||||
|
||||
opts := EnvOptions{
|
||||
PrintFlags: &printers.PrintFlags{
|
||||
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
|
||||
NamePrintFlags: printers.NewNamePrintFlags(""),
|
||||
|
||||
OutputFormat: &outputFormat,
|
||||
},
|
||||
FilenameOptions: resource.FilenameOptions{
|
||||
Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}},
|
||||
Local: true,
|
||||
IOStreams: streams,
|
||||
streams, _, buf, bufErr := genericclioptions.NewTestIOStreams()
|
||||
opts := NewEnvOptions(streams)
|
||||
opts.PrintFlags = &printers.PrintFlags{
|
||||
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
|
||||
NamePrintFlags: printers.NewNamePrintFlags(""),
|
||||
OutputFormat: &outputFormat,
|
||||
}
|
||||
err := opts.Complete(tf, cmd, []string{"env=prod"})
|
||||
if err == nil {
|
||||
err = opts.RunEnv(tf)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
opts.FilenameOptions = resource.FilenameOptions{
|
||||
Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"},
|
||||
}
|
||||
opts.Local = true
|
||||
|
||||
err := opts.Complete(tf, NewCmdEnv(tf, streams), []string{"env=prod"})
|
||||
assert.NoError(t, err)
|
||||
err = opts.Validate()
|
||||
assert.NoError(t, err)
|
||||
err = opts.RunEnv()
|
||||
assert.NoError(t, err)
|
||||
if bufErr.Len() > 0 {
|
||||
t.Errorf("unexpected error: %s", string(bufErr.String()))
|
||||
}
|
||||
expectedOut := "replicationcontroller/first-rc\nreplicationcontroller/second-rc\n"
|
||||
if buf.String() != expectedOut {
|
||||
t.Errorf("expected out:\n%s\nbut got:\n%s", expectedOut, buf.String())
|
||||
@ -472,6 +460,7 @@ func TestSetEnvRemote(t *testing.T) {
|
||||
groupVersion := schema.GroupVersion{Group: input.apiGroup, Version: input.apiVersion}
|
||||
testapi.Default = testapi.Groups[input.testAPIGroup]
|
||||
tf := cmdtesting.NewTestFactory()
|
||||
tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}}
|
||||
defer tf.Cleanup()
|
||||
|
||||
codec := scheme.Codecs.CodecForVersions(scheme.Codecs.LegacyCodec(groupVersion), scheme.Codecs.UniversalDecoder(groupVersion), groupVersion, groupVersion)
|
||||
@ -505,23 +494,18 @@ func TestSetEnvRemote(t *testing.T) {
|
||||
}
|
||||
|
||||
outputFormat := "yaml"
|
||||
|
||||
streams := genericclioptions.NewTestIOStreamsDiscard()
|
||||
cmd := NewCmdEnv(tf, streams)
|
||||
cmd.Flags().Set("output", outputFormat)
|
||||
opts := EnvOptions{
|
||||
PrintFlags: &printers.PrintFlags{
|
||||
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
|
||||
NamePrintFlags: printers.NewNamePrintFlags(""),
|
||||
|
||||
OutputFormat: &outputFormat,
|
||||
},
|
||||
Local: false,
|
||||
IOStreams: streams,
|
||||
opts := NewEnvOptions(streams)
|
||||
opts.PrintFlags = &printers.PrintFlags{
|
||||
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
|
||||
NamePrintFlags: printers.NewNamePrintFlags(""),
|
||||
OutputFormat: &outputFormat,
|
||||
}
|
||||
err := opts.Complete(tf, cmd, input.args)
|
||||
opts.Local = false
|
||||
opts.IOStreams = streams
|
||||
err := opts.Complete(tf, NewCmdEnv(tf, streams), input.args)
|
||||
assert.NoError(t, err)
|
||||
err = opts.RunEnv(tf)
|
||||
err = opts.RunEnv()
|
||||
assert.NoError(t, err)
|
||||
})
|
||||
}
|
||||
|
@ -73,6 +73,8 @@ type SubjectOptions struct {
|
||||
Groups []string
|
||||
ServiceAccounts []string
|
||||
|
||||
namespace string
|
||||
|
||||
PrintObj printers.ResourcePrinterFunc
|
||||
|
||||
genericclioptions.IOStreams
|
||||
@ -87,8 +89,7 @@ func NewSubjectOptions(streams genericclioptions.IOStreams) *SubjectOptions {
|
||||
}
|
||||
|
||||
func NewCmdSubject(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
|
||||
options := NewSubjectOptions(streams)
|
||||
|
||||
o := NewSubjectOptions(streams)
|
||||
cmd := &cobra.Command{
|
||||
Use: "subject (-f FILENAME | TYPE NAME) [--user=username] [--group=groupname] [--serviceaccount=namespace:serviceaccountname] [--dry-run]",
|
||||
DisableFlagsInUseLine: true,
|
||||
@ -96,23 +97,22 @@ func NewCmdSubject(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobr
|
||||
Long: subject_long,
|
||||
Example: subject_example,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
cmdutil.CheckErr(options.Complete(f, cmd, args))
|
||||
cmdutil.CheckErr(options.Validate())
|
||||
cmdutil.CheckErr(options.Run(f, addSubjects))
|
||||
cmdutil.CheckErr(o.Complete(f, cmd, args))
|
||||
cmdutil.CheckErr(o.Validate())
|
||||
cmdutil.CheckErr(o.Run(addSubjects))
|
||||
},
|
||||
}
|
||||
|
||||
options.PrintFlags.AddFlags(cmd)
|
||||
o.PrintFlags.AddFlags(cmd)
|
||||
|
||||
usage := "the resource to update the subjects"
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
|
||||
cmd.Flags().BoolVar(&options.All, "all", options.All, "Select all resources, including uninitialized ones, in the namespace of the specified resource types")
|
||||
cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
|
||||
cmd.Flags().BoolVar(&options.Local, "local", options.Local, "If true, set subject will NOT contact api-server but run locally.")
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, "the resource to update the subjects")
|
||||
cmd.Flags().BoolVar(&o.All, "all", o.All, "Select all resources, including uninitialized ones, in the namespace of the specified resource types")
|
||||
cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
|
||||
cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, set subject will NOT contact api-server but run locally.")
|
||||
cmdutil.AddDryRunFlag(cmd)
|
||||
cmd.Flags().StringArrayVar(&options.Users, "user", options.Users, "Usernames to bind to the role")
|
||||
cmd.Flags().StringArrayVar(&options.Groups, "group", options.Groups, "Groups to bind to the role")
|
||||
cmd.Flags().StringArrayVar(&options.ServiceAccounts, "serviceaccount", options.ServiceAccounts, "Service accounts to bind to the role")
|
||||
cmd.Flags().StringArrayVar(&o.Users, "user", o.Users, "Usernames to bind to the role")
|
||||
cmd.Flags().StringArrayVar(&o.Groups, "group", o.Groups, "Groups to bind to the role")
|
||||
cmd.Flags().StringArrayVar(&o.ServiceAccounts, "serviceaccount", o.ServiceAccounts, "Service accounts to bind to the role")
|
||||
cmdutil.AddIncludeUninitializedFlag(cmd)
|
||||
return cmd
|
||||
}
|
||||
@ -130,7 +130,8 @@ func (o *SubjectOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
||||
}
|
||||
o.PrintObj = printer.PrintObj
|
||||
|
||||
cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
|
||||
var enforceNamespace bool
|
||||
o.namespace, enforceNamespace, err = f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -140,7 +141,7 @@ func (o *SubjectOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
||||
Internal(legacyscheme.Scheme).
|
||||
LocalParam(o.Local).
|
||||
ContinueOnError().
|
||||
NamespaceParam(cmdNamespace).DefaultNamespace().
|
||||
NamespaceParam(o.namespace).DefaultNamespace().
|
||||
FilenameParam(enforceNamespace, &o.FilenameOptions).
|
||||
IncludeUninitialized(includeUninitialized).
|
||||
Flatten()
|
||||
@ -192,8 +193,7 @@ func (o *SubjectOptions) Validate() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *SubjectOptions) Run(f cmdutil.Factory, fn updateSubjects) error {
|
||||
var err error
|
||||
func (o *SubjectOptions) Run(fn updateSubjects) error {
|
||||
patches := CalculatePatches(o.Infos, cmdutil.InternalVersionJSONEncoder(), func(info *resource.Info) ([]byte, error) {
|
||||
subjects := []rbac.Subject{}
|
||||
for _, user := range sets.NewString(o.Users...).List() {
|
||||
@ -217,10 +217,7 @@ func (o *SubjectOptions) Run(f cmdutil.Factory, fn updateSubjects) error {
|
||||
namespace := tokens[0]
|
||||
name := tokens[1]
|
||||
if len(namespace) == 0 {
|
||||
namespace, _, err = f.DefaultNamespace()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
namespace = o.namespace
|
||||
}
|
||||
subject := rbac.Subject{
|
||||
Kind: rbac.ServiceAccountKind,
|
||||
|
@ -20,14 +20,15 @@ import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
apimachineryversion "k8s.io/apimachinery/pkg/version"
|
||||
"k8s.io/client-go/discovery"
|
||||
"k8s.io/kubernetes/pkg/kubectl/cmd/templates"
|
||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
|
||||
"k8s.io/kubernetes/pkg/kubectl/util/i18n"
|
||||
"k8s.io/kubernetes/pkg/version"
|
||||
)
|
||||
@ -37,52 +38,67 @@ type Version struct {
|
||||
ServerVersion *apimachineryversion.Info `json:"serverVersion,omitempty" yaml:"serverVersion,omitempty"`
|
||||
}
|
||||
|
||||
// VersionOptions: describe the options available to users of the "kubectl
|
||||
// version" command.
|
||||
type VersionOptions struct {
|
||||
clientOnly bool
|
||||
short bool
|
||||
output string
|
||||
}
|
||||
|
||||
var (
|
||||
versionExample = templates.Examples(i18n.T(`
|
||||
# Print the client and server versions for the current context
|
||||
kubectl version`))
|
||||
)
|
||||
|
||||
func NewCmdVersion(f cmdutil.Factory, out io.Writer) *cobra.Command {
|
||||
type VersionOptions struct {
|
||||
ClientOnly bool
|
||||
Short bool
|
||||
Output string
|
||||
|
||||
discoveryClient discovery.CachedDiscoveryInterface
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
|
||||
func NewVersionOptions(ioStreams genericclioptions.IOStreams) *VersionOptions {
|
||||
return &VersionOptions{
|
||||
IOStreams: ioStreams,
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func NewCmdVersion(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := NewVersionOptions(ioStreams)
|
||||
cmd := &cobra.Command{
|
||||
Use: "version",
|
||||
Short: i18n.T("Print the client and server version information"),
|
||||
Long: "Print the client and server version information for the current context",
|
||||
Example: versionExample,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
options := new(VersionOptions)
|
||||
cmdutil.CheckErr(options.Complete(cmd))
|
||||
cmdutil.CheckErr(options.Validate())
|
||||
cmdutil.CheckErr(options.Run(f, out))
|
||||
cmdutil.CheckErr(o.Complete(f, cmd))
|
||||
cmdutil.CheckErr(o.Validate())
|
||||
cmdutil.CheckErr(o.Run())
|
||||
},
|
||||
}
|
||||
cmd.Flags().BoolP("client", "c", false, "Client version only (no server required).")
|
||||
cmd.Flags().BoolP("short", "", false, "Print just the version number.")
|
||||
cmd.Flags().StringP("output", "o", "", "One of 'yaml' or 'json'.")
|
||||
cmd.Flags().BoolVarP(&o.ClientOnly, "client", "c", o.ClientOnly, "Client version only (no server required).")
|
||||
cmd.Flags().BoolVarP(&o.Short, "short", "", o.Short, "Print just the version number.")
|
||||
cmd.Flags().StringVarP(&o.Output, "output", "o", o.Output, "One of 'yaml' or 'json'.")
|
||||
cmd.Flags().MarkShorthandDeprecated("client", "please use --client instead.")
|
||||
return cmd
|
||||
}
|
||||
|
||||
func retrieveServerVersion(f cmdutil.Factory) (*apimachineryversion.Info, error) {
|
||||
discoveryClient, err := f.DiscoveryClient()
|
||||
func (o *VersionOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
var err error
|
||||
o.discoveryClient, err = f.DiscoveryClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
|
||||
// Always request fresh data from the server
|
||||
discoveryClient.Invalidate()
|
||||
return discoveryClient.ServerVersion()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *VersionOptions) Run(f cmdutil.Factory, out io.Writer) error {
|
||||
func (o *VersionOptions) Validate() error {
|
||||
if o.Output != "" && o.Output != "yaml" && o.Output != "json" {
|
||||
return errors.New(`--output must be 'yaml' or 'json'`)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *VersionOptions) Run() error {
|
||||
var (
|
||||
serverVersion *apimachineryversion.Info
|
||||
serverErr error
|
||||
@ -92,22 +108,24 @@ func (o *VersionOptions) Run(f cmdutil.Factory, out io.Writer) error {
|
||||
clientVersion := version.Get()
|
||||
versionInfo.ClientVersion = &clientVersion
|
||||
|
||||
if !o.clientOnly {
|
||||
serverVersion, serverErr = retrieveServerVersion(f)
|
||||
if !o.ClientOnly {
|
||||
// Always request fresh data from the server
|
||||
o.discoveryClient.Invalidate()
|
||||
serverVersion, serverErr = o.discoveryClient.ServerVersion()
|
||||
versionInfo.ServerVersion = serverVersion
|
||||
}
|
||||
|
||||
switch o.output {
|
||||
switch o.Output {
|
||||
case "":
|
||||
if o.short {
|
||||
fmt.Fprintf(out, "Client Version: %s\n", clientVersion.GitVersion)
|
||||
if o.Short {
|
||||
fmt.Fprintf(o.Out, "Client Version: %s\n", clientVersion.GitVersion)
|
||||
if serverVersion != nil {
|
||||
fmt.Fprintf(out, "Server Version: %s\n", serverVersion.GitVersion)
|
||||
fmt.Fprintf(o.Out, "Server Version: %s\n", serverVersion.GitVersion)
|
||||
}
|
||||
} else {
|
||||
fmt.Fprintf(out, "Client Version: %s\n", fmt.Sprintf("%#v", clientVersion))
|
||||
fmt.Fprintf(o.Out, "Client Version: %s\n", fmt.Sprintf("%#v", clientVersion))
|
||||
if serverVersion != nil {
|
||||
fmt.Fprintf(out, "Server Version: %s\n", fmt.Sprintf("%#v", *serverVersion))
|
||||
fmt.Fprintf(o.Out, "Server Version: %s\n", fmt.Sprintf("%#v", *serverVersion))
|
||||
}
|
||||
}
|
||||
case "yaml":
|
||||
@ -115,33 +133,18 @@ func (o *VersionOptions) Run(f cmdutil.Factory, out io.Writer) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(out, string(marshalled))
|
||||
fmt.Fprintln(o.Out, string(marshalled))
|
||||
case "json":
|
||||
marshalled, err := json.MarshalIndent(&versionInfo, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Fprintln(out, string(marshalled))
|
||||
fmt.Fprintln(o.Out, string(marshalled))
|
||||
default:
|
||||
// There is a bug in the program if we hit this case.
|
||||
// However, we follow a policy of never panicking.
|
||||
return fmt.Errorf("VersionOptions were not validated: --output=%q should have been rejected", o.output)
|
||||
return fmt.Errorf("VersionOptions were not validated: --output=%q should have been rejected", o.Output)
|
||||
}
|
||||
|
||||
return serverErr
|
||||
}
|
||||
|
||||
func (o *VersionOptions) Complete(cmd *cobra.Command) error {
|
||||
o.clientOnly = cmdutil.GetFlagBool(cmd, "client")
|
||||
o.short = cmdutil.GetFlagBool(cmd, "short")
|
||||
o.output = cmdutil.GetFlagString(cmd, "output")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (o *VersionOptions) Validate() error {
|
||||
if o.output != "" && o.output != "yaml" && o.output != "json" {
|
||||
return errors.New(`--output must be 'yaml' or 'json'`)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user