use record flags

pull/8/head
David Eads 2018-04-18 11:20:33 -04:00
parent b523c915e4
commit e2a5c39b23
16 changed files with 244 additions and 139 deletions

View File

@ -206,6 +206,7 @@ filegroup(
"//pkg/kubectl/categories:all-srcs", "//pkg/kubectl/categories:all-srcs",
"//pkg/kubectl/cmd:all-srcs", "//pkg/kubectl/cmd:all-srcs",
"//pkg/kubectl/explain:all-srcs", "//pkg/kubectl/explain:all-srcs",
"//pkg/kubectl/genericclioptions:all-srcs",
"//pkg/kubectl/metricsutil:all-srcs", "//pkg/kubectl/metricsutil:all-srcs",
"//pkg/kubectl/plugins:all-srcs", "//pkg/kubectl/plugins:all-srcs",
"//pkg/kubectl/proxy:all-srcs", "//pkg/kubectl/proxy:all-srcs",

View File

@ -41,7 +41,6 @@ go_library(
"plugin.go", "plugin.go",
"portforward.go", "portforward.go",
"proxy.go", "proxy.go",
"record_flags.go",
"replace.go", "replace.go",
"rollingupdate.go", "rollingupdate.go",
"run.go", "run.go",
@ -79,6 +78,7 @@ go_library(
"//pkg/kubectl/cmd/util/editor:go_default_library", "//pkg/kubectl/cmd/util/editor:go_default_library",
"//pkg/kubectl/cmd/util/openapi:go_default_library", "//pkg/kubectl/cmd/util/openapi:go_default_library",
"//pkg/kubectl/explain:go_default_library", "//pkg/kubectl/explain:go_default_library",
"//pkg/kubectl/genericclioptions:go_default_library",
"//pkg/kubectl/metricsutil:go_default_library", "//pkg/kubectl/metricsutil:go_default_library",
"//pkg/kubectl/plugins:go_default_library", "//pkg/kubectl/plugins:go_default_library",
"//pkg/kubectl/proxy:go_default_library", "//pkg/kubectl/proxy:go_default_library",

View File

@ -34,6 +34,7 @@ import (
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/kubectl/util/i18n"
) )
@ -42,6 +43,7 @@ import (
type AnnotateOptions struct { type AnnotateOptions struct {
// Filename options // Filename options
resource.FilenameOptions resource.FilenameOptions
RecordFlags *genericclioptions.RecordFlags
// Common user flags // Common user flags
overwrite bool overwrite bool
@ -51,12 +53,12 @@ type AnnotateOptions struct {
resourceVersion string resourceVersion string
selector string selector string
outputFormat string outputFormat string
recordChangeCause bool
// results of arg parsing // results of arg parsing
resources []string resources []string
newAnnotations map[string]string newAnnotations map[string]string
removeAnnotations []string removeAnnotations []string
Recorder genericclioptions.Recorder
// Common share fields // Common share fields
out io.Writer out io.Writer
@ -97,8 +99,15 @@ var (
kubectl annotate pods foo description-`)) kubectl annotate pods foo description-`))
) )
func NewAnnotateOptions(out io.Writer) *AnnotateOptions {
return &AnnotateOptions{
out: out,
RecordFlags: genericclioptions.NewRecordFlags(),
}
}
func NewCmdAnnotate(f cmdutil.Factory, out io.Writer) *cobra.Command { func NewCmdAnnotate(f cmdutil.Factory, out io.Writer) *cobra.Command {
options := &AnnotateOptions{} options := NewAnnotateOptions(out)
validArgs := cmdutil.ValidArgList(f) validArgs := cmdutil.ValidArgList(f)
cmd := &cobra.Command{ cmd := &cobra.Command{
@ -108,7 +117,7 @@ func NewCmdAnnotate(f cmdutil.Factory, out io.Writer) *cobra.Command {
Long: annotateLong + "\n\n" + cmdutil.ValidResourceTypeList(f), Long: annotateLong + "\n\n" + cmdutil.ValidResourceTypeList(f),
Example: annotateExample, Example: annotateExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if err := options.Complete(out, cmd, args); err != nil { if err := options.Complete(f, cmd, args); err != nil {
cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, "%v", err)) cmdutil.CheckErr(cmdutil.UsageErrorf(cmd, "%v", err))
} }
if err := options.Validate(); err != nil { if err := options.Validate(); err != nil {
@ -119,6 +128,10 @@ func NewCmdAnnotate(f cmdutil.Factory, out io.Writer) *cobra.Command {
ValidArgs: validArgs, ValidArgs: validArgs,
ArgAliases: kubectl.ResourceAliases(validArgs), ArgAliases: kubectl.ResourceAliases(validArgs),
} }
// bind flag structs
options.RecordFlags.AddFlags(cmd)
cmdutil.AddPrinterFlags(cmd) cmdutil.AddPrinterFlags(cmd)
cmdutil.AddIncludeUninitializedFlag(cmd) cmdutil.AddIncludeUninitializedFlag(cmd)
cmd.Flags().BoolVar(&options.overwrite, "overwrite", options.overwrite, "If true, allow annotations to be overwritten, otherwise reject annotation updates that overwrite existing annotations.") cmd.Flags().BoolVar(&options.overwrite, "overwrite", options.overwrite, "If true, allow annotations to be overwritten, otherwise reject annotation updates that overwrite existing annotations.")
@ -129,18 +142,23 @@ func NewCmdAnnotate(f cmdutil.Factory, out io.Writer) *cobra.Command {
usage := "identifying the resource to update the annotation" usage := "identifying the resource to update the annotation"
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage)
cmdutil.AddDryRunFlag(cmd) cmdutil.AddDryRunFlag(cmd)
cmdutil.AddRecordFlag(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd) cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd return cmd
} }
// Complete adapts from the command line args and factory to the data required. // Complete adapts from the command line args and factory to the data required.
func (o *AnnotateOptions) Complete(out io.Writer, cmd *cobra.Command, args []string) (err error) { func (o *AnnotateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
o.out = out o.RecordFlags.Complete(f.Command(cmd, false))
var err error
o.Recorder, err = o.RecordFlags.ToRecorder()
if err != nil {
return err
}
o.outputFormat = cmdutil.GetFlagString(cmd, "output") o.outputFormat = cmdutil.GetFlagString(cmd, "output")
o.dryrun = cmdutil.GetDryRunFlag(cmd) o.dryrun = cmdutil.GetDryRunFlag(cmd)
o.recordChangeCause = cmdutil.GetRecordFlag(cmd)
// retrieves resource and annotation args from args // retrieves resource and annotation args from args
// also checks args to verify that all resources are specified before annotations // also checks args to verify that all resources are specified before annotations
@ -174,8 +192,6 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro
return err return err
} }
changeCause := f.Command(cmd, false)
includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false) includeUninitialized := cmdutil.ShouldIncludeUninitialized(cmd, false)
b := f.NewBuilder(). b := f.NewBuilder().
Unstructured(). Unstructured().
@ -232,9 +248,8 @@ func (o AnnotateOptions) RunAnnotate(f cmdutil.Factory, cmd *cobra.Command) erro
if err != nil { if err != nil {
return err return err
} }
// If we should record change-cause, add it to new annotations if err := o.Recorder.Record(info.Object); err != nil {
if cmdutil.ContainsChangeCause(info) || o.recordChangeCause { glog.V(4).Infof("error recording current command: %v", err)
o.newAnnotations[kubectl.ChangeCauseAnnotation] = changeCause
} }
if err := o.updateAnnotations(obj); err != nil { if err := o.updateAnnotations(obj); err != nil {
return err return err

View File

@ -431,8 +431,8 @@ func TestAnnotateErrors(t *testing.T) {
for k, v := range testCase.flags { for k, v := range testCase.flags {
cmd.Flags().Set(k, v) cmd.Flags().Set(k, v)
} }
options := &AnnotateOptions{} options := NewAnnotateOptions(buf)
err := options.Complete(buf, cmd, testCase.args) err := options.Complete(tf, cmd, testCase.args)
if err == nil { if err == nil {
err = options.Validate() err = options.Validate()
} }
@ -488,9 +488,9 @@ func TestAnnotateObject(t *testing.T) {
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdAnnotate(tf, buf) cmd := NewCmdAnnotate(tf, buf)
cmd.SetOutput(buf) cmd.SetOutput(buf)
options := &AnnotateOptions{} options := NewAnnotateOptions(buf)
args := []string{"pods/foo", "a=b", "c-"} args := []string{"pods/foo", "a=b", "c-"}
if err := options.Complete(buf, cmd, args); err != nil { if err := options.Complete(tf, cmd, args); err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
if err := options.Validate(); err != nil { if err := options.Validate(); err != nil {
@ -542,10 +542,10 @@ func TestAnnotateObjectFromFile(t *testing.T) {
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdAnnotate(tf, buf) cmd := NewCmdAnnotate(tf, buf)
cmd.SetOutput(buf) cmd.SetOutput(buf)
options := &AnnotateOptions{} options := NewAnnotateOptions(buf)
options.Filenames = []string{"../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"} options.Filenames = []string{"../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}
args := []string{"a=b", "c-"} args := []string{"a=b", "c-"}
if err := options.Complete(buf, cmd, args); err != nil { if err := options.Complete(tf, cmd, args); err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
if err := options.Validate(); err != nil { if err := options.Validate(); err != nil {
@ -573,10 +573,11 @@ func TestAnnotateLocal(t *testing.T) {
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdAnnotate(tf, buf) cmd := NewCmdAnnotate(tf, buf)
options := &AnnotateOptions{local: true} options := NewAnnotateOptions(buf)
options.local = true
options.Filenames = []string{"../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"} options.Filenames = []string{"../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}
args := []string{"a=b"} args := []string{"a=b"}
if err := options.Complete(buf, cmd, args); err != nil { if err := options.Complete(tf, cmd, args); err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
if err := options.Validate(); err != nil { if err := options.Validate(); err != nil {
@ -629,9 +630,10 @@ func TestAnnotateMultipleObjects(t *testing.T) {
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdAnnotate(tf, buf) cmd := NewCmdAnnotate(tf, buf)
cmd.SetOutput(buf) cmd.SetOutput(buf)
options := &AnnotateOptions{all: true} options := NewAnnotateOptions(buf)
options.all = true
args := []string{"pods", "a=b", "c-"} args := []string{"pods", "a=b", "c-"}
if err := options.Complete(buf, cmd, args); err != nil { if err := options.Complete(tf, cmd, args); err != nil {
t.Fatalf("unexpected error: %v", err) t.Fatalf("unexpected error: %v", err)
} }
if err := options.Validate(); err != nil { if err := options.Validate(); err != nil {

View File

@ -45,16 +45,17 @@ import (
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi" "k8s.io/kubernetes/pkg/kubectl/cmd/util/openapi"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
"k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/kubectl/util/i18n"
) )
type ApplyOptions struct { type ApplyOptions struct {
RecordFlags *RecordFlags RecordFlags *genericclioptions.RecordFlags
FilenameOptions resource.FilenameOptions FilenameOptions resource.FilenameOptions
Recorder Recorder Recorder genericclioptions.Recorder
Selector string Selector string
Force bool Force bool
@ -111,7 +112,7 @@ var (
func NewApplyOptions(out, errout io.Writer) *ApplyOptions { func NewApplyOptions(out, errout io.Writer) *ApplyOptions {
return &ApplyOptions{ return &ApplyOptions{
RecordFlags: NewRecordFlags(), RecordFlags: genericclioptions.NewRecordFlags(),
Overwrite: true, Overwrite: true,
Cascade: true, Cascade: true,

View File

@ -18,7 +18,6 @@ package cmd
import ( import (
"io" "io"
"runtime"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -59,11 +58,8 @@ var (
) )
func NewCmdApplyEditLastApplied(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { func NewCmdApplyEditLastApplied(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
options := &editor.EditOptions{ o := editor.NewEditOptions(editor.ApplyEditMode, out, errOut)
EditMode: editor.ApplyEditMode,
Output: "yaml",
WindowsLineEndings: runtime.GOOS == "windows",
}
validArgs := cmdutil.ValidArgList(f) validArgs := cmdutil.ValidArgList(f)
cmd := &cobra.Command{ cmd := &cobra.Command{
@ -73,11 +69,10 @@ func NewCmdApplyEditLastApplied(f cmdutil.Factory, out, errOut io.Writer) *cobra
Long: applyEditLastAppliedLong, Long: applyEditLastAppliedLong,
Example: applyEditLastAppliedExample, Example: applyEditLastAppliedExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
options.ChangeCause = f.Command(cmd, false) if err := o.Complete(f, args, cmd); err != nil {
if err := options.Complete(f, out, errOut, args, cmd); err != nil {
cmdutil.CheckErr(err) cmdutil.CheckErr(err)
} }
if err := options.Run(); err != nil { if err := o.Run(); err != nil {
cmdutil.CheckErr(err) cmdutil.CheckErr(err)
} }
}, },
@ -85,12 +80,14 @@ func NewCmdApplyEditLastApplied(f cmdutil.Factory, out, errOut io.Writer) *cobra
ArgAliases: kubectl.ResourceAliases(validArgs), ArgAliases: kubectl.ResourceAliases(validArgs),
} }
// bind flag structs
o.RecordFlags.AddFlags(cmd)
usage := "to use to edit the resource" usage := "to use to edit the resource"
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage)
cmd.Flags().StringVarP(&options.Output, "output", "o", options.Output, "Output format. One of: yaml|json.") cmd.Flags().StringVarP(&o.Output, "output", "o", o.Output, "Output format. One of: yaml|json.")
cmd.Flags().BoolVar(&options.WindowsLineEndings, "windows-line-endings", options.WindowsLineEndings, cmd.Flags().BoolVar(&o.WindowsLineEndings, "windows-line-endings", o.WindowsLineEndings,
"Defaults to the line ending native to your platform.") "Defaults to the line ending native to your platform.")
cmdutil.AddRecordVarFlag(cmd, &options.Record)
cmdutil.AddIncludeUninitializedFlag(cmd) cmdutil.AddIncludeUninitializedFlag(cmd)
return cmd return cmd

View File

@ -54,6 +54,7 @@ type SetLastAppliedOptions struct {
Output string Output string
PatchBufferList []PatchBuffer PatchBufferList []PatchBuffer
Factory cmdutil.Factory Factory cmdutil.Factory
Out io.Writer Out io.Writer
ErrOut io.Writer ErrOut io.Writer
} }
@ -81,8 +82,15 @@ var (
`)) `))
) )
func NewCmdApplySetLastApplied(f cmdutil.Factory, out, err io.Writer) *cobra.Command { func NewSetLastAppliedOptions(out, errout io.Writer) *SetLastAppliedOptions {
options := &SetLastAppliedOptions{Out: out, ErrOut: err} return &SetLastAppliedOptions{
Out: out,
ErrOut: errout,
}
}
func NewCmdApplySetLastApplied(f cmdutil.Factory, out, errout io.Writer) *cobra.Command {
options := NewSetLastAppliedOptions(out, errout)
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "set-last-applied -f FILENAME", Use: "set-last-applied -f FILENAME",
DisableFlagsInUseLine: true, DisableFlagsInUseLine: true,
@ -97,7 +105,6 @@ func NewCmdApplySetLastApplied(f cmdutil.Factory, out, err io.Writer) *cobra.Com
} }
cmdutil.AddDryRunFlag(cmd) cmdutil.AddDryRunFlag(cmd)
cmdutil.AddRecordFlag(cmd)
cmdutil.AddPrinterFlags(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") 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" usage := "that contains the last-applied-configuration annotations"
@ -111,12 +118,9 @@ func (o *SetLastAppliedOptions) Complete(f cmdutil.Factory, cmd *cobra.Command)
o.Output = cmdutil.GetFlagString(cmd, "output") o.Output = cmdutil.GetFlagString(cmd, "output")
o.ShortOutput = o.Output == "name" o.ShortOutput = o.Output == "name"
var err error
o.Mapper, o.Typer = f.Object() o.Mapper, o.Typer = f.Object()
if err != nil {
return err
}
var err error
o.Namespace, o.EnforceNamespace, err = f.DefaultNamespace() o.Namespace, o.EnforceNamespace, err = f.DefaultNamespace()
return err return err
} }

View File

@ -24,9 +24,11 @@ import (
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/kubectl/util/i18n"
"github.com/golang/glog"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
@ -45,8 +47,22 @@ var (
kubectl autoscale rc foo --max=5 --cpu-percent=80`)) kubectl autoscale rc foo --max=5 --cpu-percent=80`))
) )
type AutoscaleOptions struct {
FilenameOptions resource.FilenameOptions
RecordFlags *genericclioptions.RecordFlags
Recorder genericclioptions.Recorder
}
func NewAutoscaleOptions() *AutoscaleOptions {
return &AutoscaleOptions{
FilenameOptions: resource.FilenameOptions{},
RecordFlags: genericclioptions.NewRecordFlags(),
}
}
func NewCmdAutoscale(f cmdutil.Factory, out io.Writer) *cobra.Command { func NewCmdAutoscale(f cmdutil.Factory, out io.Writer) *cobra.Command {
options := &resource.FilenameOptions{} o := NewAutoscaleOptions()
validArgs := []string{"deployment", "replicaset", "replicationcontroller"} validArgs := []string{"deployment", "replicaset", "replicationcontroller"}
argAliases := kubectl.ResourceAliases(validArgs) argAliases := kubectl.ResourceAliases(validArgs)
@ -58,12 +74,16 @@ func NewCmdAutoscale(f cmdutil.Factory, out io.Writer) *cobra.Command {
Long: autoscaleLong, Long: autoscaleLong,
Example: autoscaleExample, Example: autoscaleExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
err := RunAutoscale(f, out, cmd, args, options) cmdutil.CheckErr(o.Complete(f, cmd))
cmdutil.CheckErr(err) cmdutil.CheckErr(o.RunAutoscale(f, out, cmd, args))
}, },
ValidArgs: validArgs, ValidArgs: validArgs,
ArgAliases: argAliases, ArgAliases: argAliases,
} }
// bind flag structs
o.RecordFlags.AddFlags(cmd)
cmdutil.AddPrinterFlags(cmd) cmdutil.AddPrinterFlags(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().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("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.")
@ -73,14 +93,25 @@ func NewCmdAutoscale(f cmdutil.Factory, out io.Writer) *cobra.Command {
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().String("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) cmdutil.AddDryRunFlag(cmd)
usage := "identifying the resource to autoscale." usage := "identifying the resource to autoscale."
cmdutil.AddFilenameOptionFlags(cmd, options, usage) cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage)
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddRecordFlag(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd) cmdutil.AddInclude3rdPartyFlags(cmd)
return cmd return cmd
} }
func RunAutoscale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string, options *resource.FilenameOptions) error { func (o *AutoscaleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
o.RecordFlags.Complete(f.Command(cmd, false))
var err error
o.Recorder, err = o.RecordFlags.ToRecorder()
if err != nil {
return err
}
return nil
}
func (o *AutoscaleOptions) RunAutoscale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []string) error {
namespace, enforceNamespace, err := f.DefaultNamespace() namespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
@ -95,7 +126,7 @@ func RunAutoscale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s
Internal(). Internal().
ContinueOnError(). ContinueOnError().
NamespaceParam(namespace).DefaultNamespace(). NamespaceParam(namespace).DefaultNamespace().
FilenameParam(enforceNamespace, options). FilenameParam(enforceNamespace, &o.FilenameOptions).
ResourceTypeOrNameArgs(false, args...). ResourceTypeOrNameArgs(false, args...).
Flatten(). Flatten().
Do() Do()
@ -149,11 +180,8 @@ func RunAutoscale(f cmdutil.Factory, out io.Writer, cmd *cobra.Command, args []s
if err != nil { if err != nil {
return err return err
} }
if cmdutil.ShouldRecord(cmd, hpa) { if err := o.Recorder.Record(hpa.Object); err != nil {
if err := cmdutil.RecordChangeCause(hpa.Object, f.Command(cmd, false)); err != nil { glog.V(4).Infof("error recording current command: %v", err)
return err
}
object = hpa.Object
} }
if cmdutil.GetDryRunFlag(cmd) { if cmdutil.GetDryRunFlag(cmd) {
return cmdutil.PrintObject(cmd, object, out) return cmdutil.PrintObject(cmd, object, out)

View File

@ -27,9 +27,11 @@ go_library(
"//pkg/kubectl/cmd/templates:go_default_library", "//pkg/kubectl/cmd/templates:go_default_library",
"//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/cmd/util:go_default_library",
"//pkg/kubectl/cmd/util/editor:go_default_library", "//pkg/kubectl/cmd/util/editor:go_default_library",
"//pkg/kubectl/genericclioptions:go_default_library",
"//pkg/kubectl/resource:go_default_library", "//pkg/kubectl/resource:go_default_library",
"//pkg/kubectl/util/i18n:go_default_library", "//pkg/kubectl/util/i18n:go_default_library",
"//pkg/printers:go_default_library", "//pkg/printers:go_default_library",
"//vendor/github.com/golang/glog:go_default_library",
"//vendor/github.com/spf13/cobra:go_default_library", "//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/k8s.io/api/batch/v1:go_default_library", "//vendor/k8s.io/api/batch/v1:go_default_library",
"//vendor/k8s.io/api/batch/v1beta1:go_default_library", "//vendor/k8s.io/api/batch/v1beta1:go_default_library",

View File

@ -27,6 +27,7 @@ import (
"net/url" "net/url"
"github.com/golang/glog"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
kruntime "k8s.io/apimachinery/pkg/runtime" kruntime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/runtime/schema"
@ -34,13 +35,14 @@ import (
"k8s.io/kubernetes/pkg/kubectl/cmd/templates" "k8s.io/kubernetes/pkg/kubectl/cmd/templates"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/cmd/util/editor" "k8s.io/kubernetes/pkg/kubectl/cmd/util/editor"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/kubectl/util/i18n" "k8s.io/kubernetes/pkg/kubectl/util/i18n"
) )
type CreateOptions struct { type CreateOptions struct {
PrintFlags *PrintFlags PrintFlags *PrintFlags
PrintObj func(obj kruntime.Object) error RecordFlags *genericclioptions.RecordFlags
DryRun bool DryRun bool
@ -50,6 +52,9 @@ type CreateOptions struct {
Raw string Raw string
Out io.Writer Out io.Writer
ErrOut io.Writer ErrOut io.Writer
Recorder genericclioptions.Recorder
PrintObj func(obj kruntime.Object) error
} }
var ( var (
@ -69,13 +74,18 @@ var (
kubectl create -f docker-registry.yaml --edit -o json`)) kubectl create -f docker-registry.yaml --edit -o json`))
) )
func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { func NewCreateOptions(out, errOut io.Writer) *CreateOptions {
options := &CreateOptions{ return &CreateOptions{
PrintFlags: NewPrintFlags("created"), PrintFlags: NewPrintFlags("created"),
RecordFlags: genericclioptions.NewRecordFlags(),
Out: out, Out: out,
ErrOut: errOut, ErrOut: errOut,
} }
}
func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
o := NewCreateOptions(out, errOut)
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "create -f FILENAME", Use: "create -f FILENAME",
@ -84,32 +94,34 @@ func NewCmdCreate(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
Long: createLong, Long: createLong,
Example: createExample, Example: createExample,
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
if cmdutil.IsFilenameSliceEmpty(options.FilenameOptions.Filenames) { if cmdutil.IsFilenameSliceEmpty(o.FilenameOptions.Filenames) {
defaultRunFunc := cmdutil.DefaultSubCommandRun(errOut) defaultRunFunc := cmdutil.DefaultSubCommandRun(errOut)
defaultRunFunc(cmd, args) defaultRunFunc(cmd, args)
return return
} }
cmdutil.CheckErr(options.Complete(cmd)) cmdutil.CheckErr(o.Complete(f, cmd))
cmdutil.CheckErr(options.ValidateArgs(cmd, args)) cmdutil.CheckErr(o.ValidateArgs(cmd, args))
cmdutil.CheckErr(options.RunCreate(f, cmd)) cmdutil.CheckErr(o.RunCreate(f, cmd))
}, },
} }
// bind flag structs
o.RecordFlags.AddFlags(cmd)
usage := "to use to create the resource" usage := "to use to create the resource"
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage)
cmd.MarkFlagRequired("filename") cmd.MarkFlagRequired("filename")
cmdutil.AddValidateFlags(cmd) cmdutil.AddValidateFlags(cmd)
cmd.Flags().BoolVar(&options.EditBeforeCreate, "edit", options.EditBeforeCreate, "Edit the API resource before creating") cmd.Flags().BoolVar(&o.EditBeforeCreate, "edit", o.EditBeforeCreate, "Edit the API resource before creating")
cmd.Flags().Bool("windows-line-endings", runtime.GOOS == "windows", cmd.Flags().Bool("windows-line-endings", runtime.GOOS == "windows",
"Only relevant if --edit=true. Defaults to the line ending native to your platform.") "Only relevant if --edit=true. Defaults to the line ending native to your platform.")
cmdutil.AddApplyAnnotationFlags(cmd) cmdutil.AddApplyAnnotationFlags(cmd)
cmdutil.AddRecordFlag(cmd)
cmdutil.AddDryRunFlag(cmd) cmdutil.AddDryRunFlag(cmd)
cmdutil.AddInclude3rdPartyFlags(cmd) cmdutil.AddInclude3rdPartyFlags(cmd)
cmd.Flags().StringVarP(&options.Selector, "selector", "l", options.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)") cmd.Flags().StringVarP(&o.Selector, "selector", "l", o.Selector, "Selector (label query) to filter on, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2)")
cmd.Flags().StringVar(&options.Raw, "raw", options.Raw, "Raw URI to POST to the server. Uses the transport specified by the kubeconfig file.") cmd.Flags().StringVar(&o.Raw, "raw", o.Raw, "Raw URI to POST to the server. Uses the transport specified by the kubeconfig file.")
options.PrintFlags.AddFlags(cmd) o.PrintFlags.AddFlags(cmd)
// create subcommands // create subcommands
cmd.AddCommand(NewCmdCreateNamespace(f, out)) cmd.AddCommand(NewCmdCreateNamespace(f, out))
@ -160,7 +172,15 @@ func (o *CreateOptions) ValidateArgs(cmd *cobra.Command, args []string) error {
return nil return nil
} }
func (o *CreateOptions) Complete(cmd *cobra.Command) error { func (o *CreateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
o.RecordFlags.Complete(f.Command(cmd, false))
var err error
o.Recorder, err = o.RecordFlags.ToRecorder()
if err != nil {
return err
}
o.DryRun = cmdutil.GetDryRunFlag(cmd) o.DryRun = cmdutil.GetDryRunFlag(cmd)
if o.DryRun { if o.DryRun {
@ -186,7 +206,7 @@ func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error {
} }
if o.EditBeforeCreate { if o.EditBeforeCreate {
return RunEditOnCreate(f, o.Out, o.ErrOut, cmd, &o.FilenameOptions) return RunEditOnCreate(f, o.RecordFlags, o.Out, o.ErrOut, cmd, &o.FilenameOptions)
} }
schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate")) schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"))
if err != nil { if err != nil {
@ -221,10 +241,8 @@ func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error {
return cmdutil.AddSourceToErr("creating", info.Source, err) return cmdutil.AddSourceToErr("creating", info.Source, err)
} }
if cmdutil.ShouldRecord(cmd, info) { if err := o.Recorder.Record(info.Object); err != nil {
if err := cmdutil.RecordChangeCause(info.Object, f.Command(cmd, false)); err != nil { glog.V(4).Infof("error recording current command: %v", err)
return cmdutil.AddSourceToErr("creating", info.Source, err)
}
} }
if !o.DryRun { if !o.DryRun {
@ -273,21 +291,18 @@ func (o *CreateOptions) raw(f cmdutil.Factory) error {
return nil return nil
} }
func RunEditOnCreate(f cmdutil.Factory, out, errOut io.Writer, cmd *cobra.Command, options *resource.FilenameOptions) error { func RunEditOnCreate(f cmdutil.Factory, recordFlags *genericclioptions.RecordFlags, out, errOut io.Writer, cmd *cobra.Command, options *resource.FilenameOptions) error {
editOptions := &editor.EditOptions{ editOptions := editor.NewEditOptions(editor.EditBeforeCreateMode, out, errOut)
EditMode: editor.EditBeforeCreateMode, editOptions.FilenameOptions = *options
FilenameOptions: *options, editOptions.ValidateOptions = cmdutil.ValidateOptions{
ValidateOptions: cmdutil.ValidateOptions{
EnableValidation: cmdutil.GetFlagBool(cmd, "validate"), EnableValidation: cmdutil.GetFlagBool(cmd, "validate"),
},
Output: cmdutil.GetFlagString(cmd, "output"),
WindowsLineEndings: cmdutil.GetFlagBool(cmd, "windows-line-endings"),
ApplyAnnotation: cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag),
Record: cmdutil.GetFlagBool(cmd, "record"),
ChangeCause: f.Command(cmd, false),
Include3rdParty: cmdutil.GetFlagBool(cmd, "include-extended-apis"),
} }
err := editOptions.Complete(f, out, errOut, []string{}, cmd) editOptions.Output = cmdutil.GetFlagString(cmd, "output")
editOptions.ApplyAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
editOptions.RecordFlags = recordFlags
editOptions.Include3rdParty = cmdutil.GetFlagBool(cmd, "include-extended-apis")
err := editOptions.Complete(f, []string{}, cmd)
if err != nil { if err != nil {
return err return err
} }

View File

@ -19,7 +19,6 @@ package cmd
import ( import (
"fmt" "fmt"
"io" "io"
"runtime"
"github.com/spf13/cobra" "github.com/spf13/cobra"
@ -70,13 +69,10 @@ var (
) )
func NewCmdEdit(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command { func NewCmdEdit(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
options := &editor.EditOptions{ o := editor.NewEditOptions(editor.NormalEditMode, out, errOut)
EditMode: editor.NormalEditMode, o.ValidateOptions = cmdutil.ValidateOptions{EnableValidation: true}
Output: "yaml", o.Include3rdParty = true
WindowsLineEndings: runtime.GOOS == "windows",
ValidateOptions: cmdutil.ValidateOptions{EnableValidation: true},
Include3rdParty: true,
}
validArgs := cmdutil.ValidArgList(f) validArgs := cmdutil.ValidArgList(f)
cmd := &cobra.Command{ cmd := &cobra.Command{
@ -86,28 +82,30 @@ func NewCmdEdit(f cmdutil.Factory, out, errOut io.Writer) *cobra.Command {
Long: editLong, Long: editLong,
Example: fmt.Sprintf(editExample), Example: fmt.Sprintf(editExample),
Run: func(cmd *cobra.Command, args []string) { Run: func(cmd *cobra.Command, args []string) {
options.ChangeCause = f.Command(cmd, false) if err := o.Complete(f, args, cmd); err != nil {
if err := options.Complete(f, out, errOut, args, cmd); err != nil {
cmdutil.CheckErr(err) cmdutil.CheckErr(err)
} }
if err := options.Run(); err != nil { if err := o.Run(); err != nil {
cmdutil.CheckErr(err) cmdutil.CheckErr(err)
} }
}, },
ValidArgs: validArgs, ValidArgs: validArgs,
ArgAliases: kubectl.ResourceAliases(validArgs), ArgAliases: kubectl.ResourceAliases(validArgs),
} }
// bind flag structs
o.RecordFlags.AddFlags(cmd)
usage := "to use to edit the resource" usage := "to use to edit the resource"
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage)
cmdutil.AddValidateOptionFlags(cmd, &options.ValidateOptions) cmdutil.AddValidateOptionFlags(cmd, &o.ValidateOptions)
cmd.Flags().StringVarP(&options.Output, "output", "o", options.Output, "Output format. One of: yaml|json.") cmd.Flags().StringVarP(&o.Output, "output", "o", o.Output, "Output format. One of: yaml|json.")
cmd.Flags().BoolVarP(&options.OutputPatch, "output-patch", "", options.OutputPatch, "Output the patch if the resource is edited.") cmd.Flags().BoolVarP(&o.OutputPatch, "output-patch", "", o.OutputPatch, "Output the patch if the resource is edited.")
cmd.Flags().BoolVar(&options.WindowsLineEndings, "windows-line-endings", options.WindowsLineEndings, cmd.Flags().BoolVar(&o.WindowsLineEndings, "windows-line-endings", o.WindowsLineEndings,
"Defaults to the line ending native to your platform.") "Defaults to the line ending native to your platform.")
cmdutil.AddApplyAnnotationVarFlags(cmd, &options.ApplyAnnotation) cmdutil.AddApplyAnnotationVarFlags(cmd, &o.ApplyAnnotation)
cmdutil.AddRecordVarFlag(cmd, &options.Record) cmdutil.AddInclude3rdPartyVarFlags(cmd, &o.Include3rdParty)
cmdutil.AddInclude3rdPartyVarFlags(cmd, &options.Include3rdParty)
cmdutil.AddIncludeUninitializedFlag(cmd) cmdutil.AddIncludeUninitializedFlag(cmd)
return cmd return cmd
} }

View File

@ -1,10 +1,5 @@
{ {
"data": { "data": {
"new-data3": "newivalue" "new-data3": "newivalue"
},
"metadata": {
"annotations": {
"kubernetes.io/change-cause": "edit test cmd invocation"
}
} }
} }

View File

@ -1,8 +1,5 @@
{ {
"metadata": { "metadata": {
"annotations": {
"kubernetes.io/change-cause": "edit test cmd invocation"
},
"labels": { "labels": {
"new-label2": "foo2" "new-label2": "foo2"
} }

View File

@ -18,6 +18,7 @@ go_library(
"//pkg/apis/core:go_default_library", "//pkg/apis/core:go_default_library",
"//pkg/kubectl:go_default_library", "//pkg/kubectl:go_default_library",
"//pkg/kubectl/cmd/util:go_default_library", "//pkg/kubectl/cmd/util:go_default_library",
"//pkg/kubectl/genericclioptions:go_default_library",
"//pkg/kubectl/resource:go_default_library", "//pkg/kubectl/resource:go_default_library",
"//pkg/kubectl/scheme:go_default_library", "//pkg/kubectl/scheme:go_default_library",
"//pkg/kubectl/util/crlf:go_default_library", "//pkg/kubectl/util/crlf:go_default_library",

View File

@ -25,6 +25,7 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"reflect" "reflect"
goruntime "runtime"
"strings" "strings"
"github.com/evanphx/json-patch" "github.com/evanphx/json-patch"
@ -44,6 +45,7 @@ import (
api "k8s.io/kubernetes/pkg/apis/core" api "k8s.io/kubernetes/pkg/apis/core"
"k8s.io/kubernetes/pkg/kubectl" "k8s.io/kubernetes/pkg/kubectl"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util" cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/genericclioptions"
"k8s.io/kubernetes/pkg/kubectl/resource" "k8s.io/kubernetes/pkg/kubectl/resource"
"k8s.io/kubernetes/pkg/kubectl/scheme" "k8s.io/kubernetes/pkg/kubectl/scheme"
"k8s.io/kubernetes/pkg/kubectl/util/crlf" "k8s.io/kubernetes/pkg/kubectl/util/crlf"
@ -53,6 +55,7 @@ import (
// EditOptions contains all the options for running edit cli command. // EditOptions contains all the options for running edit cli command.
type EditOptions struct { type EditOptions struct {
resource.FilenameOptions resource.FilenameOptions
RecordFlags *genericclioptions.RecordFlags
Output string Output string
OutputPatch bool OutputPatch bool
@ -67,18 +70,32 @@ type EditOptions struct {
CmdNamespace string CmdNamespace string
ApplyAnnotation bool ApplyAnnotation bool
Record bool
ChangeCause string ChangeCause string
Include3rdParty bool Include3rdParty bool
Out io.Writer Out io.Writer
ErrOut io.Writer ErrOut io.Writer
Recorder genericclioptions.Recorder
f cmdutil.Factory f cmdutil.Factory
editPrinterOptions *editPrinterOptions editPrinterOptions *editPrinterOptions
updatedResultGetter func(data []byte) *resource.Result updatedResultGetter func(data []byte) *resource.Result
} }
func NewEditOptions(editMode EditMode, out, errOut io.Writer) *EditOptions {
return &EditOptions{
RecordFlags: genericclioptions.NewRecordFlags(),
EditMode: editMode,
Output: "yaml",
WindowsLineEndings: goruntime.GOOS == "windows",
Out: out,
ErrOut: errOut,
}
}
type editPrinterOptions struct { type editPrinterOptions struct {
printer printers.ResourcePrinter printer printers.ResourcePrinter
ext string ext string
@ -86,7 +103,15 @@ type editPrinterOptions struct {
} }
// Complete completes all the required options // Complete completes all the required options
func (o *EditOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args []string, cmd *cobra.Command) error { func (o *EditOptions) Complete(f cmdutil.Factory, args []string, cmd *cobra.Command) error {
o.RecordFlags.Complete(f.Command(cmd, false))
var err error
o.Recorder, err = o.RecordFlags.ToRecorder()
if err != nil {
return err
}
if o.EditMode != NormalEditMode && o.EditMode != EditBeforeCreateMode && o.EditMode != ApplyEditMode { if o.EditMode != NormalEditMode && o.EditMode != EditBeforeCreateMode && o.EditMode != ApplyEditMode {
return fmt.Errorf("unsupported edit mode %q", o.EditMode) return fmt.Errorf("unsupported edit mode %q", o.EditMode)
} }
@ -138,10 +163,6 @@ func (o *EditOptions) Complete(f cmdutil.Factory, out, errOut io.Writer, args []
o.CmdNamespace = cmdNamespace o.CmdNamespace = cmdNamespace
o.f = f o.f = f
// Set up writer
o.Out = out
o.ErrOut = errOut
return nil return nil
} }
@ -609,10 +630,8 @@ func (o *EditOptions) visitAnnotation(annotationVisitor resource.Visitor) error
return err return err
} }
} }
if o.Record || cmdutil.ContainsChangeCause(info) { if err := o.Recorder.Record(info.Object); err != nil {
if err := cmdutil.RecordChangeCause(info.Object, o.ChangeCause); err != nil { glog.V(4).Infof("error recording current command: %v", err)
return err
}
} }
return nil return nil

View File

@ -0,0 +1,30 @@
load("@io_bazel_rules_go//go:def.bzl", "go_library")
go_library(
name = "go_default_library",
srcs = [
"doc.go",
"record_flags.go",
],
importpath = "k8s.io/kubernetes/pkg/kubectl/genericclioptions",
visibility = ["//visibility:public"],
deps = [
"//vendor/github.com/spf13/cobra:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
],
)
filegroup(
name = "package-srcs",
srcs = glob(["**"]),
tags = ["automanaged"],
visibility = ["//visibility:private"],
)
filegroup(
name = "all-srcs",
srcs = [":package-srcs"],
tags = ["automanaged"],
visibility = ["//visibility:public"],
)