wire printflags through set cmds

parent f79ab9c1
...@@ -20,6 +20,8 @@ import ( ...@@ -20,6 +20,8 @@ import (
"fmt" "fmt"
"io" "io"
"k8s.io/kubernetes/pkg/printers"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
...@@ -36,12 +38,13 @@ import ( ...@@ -36,12 +38,13 @@ import (
type ImageOptions struct { type ImageOptions struct {
resource.FilenameOptions resource.FilenameOptions
PrintFlags *printers.PrintFlags
Infos []*resource.Info Infos []*resource.Info
Selector string Selector string
Out io.Writer Out io.Writer
Err io.Writer Err io.Writer
DryRun bool DryRun bool
ShortOutput bool
All bool All bool
Record bool Record bool
Output string Output string
...@@ -50,6 +53,8 @@ type ImageOptions struct { ...@@ -50,6 +53,8 @@ type ImageOptions struct {
Cmd *cobra.Command Cmd *cobra.Command
ResolveImage func(in string) (string, error) ResolveImage func(in string) (string, error)
PrintObj func(runtime.Object) error
UpdatePodSpecForObject func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error) UpdatePodSpecForObject func(obj runtime.Object, fn func(*v1.PodSpec) error) (bool, error)
Resources []string Resources []string
ContainerImages map[string]string ContainerImages map[string]string
...@@ -81,6 +86,8 @@ var ( ...@@ -81,6 +86,8 @@ var (
func NewCmdImage(f cmdutil.Factory, out, err io.Writer) *cobra.Command { func NewCmdImage(f cmdutil.Factory, out, err io.Writer) *cobra.Command {
options := &ImageOptions{ options := &ImageOptions{
PrintFlags: printers.NewPrintFlags("image updated"),
Out: out, Out: out,
Err: err, Err: err,
} }
...@@ -98,7 +105,8 @@ func NewCmdImage(f cmdutil.Factory, out, err io.Writer) *cobra.Command { ...@@ -98,7 +105,8 @@ func NewCmdImage(f cmdutil.Factory, out, err io.Writer) *cobra.Command {
}, },
} }
cmdutil.AddPrinterFlags(cmd) options.PrintFlags.AddFlags(cmd)
usage := "identifying the resource to get from a server." usage := "identifying the resource to get from a server."
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) 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().BoolVar(&options.All, "all", options.All, "Select all resources, including uninitialized ones, in the namespace of the specified resource types")
...@@ -112,7 +120,6 @@ func NewCmdImage(f cmdutil.Factory, out, err io.Writer) *cobra.Command { ...@@ -112,7 +120,6 @@ func NewCmdImage(f cmdutil.Factory, out, err io.Writer) *cobra.Command {
func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
o.UpdatePodSpecForObject = f.UpdatePodSpecForObject o.UpdatePodSpecForObject = f.UpdatePodSpecForObject
o.ShortOutput = cmdutil.GetFlagString(cmd, "output") == "name"
o.Record = cmdutil.GetRecordFlag(cmd) o.Record = cmdutil.GetRecordFlag(cmd)
o.ChangeCause = f.Command(cmd, false) o.ChangeCause = f.Command(cmd, false)
o.DryRun = cmdutil.GetDryRunFlag(cmd) o.DryRun = cmdutil.GetDryRunFlag(cmd)
...@@ -120,6 +127,17 @@ func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st ...@@ -120,6 +127,17 @@ func (o *ImageOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
o.ResolveImage = f.ResolveImage o.ResolveImage = f.ResolveImage
o.Cmd = cmd o.Cmd = cmd
o.PrintFlags.Complete(o.DryRun)
printer, err := o.PrintFlags.ToPrinter()
if err != nil {
return err
}
o.PrintObj = func(obj runtime.Object) error {
return printer.PrintObj(obj, o.Out)
}
cmdNamespace, enforceNamespace, err := f.DefaultNamespace() cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
...@@ -232,18 +250,18 @@ func (o *ImageOptions) Run() error { ...@@ -232,18 +250,18 @@ func (o *ImageOptions) Run() error {
continue continue
} }
// no changes
if string(patch.Patch) == "{}" || len(patch.Patch) == 0 {
continue
}
if o.Local || o.DryRun { if o.Local || o.DryRun {
if err := cmdutil.PrintObject(o.Cmd, patch.Info.AsVersioned(), o.Out); err != nil { if err := o.PrintObj(patch.Info.AsVersioned()); err != nil {
return err return err
} }
continue continue
} }
// no changes
if string(patch.Patch) == "{}" || len(patch.Patch) == 0 {
continue
}
// patch the change // patch the change
obj, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch) obj, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch)
if err != nil { if err != nil {
...@@ -263,13 +281,9 @@ func (o *ImageOptions) Run() error { ...@@ -263,13 +281,9 @@ func (o *ImageOptions) Run() error {
info.Refresh(obj, true) info.Refresh(obj, true)
if len(o.Output) > 0 { if err := o.PrintObj(info.AsVersioned()); err != nil {
if err := cmdutil.PrintObject(o.Cmd, info.AsVersioned(), o.Out); err != nil { return err
return err
}
continue
} }
cmdutil.PrintSuccess(o.ShortOutput, o.Out, info.Object, o.DryRun, "image updated")
} }
return utilerrors.NewAggregate(allErrs) return utilerrors.NewAggregate(allErrs)
} }
......
...@@ -25,6 +25,8 @@ import ( ...@@ -25,6 +25,8 @@ import (
"strings" "strings"
"testing" "testing"
"k8s.io/kubernetes/pkg/printers"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1" appsv1 "k8s.io/api/apps/v1"
appsv1beta1 "k8s.io/api/apps/v1beta1" appsv1beta1 "k8s.io/api/apps/v1beta1"
...@@ -61,14 +63,23 @@ func TestImageLocal(t *testing.T) { ...@@ -61,14 +63,23 @@ func TestImageLocal(t *testing.T) {
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}}
outputFormat := "name"
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdImage(tf, buf, buf) cmd := NewCmdImage(tf, buf, buf)
cmd.SetOutput(buf) cmd.SetOutput(buf)
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", outputFormat)
cmd.Flags().Set("local", "true") cmd.Flags().Set("local", "true")
opts := ImageOptions{FilenameOptions: resource.FilenameOptions{ opts := ImageOptions{
Filenames: []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}}, PrintFlags: &printers.PrintFlags{
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
NamePrintFlags: printers.NewNamePrintFlags("", false),
OutputFormat: &outputFormat,
},
FilenameOptions: resource.FilenameOptions{
Filenames: []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}},
Out: buf, Out: buf,
Local: true} Local: true}
err := opts.Complete(tf, cmd, []string{"cassandra=thingy"}) err := opts.Complete(tf, cmd, []string{"cassandra=thingy"})
...@@ -87,6 +98,11 @@ func TestImageLocal(t *testing.T) { ...@@ -87,6 +98,11 @@ func TestImageLocal(t *testing.T) {
} }
func TestSetImageValidation(t *testing.T) { func TestSetImageValidation(t *testing.T) {
printFlags := &printers.PrintFlags{
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
NamePrintFlags: printers.NewNamePrintFlags("", false),
}
testCases := []struct { testCases := []struct {
name string name string
imageOptions *ImageOptions imageOptions *ImageOptions
...@@ -94,13 +110,14 @@ func TestSetImageValidation(t *testing.T) { ...@@ -94,13 +110,14 @@ func TestSetImageValidation(t *testing.T) {
}{ }{
{ {
name: "test resource < 1 and filenames empty", name: "test resource < 1 and filenames empty",
imageOptions: &ImageOptions{}, imageOptions: &ImageOptions{PrintFlags: printFlags},
expectErr: "[one or more resources must be specified as <resource> <name> or <resource>/<name>, at least one image update is required]", expectErr: "[one or more resources must be specified as <resource> <name> or <resource>/<name>, at least one image update is required]",
}, },
{ {
name: "test containerImages < 1", name: "test containerImages < 1",
imageOptions: &ImageOptions{ imageOptions: &ImageOptions{
Resources: []string{"a", "b", "c"}, PrintFlags: printFlags,
Resources: []string{"a", "b", "c"},
FilenameOptions: resource.FilenameOptions{ FilenameOptions: resource.FilenameOptions{
Filenames: []string{"testFile"}, Filenames: []string{"testFile"},
...@@ -111,7 +128,8 @@ func TestSetImageValidation(t *testing.T) { ...@@ -111,7 +128,8 @@ func TestSetImageValidation(t *testing.T) {
{ {
name: "test containerImages > 1 and all containers are already specified by *", name: "test containerImages > 1 and all containers are already specified by *",
imageOptions: &ImageOptions{ imageOptions: &ImageOptions{
Resources: []string{"a", "b", "c"}, PrintFlags: printFlags,
Resources: []string{"a", "b", "c"},
FilenameOptions: resource.FilenameOptions{ FilenameOptions: resource.FilenameOptions{
Filenames: []string{"testFile"}, Filenames: []string{"testFile"},
}, },
...@@ -125,7 +143,8 @@ func TestSetImageValidation(t *testing.T) { ...@@ -125,7 +143,8 @@ func TestSetImageValidation(t *testing.T) {
{ {
name: "success case", name: "success case",
imageOptions: &ImageOptions{ imageOptions: &ImageOptions{
Resources: []string{"a", "b", "c"}, PrintFlags: printFlags,
Resources: []string{"a", "b", "c"},
FilenameOptions: resource.FilenameOptions{ FilenameOptions: resource.FilenameOptions{
Filenames: []string{"testFile"}, Filenames: []string{"testFile"},
}, },
...@@ -166,14 +185,23 @@ func TestSetMultiResourcesImageLocal(t *testing.T) { ...@@ -166,14 +185,23 @@ func TestSetMultiResourcesImageLocal(t *testing.T) {
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}}
outputFormat := "name"
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdImage(tf, buf, buf) cmd := NewCmdImage(tf, buf, buf)
cmd.SetOutput(buf) cmd.SetOutput(buf)
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", outputFormat)
cmd.Flags().Set("local", "true") cmd.Flags().Set("local", "true")
opts := ImageOptions{FilenameOptions: resource.FilenameOptions{ opts := ImageOptions{
Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}}, PrintFlags: &printers.PrintFlags{
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
NamePrintFlags: printers.NewNamePrintFlags("", false),
OutputFormat: &outputFormat,
},
FilenameOptions: resource.FilenameOptions{
Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}},
Out: buf, Out: buf,
Local: true} Local: true}
err := opts.Complete(tf, cmd, []string{"*=thingy"}) err := opts.Complete(tf, cmd, []string{"*=thingy"})
...@@ -552,11 +580,21 @@ func TestSetImageRemote(t *testing.T) { ...@@ -552,11 +580,21 @@ func TestSetImageRemote(t *testing.T) {
}), }),
VersionedAPIPath: path.Join(input.apiPrefix, testapi.Default.GroupVersion().String()), VersionedAPIPath: path.Join(input.apiPrefix, testapi.Default.GroupVersion().String()),
} }
outputFormat := "yaml"
out := new(bytes.Buffer) out := new(bytes.Buffer)
cmd := NewCmdImage(tf, out, out) cmd := NewCmdImage(tf, out, out)
cmd.SetOutput(out) cmd.SetOutput(out)
cmd.Flags().Set("output", "yaml") cmd.Flags().Set("output", outputFormat)
opts := ImageOptions{ opts := ImageOptions{
PrintFlags: &printers.PrintFlags{
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
NamePrintFlags: printers.NewNamePrintFlags("", false),
OutputFormat: &outputFormat,
},
Out: out, Out: out,
Local: false} Local: false}
err := opts.Complete(tf, cmd, input.args) err := opts.Complete(tf, cmd, input.args)
......
...@@ -21,6 +21,8 @@ import ( ...@@ -21,6 +21,8 @@ import (
"io" "io"
"strings" "strings"
"k8s.io/kubernetes/pkg/printers"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
...@@ -61,6 +63,8 @@ var ( ...@@ -61,6 +63,8 @@ var (
type ResourcesOptions struct { type ResourcesOptions struct {
resource.FilenameOptions resource.FilenameOptions
PrintFlags *printers.PrintFlags
Infos []*resource.Info Infos []*resource.Info
Out io.Writer Out io.Writer
Err io.Writer Err io.Writer
...@@ -73,6 +77,10 @@ type ResourcesOptions struct { ...@@ -73,6 +77,10 @@ type ResourcesOptions struct {
Local bool Local bool
Cmd *cobra.Command Cmd *cobra.Command
DryRun bool
PrintObj func(runtime.Object) error
Limits string Limits string
Requests string Requests string
ResourceRequirements v1.ResourceRequirements ResourceRequirements v1.ResourceRequirements
...@@ -85,6 +93,8 @@ type ResourcesOptions struct { ...@@ -85,6 +93,8 @@ type ResourcesOptions struct {
// pod templates are selected by default. // pod templates are selected by default.
func NewResourcesOptions(out io.Writer, errOut io.Writer) *ResourcesOptions { func NewResourcesOptions(out io.Writer, errOut io.Writer) *ResourcesOptions {
return &ResourcesOptions{ return &ResourcesOptions{
PrintFlags: printers.NewPrintFlags("resource requirements updated"),
Out: out, Out: out,
Err: errOut, Err: errOut,
ContainerSelector: "*", ContainerSelector: "*",
...@@ -112,7 +122,8 @@ func NewCmdResources(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra. ...@@ -112,7 +122,8 @@ func NewCmdResources(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.
}, },
} }
cmdutil.AddPrinterFlags(cmd) options.PrintFlags.AddFlags(cmd)
//usage := "Filename, directory, or URL to a file identifying the resource to get from the server" //usage := "Filename, directory, or URL to a file identifying the resource to get from the server"
//kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage) //kubectl.AddJsonFilenameFlag(cmd, &options.Filenames, usage)
usage := "identifying the resource to get from a server." usage := "identifying the resource to get from a server."
...@@ -135,6 +146,18 @@ func (o *ResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args ...@@ -135,6 +146,18 @@ func (o *ResourcesOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
o.Record = cmdutil.GetRecordFlag(cmd) o.Record = cmdutil.GetRecordFlag(cmd)
o.ChangeCause = f.Command(cmd, false) o.ChangeCause = f.Command(cmd, false)
o.Cmd = cmd o.Cmd = cmd
o.DryRun = cmdutil.GetDryRunFlag(o.Cmd)
o.PrintFlags.Complete(o.DryRun)
printer, err := o.PrintFlags.ToPrinter()
if err != nil {
return err
}
o.PrintObj = func(obj runtime.Object) error {
return printer.PrintObj(obj, o.Out)
}
cmdNamespace, enforceNamespace, err := f.DefaultNamespace() cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil { if err != nil {
...@@ -238,8 +261,8 @@ func (o *ResourcesOptions) Run() error { ...@@ -238,8 +261,8 @@ func (o *ResourcesOptions) Run() error {
continue continue
} }
if o.Local || cmdutil.GetDryRunFlag(o.Cmd) { if o.Local || o.DryRun {
if err := cmdutil.PrintObject(o.Cmd, patch.Info.AsVersioned(), o.Out); err != nil { if err := o.PrintObj(patch.Info.AsVersioned()); err != nil {
return err return err
} }
continue continue
...@@ -262,14 +285,9 @@ func (o *ResourcesOptions) Run() error { ...@@ -262,14 +285,9 @@ func (o *ResourcesOptions) Run() error {
} }
info.Refresh(obj, true) info.Refresh(obj, true)
shortOutput := o.Output == "name" if err := o.PrintObj(info.AsVersioned()); err != nil {
if len(o.Output) > 0 && !shortOutput { return err
if err := cmdutil.PrintObject(o.Cmd, info.AsVersioned(), o.Out); err != nil {
return err
}
continue
} }
cmdutil.PrintSuccess(shortOutput, o.Out, info.Object, false, "resource requirements updated")
} }
return utilerrors.NewAggregate(allErrs) return utilerrors.NewAggregate(allErrs)
} }
...@@ -25,6 +25,8 @@ import ( ...@@ -25,6 +25,8 @@ import (
"strings" "strings"
"testing" "testing"
"k8s.io/kubernetes/pkg/printers"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1" appsv1 "k8s.io/api/apps/v1"
appsv1beta1 "k8s.io/api/apps/v1beta1" appsv1beta1 "k8s.io/api/apps/v1beta1"
...@@ -60,14 +62,23 @@ func TestResourcesLocal(t *testing.T) { ...@@ -60,14 +62,23 @@ func TestResourcesLocal(t *testing.T) {
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}}
outputFormat := "name"
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdResources(tf, buf, buf) cmd := NewCmdResources(tf, buf, buf)
cmd.SetOutput(buf) cmd.SetOutput(buf)
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", outputFormat)
cmd.Flags().Set("local", "true") cmd.Flags().Set("local", "true")
opts := ResourcesOptions{FilenameOptions: resource.FilenameOptions{ opts := ResourcesOptions{
Filenames: []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}}, PrintFlags: &printers.PrintFlags{
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
NamePrintFlags: printers.NewNamePrintFlags("", false),
OutputFormat: &outputFormat,
},
FilenameOptions: resource.FilenameOptions{
Filenames: []string{"../../../../test/e2e/testing-manifests/statefulset/cassandra/controller.yaml"}},
Out: buf, Out: buf,
Local: true, Local: true,
Limits: "cpu=200m,memory=512Mi", Limits: "cpu=200m,memory=512Mi",
...@@ -105,14 +116,23 @@ func TestSetMultiResourcesLimitsLocal(t *testing.T) { ...@@ -105,14 +116,23 @@ func TestSetMultiResourcesLimitsLocal(t *testing.T) {
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}}
outputFormat := "name"
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdResources(tf, buf, buf) cmd := NewCmdResources(tf, buf, buf)
cmd.SetOutput(buf) cmd.SetOutput(buf)
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", outputFormat)
cmd.Flags().Set("local", "true") cmd.Flags().Set("local", "true")
opts := ResourcesOptions{FilenameOptions: resource.FilenameOptions{ opts := ResourcesOptions{
Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}}, PrintFlags: &printers.PrintFlags{
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
NamePrintFlags: printers.NewNamePrintFlags("", false),
OutputFormat: &outputFormat,
},
FilenameOptions: resource.FilenameOptions{
Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}},
Out: buf, Out: buf,
Local: true, Local: true,
Limits: "cpu=200m,memory=512Mi", Limits: "cpu=200m,memory=512Mi",
...@@ -478,11 +498,21 @@ func TestSetResourcesRemote(t *testing.T) { ...@@ -478,11 +498,21 @@ func TestSetResourcesRemote(t *testing.T) {
}), }),
VersionedAPIPath: path.Join(input.apiPrefix, testapi.Default.GroupVersion().String()), VersionedAPIPath: path.Join(input.apiPrefix, testapi.Default.GroupVersion().String()),
} }
outputFormat := "yaml"
buf := new(bytes.Buffer) buf := new(bytes.Buffer)
cmd := NewCmdResources(tf, buf, buf) cmd := NewCmdResources(tf, buf, buf)
cmd.SetOutput(buf) cmd.SetOutput(buf)
cmd.Flags().Set("output", "yaml") cmd.Flags().Set("output", outputFormat)
opts := ResourcesOptions{ opts := ResourcesOptions{
PrintFlags: &printers.PrintFlags{
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
NamePrintFlags: printers.NewNamePrintFlags("", false),
OutputFormat: &outputFormat,
},
Out: buf, Out: buf,
Limits: "cpu=200m,memory=512Mi", Limits: "cpu=200m,memory=512Mi",
ContainerSelector: "*"} ContainerSelector: "*"}
......
...@@ -20,6 +20,8 @@ import ( ...@@ -20,6 +20,8 @@ import (
"fmt" "fmt"
"io" "io"
"k8s.io/kubernetes/pkg/printers"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/api/meta"
...@@ -38,6 +40,8 @@ import ( ...@@ -38,6 +40,8 @@ import (
type SelectorOptions struct { type SelectorOptions struct {
fileOptions resource.FilenameOptions fileOptions resource.FilenameOptions
PrintFlags *printers.PrintFlags
local bool local bool
dryrun bool dryrun bool
all bool all bool
...@@ -52,6 +56,8 @@ type SelectorOptions struct { ...@@ -52,6 +56,8 @@ type SelectorOptions struct {
PrintObject func(obj runtime.Object) error PrintObject func(obj runtime.Object) error
ClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error) ClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error)
PrintObj func(runtime.Object) error
builder *resource.Builder builder *resource.Builder
mapper meta.RESTMapper mapper meta.RESTMapper
} }
...@@ -73,6 +79,8 @@ var ( ...@@ -73,6 +79,8 @@ var (
// NewCmdSelector is the "set selector" command. // NewCmdSelector is the "set selector" command.
func NewCmdSelector(f cmdutil.Factory, out io.Writer) *cobra.Command { func NewCmdSelector(f cmdutil.Factory, out io.Writer) *cobra.Command {
options := &SelectorOptions{ options := &SelectorOptions{
PrintFlags: printers.NewPrintFlags("selector updated"),
out: out, out: out,
} }
...@@ -88,7 +96,9 @@ func NewCmdSelector(f cmdutil.Factory, out io.Writer) *cobra.Command { ...@@ -88,7 +96,9 @@ func NewCmdSelector(f cmdutil.Factory, out io.Writer) *cobra.Command {
cmdutil.CheckErr(options.RunSelector()) cmdutil.CheckErr(options.RunSelector())
}, },
} }
cmdutil.AddPrinterFlags(cmd)
options.PrintFlags.AddFlags(cmd)
cmd.Flags().Bool("all", false, "Select all resources, including uninitialized ones, in the namespace of the specified resource types") cmd.Flags().Bool("all", false, "Select all resources, including uninitialized ones, in the namespace of the specified resource types")
cmd.Flags().Bool("local", false, "If true, set selector will NOT contact api-server but run locally.") cmd.Flags().Bool("local", false, "If true, set selector will NOT contact api-server but run locally.")
cmd.Flags().String("resource-version", "", "If non-empty, the selectors update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.") cmd.Flags().String("resource-version", "", "If non-empty, the selectors update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.")
...@@ -109,6 +119,8 @@ func (o *SelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [ ...@@ -109,6 +119,8 @@ func (o *SelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [
o.dryrun = cmdutil.GetDryRunFlag(cmd) o.dryrun = cmdutil.GetDryRunFlag(cmd)
o.output = cmdutil.GetFlagString(cmd, "output") o.output = cmdutil.GetFlagString(cmd, "output")
o.PrintFlags.Complete(o.dryrun)
cmdNamespace, enforceNamespace, err := f.DefaultNamespace() cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
...@@ -146,8 +158,13 @@ func (o *SelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [ ...@@ -146,8 +158,13 @@ func (o *SelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [
} }
} }
printer, err := o.PrintFlags.ToPrinter()
if err != nil {
return err
}
o.PrintObject = func(obj runtime.Object) error { o.PrintObject = func(obj runtime.Object) error {
return cmdutil.PrintObject(cmd, obj, o.out) return printer.PrintObj(obj, o.out)
} }
o.ClientForMapping = func(mapping *meta.RESTMapping) (resource.RESTClient, error) { o.ClientForMapping = func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
return f.ClientForMapping(mapping) return f.ClientForMapping(mapping)
...@@ -208,13 +225,7 @@ func (o *SelectorOptions) RunSelector() error { ...@@ -208,13 +225,7 @@ func (o *SelectorOptions) RunSelector() error {
} }
info.Refresh(patched, true) info.Refresh(patched, true)
return o.PrintObject(patch.Info.AsVersioned())
shortOutput := o.output == "name"
if len(o.output) > 0 && !shortOutput {
return o.PrintObject(patched)
}
cmdutil.PrintSuccess(shortOutput, o.out, info.Object, o.dryrun, "selector updated")
return nil
}) })
} }
......
...@@ -21,6 +21,8 @@ import ( ...@@ -21,6 +21,8 @@ import (
"fmt" "fmt"
"io" "io"
"k8s.io/kubernetes/pkg/printers"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/api/core/v1" "k8s.io/api/core/v1"
...@@ -54,6 +56,8 @@ var ( ...@@ -54,6 +56,8 @@ var (
// serviceAccountConfig encapsulates the data required to perform the operation. // serviceAccountConfig encapsulates the data required to perform the operation.
type serviceAccountConfig struct { type serviceAccountConfig struct {
PrintFlags *printers.PrintFlags
fileNameOptions resource.FilenameOptions fileNameOptions resource.FilenameOptions
out io.Writer out io.Writer
err io.Writer err io.Writer
...@@ -68,11 +72,15 @@ type serviceAccountConfig struct { ...@@ -68,11 +72,15 @@ type serviceAccountConfig struct {
updatePodSpecForObject func(runtime.Object, func(*v1.PodSpec) error) (bool, error) updatePodSpecForObject func(runtime.Object, func(*v1.PodSpec) error) (bool, error)
infos []*resource.Info infos []*resource.Info
serviceAccountName string serviceAccountName string
PrintObj func(runtime.Object) error
} }
// NewCmdServiceAccount returns the "set serviceaccount" command. // NewCmdServiceAccount returns the "set serviceaccount" command.
func NewCmdServiceAccount(f cmdutil.Factory, out, err io.Writer) *cobra.Command { func NewCmdServiceAccount(f cmdutil.Factory, out, err io.Writer) *cobra.Command {
saConfig := &serviceAccountConfig{ saConfig := &serviceAccountConfig{
PrintFlags: printers.NewPrintFlags("serviceaccount updated"),
out: out, out: out,
err: err, err: err,
} }
...@@ -89,7 +97,8 @@ func NewCmdServiceAccount(f cmdutil.Factory, out, err io.Writer) *cobra.Command ...@@ -89,7 +97,8 @@ func NewCmdServiceAccount(f cmdutil.Factory, out, err io.Writer) *cobra.Command
cmdutil.CheckErr(saConfig.Run()) cmdutil.CheckErr(saConfig.Run())
}, },
} }
cmdutil.AddPrinterFlags(cmd)
saConfig.PrintFlags.AddFlags(cmd)
usage := "identifying the resource to get from a server." usage := "identifying the resource to get from a server."
cmdutil.AddFilenameOptionFlags(cmd, &saConfig.fileNameOptions, usage) cmdutil.AddFilenameOptionFlags(cmd, &saConfig.fileNameOptions, usage)
...@@ -111,6 +120,17 @@ func (saConfig *serviceAccountConfig) Complete(f cmdutil.Factory, cmd *cobra.Com ...@@ -111,6 +120,17 @@ func (saConfig *serviceAccountConfig) Complete(f cmdutil.Factory, cmd *cobra.Com
saConfig.updatePodSpecForObject = f.UpdatePodSpecForObject saConfig.updatePodSpecForObject = f.UpdatePodSpecForObject
saConfig.cmd = cmd saConfig.cmd = cmd
saConfig.PrintFlags.Complete(saConfig.dryRun)
printer, err := saConfig.PrintFlags.ToPrinter()
if err != nil {
return err
}
saConfig.PrintObj = func(obj runtime.Object) error {
return printer.PrintObj(obj, saConfig.out)
}
cmdNamespace, enforceNamespace, err := f.DefaultNamespace() cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
if err != nil { if err != nil {
return err return err
...@@ -151,6 +171,7 @@ func (saConfig *serviceAccountConfig) Run() error { ...@@ -151,6 +171,7 @@ func (saConfig *serviceAccountConfig) Run() error {
}) })
return runtime.Encode(cmdutil.InternalVersionJSONEncoder(), info.Object) return runtime.Encode(cmdutil.InternalVersionJSONEncoder(), info.Object)
} }
patches := CalculatePatches(saConfig.infos, cmdutil.InternalVersionJSONEncoder(), patchFn) patches := CalculatePatches(saConfig.infos, cmdutil.InternalVersionJSONEncoder(), patchFn)
for _, patch := range patches { for _, patch := range patches {
info := patch.Info info := patch.Info
...@@ -159,7 +180,7 @@ func (saConfig *serviceAccountConfig) Run() error { ...@@ -159,7 +180,7 @@ func (saConfig *serviceAccountConfig) Run() error {
continue continue
} }
if saConfig.local || saConfig.dryRun { if saConfig.local || saConfig.dryRun {
if err := cmdutil.PrintObject(saConfig.cmd, patch.Info.AsVersioned(), saConfig.out); err != nil { if err := saConfig.PrintObj(patch.Info.AsVersioned()); err != nil {
return err return err
} }
continue continue
...@@ -177,13 +198,10 @@ func (saConfig *serviceAccountConfig) Run() error { ...@@ -177,13 +198,10 @@ func (saConfig *serviceAccountConfig) Run() error {
} }
} }
} }
if len(saConfig.output) > 0 {
if err := cmdutil.PrintObject(saConfig.cmd, info.AsVersioned(), saConfig.out); err != nil { if err := saConfig.PrintObj(info.AsVersioned()); err != nil {
return err return err
}
continue
} }
cmdutil.PrintSuccess(saConfig.shortOutput, saConfig.out, info.Object, saConfig.dryRun, "serviceaccount updated")
} }
return utilerrors.NewAggregate(patchErrs) return utilerrors.NewAggregate(patchErrs)
} }
...@@ -25,6 +25,8 @@ import ( ...@@ -25,6 +25,8 @@ import (
"path" "path"
"testing" "testing"
"k8s.io/kubernetes/pkg/printers"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1" appsv1 "k8s.io/api/apps/v1"
appsv1beta1 "k8s.io/api/apps/v1beta1" appsv1beta1 "k8s.io/api/apps/v1beta1"
...@@ -77,15 +79,25 @@ func TestSetServiceAccountLocal(t *testing.T) { ...@@ -77,15 +79,25 @@ func TestSetServiceAccountLocal(t *testing.T) {
return nil, nil return nil, nil
}), }),
} }
outputFormat := "yaml"
tf.Namespace = "test" tf.Namespace = "test"
out := new(bytes.Buffer) out := new(bytes.Buffer)
cmd := NewCmdServiceAccount(tf, out, out) cmd := NewCmdServiceAccount(tf, out, out)
cmd.SetOutput(out) cmd.SetOutput(out)
cmd.Flags().Set("output", "yaml") cmd.Flags().Set("output", outputFormat)
cmd.Flags().Set("local", "true") cmd.Flags().Set("local", "true")
testapi.Default = testapi.Groups[input.apiGroup] testapi.Default = testapi.Groups[input.apiGroup]
saConfig := serviceAccountConfig{fileNameOptions: resource.FilenameOptions{ saConfig := serviceAccountConfig{
Filenames: []string{input.yaml}}, PrintFlags: &printers.PrintFlags{
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
NamePrintFlags: printers.NewNamePrintFlags("", false),
OutputFormat: &outputFormat,
},
fileNameOptions: resource.FilenameOptions{
Filenames: []string{input.yaml}},
out: out, out: out,
local: true} local: true}
err := saConfig.Complete(tf, cmd, []string{serviceAccount}) err := saConfig.Complete(tf, cmd, []string{serviceAccount})
...@@ -114,13 +126,22 @@ func TestSetServiceAccountMultiLocal(t *testing.T) { ...@@ -114,13 +126,22 @@ func TestSetServiceAccountMultiLocal(t *testing.T) {
tf.Namespace = "test" tf.Namespace = "test"
tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}} tf.ClientConfigVal = &restclient.Config{ContentConfig: restclient.ContentConfig{GroupVersion: &schema.GroupVersion{Version: ""}}}
outputFormat := "name"
buf := bytes.NewBuffer([]byte{}) buf := bytes.NewBuffer([]byte{})
cmd := NewCmdServiceAccount(tf, buf, buf) cmd := NewCmdServiceAccount(tf, buf, buf)
cmd.SetOutput(buf) cmd.SetOutput(buf)
cmd.Flags().Set("output", "name") cmd.Flags().Set("output", outputFormat)
cmd.Flags().Set("local", "true") cmd.Flags().Set("local", "true")
opts := serviceAccountConfig{fileNameOptions: resource.FilenameOptions{ opts := serviceAccountConfig{
Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}}, PrintFlags: &printers.PrintFlags{
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
NamePrintFlags: printers.NewNamePrintFlags("", false),
OutputFormat: &outputFormat,
},
fileNameOptions: resource.FilenameOptions{
Filenames: []string{"../../../../test/fixtures/pkg/kubectl/cmd/set/multi-resource-yaml.yaml"}},
out: buf, out: buf,
local: true} local: true}
...@@ -349,11 +370,21 @@ func TestSetServiceAccountRemote(t *testing.T) { ...@@ -349,11 +370,21 @@ func TestSetServiceAccountRemote(t *testing.T) {
}), }),
VersionedAPIPath: path.Join(input.apiPrefix, testapi.Default.GroupVersion().String()), VersionedAPIPath: path.Join(input.apiPrefix, testapi.Default.GroupVersion().String()),
} }
outputFormat := "yaml"
out := new(bytes.Buffer) out := new(bytes.Buffer)
cmd := NewCmdServiceAccount(tf, out, out) cmd := NewCmdServiceAccount(tf, out, out)
cmd.SetOutput(out) cmd.SetOutput(out)
cmd.Flags().Set("output", "yaml") cmd.Flags().Set("output", outputFormat)
saConfig := serviceAccountConfig{ saConfig := serviceAccountConfig{
PrintFlags: &printers.PrintFlags{
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
NamePrintFlags: printers.NewNamePrintFlags("", false),
OutputFormat: &outputFormat,
},
out: out, out: out,
local: false} local: false}
err := saConfig.Complete(tf, cmd, input.args) err := saConfig.Complete(tf, cmd, input.args)
...@@ -385,12 +416,22 @@ func TestServiceAccountValidation(t *testing.T) { ...@@ -385,12 +416,22 @@ func TestServiceAccountValidation(t *testing.T) {
return nil, nil return nil, nil
}), }),
} }
outputFormat := ""
tf.Namespace = "test" tf.Namespace = "test"
out := bytes.NewBuffer([]byte{}) out := bytes.NewBuffer([]byte{})
cmd := NewCmdServiceAccount(tf, out, out) cmd := NewCmdServiceAccount(tf, out, out)
cmd.SetOutput(out) cmd.SetOutput(out)
saConfig := &serviceAccountConfig{} saConfig := &serviceAccountConfig{
PrintFlags: &printers.PrintFlags{
JSONYamlPrintFlags: printers.NewJSONYamlPrintFlags(),
NamePrintFlags: printers.NewNamePrintFlags("", false),
OutputFormat: &outputFormat,
},
}
err := saConfig.Complete(tf, cmd, input.args) err := saConfig.Complete(tf, cmd, input.args)
assert.EqualError(t, err, input.errorString) assert.EqualError(t, err, input.errorString)
}) })
......
...@@ -21,6 +21,8 @@ import ( ...@@ -21,6 +21,8 @@ import (
"io" "io"
"strings" "strings"
"k8s.io/kubernetes/pkg/printers"
"github.com/spf13/cobra" "github.com/spf13/cobra"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
...@@ -54,6 +56,8 @@ type updateSubjects func(existings []rbac.Subject, targets []rbac.Subject) (bool ...@@ -54,6 +56,8 @@ type updateSubjects func(existings []rbac.Subject, targets []rbac.Subject) (bool
// SubjectOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of // SubjectOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
// referencing the cmd.Flags // referencing the cmd.Flags
type SubjectOptions struct { type SubjectOptions struct {
PrintFlags *printers.PrintFlags
resource.FilenameOptions resource.FilenameOptions
Infos []*resource.Info Infos []*resource.Info
...@@ -70,11 +74,13 @@ type SubjectOptions struct { ...@@ -70,11 +74,13 @@ type SubjectOptions struct {
Groups []string Groups []string
ServiceAccounts []string ServiceAccounts []string
PrintObject func(obj runtime.Object, out io.Writer) error PrintObject func(obj runtime.Object) error
} }
func NewCmdSubject(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command { func NewCmdSubject(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Command {
options := &SubjectOptions{ options := &SubjectOptions{
PrintFlags: printers.NewPrintFlags("subjects updated"),
Out: out, Out: out,
Err: errOut, Err: errOut,
} }
...@@ -92,7 +98,8 @@ func NewCmdSubject(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Co ...@@ -92,7 +98,8 @@ func NewCmdSubject(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Co
}, },
} }
cmdutil.AddPrinterFlags(cmd) options.PrintFlags.AddFlags(cmd)
usage := "the resource to update the subjects" usage := "the resource to update the subjects"
cmdutil.AddFilenameOptionFlags(cmd, &options.FilenameOptions, usage) 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().BoolVar(&options.All, "all", options.All, "Select all resources, including uninitialized ones, in the namespace of the specified resource types")
...@@ -109,8 +116,16 @@ func NewCmdSubject(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Co ...@@ -109,8 +116,16 @@ func NewCmdSubject(f cmdutil.Factory, out io.Writer, errOut io.Writer) *cobra.Co
func (o *SubjectOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error { func (o *SubjectOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
o.Output = cmdutil.GetFlagString(cmd, "output") o.Output = cmdutil.GetFlagString(cmd, "output")
o.DryRun = cmdutil.GetDryRunFlag(cmd) o.DryRun = cmdutil.GetDryRunFlag(cmd)
o.PrintObject = func(obj runtime.Object, out io.Writer) error {
return cmdutil.PrintObject(cmd, obj, out) o.PrintFlags.Complete(o.DryRun)
printer, err := o.PrintFlags.ToPrinter()
if err != nil {
return err
}
o.PrintObject = func(obj runtime.Object) error {
return printer.PrintObj(obj, o.Out)
} }
cmdNamespace, enforceNamespace, err := f.DefaultNamespace() cmdNamespace, enforceNamespace, err := f.DefaultNamespace()
...@@ -236,7 +251,7 @@ func (o *SubjectOptions) Run(f cmdutil.Factory, fn updateSubjects) error { ...@@ -236,7 +251,7 @@ func (o *SubjectOptions) Run(f cmdutil.Factory, fn updateSubjects) error {
} }
if o.Local || o.DryRun { if o.Local || o.DryRun {
if err := o.PrintObject(info.Object, o.Out); err != nil { if err := o.PrintObject(info.Object); err != nil {
return err return err
} }
continue continue
...@@ -249,11 +264,7 @@ func (o *SubjectOptions) Run(f cmdutil.Factory, fn updateSubjects) error { ...@@ -249,11 +264,7 @@ func (o *SubjectOptions) Run(f cmdutil.Factory, fn updateSubjects) error {
} }
info.Refresh(obj, true) info.Refresh(obj, true)
shortOutput := o.Output == "name" return o.PrintObject(info.AsVersioned())
if len(o.Output) > 0 && !shortOutput {
return o.PrintObject(info.AsVersioned(), o.Out)
}
cmdutil.PrintSuccess(shortOutput, o.Out, info.Object, false, "subjects updated")
} }
return utilerrors.NewAggregate(allErrs) return utilerrors.NewAggregate(allErrs)
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment