Merge pull request #108210 from jlsong01/update_kubectl_warning

coordinate the kubectl warning style

Kubernetes-commit: fdb2d544751adc9fd2f6fa5075e9a16df7d352df
This commit is contained in:
Kubernetes Publisher 2022-05-23 15:57:09 -07:00
commit 1d7e71a12f
11 changed files with 72 additions and 36 deletions

12
go.mod
View File

@ -30,9 +30,9 @@ require (
golang.org/x/sys v0.0.0-20220209214540-3681064d5158
gopkg.in/yaml.v2 v2.4.0
k8s.io/api v0.0.0-20220512153301-be84346886a4
k8s.io/apimachinery v0.0.0-20220517160406-e11374f12506
k8s.io/cli-runtime v0.0.0-20220509192006-eb61732d7560
k8s.io/client-go v0.0.0-20220517200918-0bc005e72ff1
k8s.io/apimachinery v0.0.0-20220518000438-e57249028810
k8s.io/cli-runtime v0.0.0-20220524010219-7549443c9917
k8s.io/client-go v0.0.0-20220523084741-33115b49ac5c
k8s.io/component-base v0.0.0-20220512234209-c37f6817941c
k8s.io/component-helpers v0.0.0-20220509184522-76ad8716b7b9
k8s.io/klog/v2 v2.60.1
@ -99,9 +99,9 @@ require (
replace (
k8s.io/api => k8s.io/api v0.0.0-20220512153301-be84346886a4
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20220517160406-e11374f12506
k8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20220509192006-eb61732d7560
k8s.io/client-go => k8s.io/client-go v0.0.0-20220517200918-0bc005e72ff1
k8s.io/apimachinery => k8s.io/apimachinery v0.0.0-20220518000438-e57249028810
k8s.io/cli-runtime => k8s.io/cli-runtime v0.0.0-20220524010219-7549443c9917
k8s.io/client-go => k8s.io/client-go v0.0.0-20220523084741-33115b49ac5c
k8s.io/code-generator => k8s.io/code-generator v0.0.0-20220512215755-7d977b3e5454
k8s.io/component-base => k8s.io/component-base v0.0.0-20220512234209-c37f6817941c
k8s.io/component-helpers => k8s.io/component-helpers v0.0.0-20220509184522-76ad8716b7b9

12
go.sum
View File

@ -761,12 +761,12 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
k8s.io/api v0.0.0-20220512153301-be84346886a4 h1:ATL01GmGTBjwQjXxfD0UGj3une2C8WyzTOXXzNFI790=
k8s.io/api v0.0.0-20220512153301-be84346886a4/go.mod h1:swy7cXqCDjYcBv6ylU8ErrJ2ALa+9PSVEdM4zw65jFQ=
k8s.io/apimachinery v0.0.0-20220517160406-e11374f12506 h1:A+vVaBjqEcFqPLVX9RBO98INUqJCFLlI4XDnH+dDclY=
k8s.io/apimachinery v0.0.0-20220517160406-e11374f12506/go.mod h1:1oBVxgNUfLl978lJAlywA+H45m2ctSuqJU2stpbcjT4=
k8s.io/cli-runtime v0.0.0-20220509192006-eb61732d7560 h1:j8BTlnEUZ+yqwbtEayJS9qWGEhbiZQMuU46/JBunrxg=
k8s.io/cli-runtime v0.0.0-20220509192006-eb61732d7560/go.mod h1:CkzQi01IKV+8rXQDV0jpfK1j+u88qd3tHVhzoPV8meg=
k8s.io/client-go v0.0.0-20220517200918-0bc005e72ff1 h1:RWBe/xAWWVeDL9d/bOjXJSahrJrnsLQvX/0LRH2LXNs=
k8s.io/client-go v0.0.0-20220517200918-0bc005e72ff1/go.mod h1:X+Sryi2FUgezs51csO6s0Ifell3bpMmhzMxiX55kO0Y=
k8s.io/apimachinery v0.0.0-20220518000438-e57249028810 h1:AaArI0wyQ6/2bFlQ0mKgDTYNi8ibRDMBR29PHD6ZesI=
k8s.io/apimachinery v0.0.0-20220518000438-e57249028810/go.mod h1:1oBVxgNUfLl978lJAlywA+H45m2ctSuqJU2stpbcjT4=
k8s.io/cli-runtime v0.0.0-20220524010219-7549443c9917 h1:s7645Wpu53157mdaHUqVtXEvJO8Pob/3qV0yRS9UMSo=
k8s.io/cli-runtime v0.0.0-20220524010219-7549443c9917/go.mod h1:u86waVQLwV7Gy9ksP6jTISrw+rKXuJmL5aimpm28X4s=
k8s.io/client-go v0.0.0-20220523084741-33115b49ac5c h1:jWVU+2OqMGxK9UKk0CC/9HIcQhYeOFqFkHTGx44o8pk=
k8s.io/client-go v0.0.0-20220523084741-33115b49ac5c/go.mod h1:WovSaS/AXTKQf6DSQhaZf3xOzr7eCc7b8k6DgRhC8PQ=
k8s.io/component-base v0.0.0-20220512234209-c37f6817941c h1:mXjI7vadkvEb5V3Jpsfx2/DA+bmFF7khwhVrp8F8fHI=
k8s.io/component-base v0.0.0-20220512234209-c37f6817941c/go.mod h1:NjTZfHd0dH/TjoaGOrLmvEbCzyIvRL8u2qtbyd7zItk=
k8s.io/component-helpers v0.0.0-20220509184522-76ad8716b7b9 h1:Q9MviBOPQrPjw1uC5Yh7Al4tSGB4EgC+8zT7jR4CQDI=

View File

@ -43,6 +43,7 @@ import (
"k8s.io/kubectl/pkg/describe"
rbacutil "k8s.io/kubectl/pkg/util/rbac"
"k8s.io/kubectl/pkg/util/templates"
"k8s.io/kubectl/pkg/util/term"
)
// CanIOptions is the start of the data required to perform the operation. As new fields are added, add them here instead of
@ -63,6 +64,7 @@ type CanIOptions struct {
List bool
genericclioptions.IOStreams
warningPrinter *printers.WarningPrinter
}
var (
@ -144,6 +146,8 @@ func NewCmdCanI(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.C
// Complete completes all the required options
func (o *CanIOptions) Complete(f cmdutil.Factory, args []string) error {
o.warningPrinter = printers.NewWarningPrinter(o.ErrOut, printers.WarningPrinterOptions{Color: term.AllowsColorOutput(o.ErrOut)})
if o.List {
if len(args) != 0 {
return errors.New("list option must be specified with no arguments")
@ -201,6 +205,10 @@ func (o *CanIOptions) Validate() error {
return nil
}
if o.warningPrinter == nil {
return fmt.Errorf("warningPrinter can not be used without initialization")
}
if o.NonResourceURL != "" {
if o.Subresource != "" {
return fmt.Errorf("--subresource can not be used with NonResourceURL")
@ -209,20 +217,19 @@ func (o *CanIOptions) Validate() error {
return fmt.Errorf("NonResourceURL and ResourceName can not specified together")
}
if !isKnownNonResourceVerb(o.Verb) {
fmt.Fprintf(o.ErrOut, "Warning: verb '%s' is not a known verb\n", o.Verb)
o.warningPrinter.Print(fmt.Sprintf("verb '%s' is not a known verb\n", o.Verb))
}
} else if !o.Resource.Empty() && !o.AllNamespaces && o.DiscoveryClient != nil {
if namespaced, err := isNamespaced(o.Resource, o.DiscoveryClient); err == nil && !namespaced {
if len(o.Resource.Group) == 0 {
fmt.Fprintf(o.ErrOut, "Warning: resource '%s' is not namespace scoped\n", o.Resource.Resource)
o.warningPrinter.Print(fmt.Sprintf("resource '%s' is not namespace scoped\n", o.Resource.Resource))
} else {
fmt.Fprintf(o.ErrOut, "Warning: resource '%s' is not namespace scoped in group '%s'\n", o.Resource.Resource, o.Resource.Group)
o.warningPrinter.Print(fmt.Sprintf("resource '%s' is not namespace scoped in group '%s'\n", o.Resource.Resource, o.Resource.Group))
}
}
if !isKnownResourceVerb(o.Verb) {
fmt.Fprintf(o.ErrOut, "Warning: verb '%s' is not a known verb\n", o.Verb)
o.warningPrinter.Print(fmt.Sprintf("verb '%s' is not a known verb\n", o.Verb))
}
}
if o.NoHeaders {
@ -309,9 +316,9 @@ func (o *CanIOptions) resourceFor(mapper meta.RESTMapper, resourceArg string) sc
if err != nil {
if !nonStandardResourceNames.Has(groupResource.String()) {
if len(groupResource.Group) == 0 {
fmt.Fprintf(o.ErrOut, "Warning: the server doesn't have a resource type '%s'\n", groupResource.Resource)
o.warningPrinter.Print(fmt.Sprintf("the server doesn't have a resource type '%s'\n", groupResource.Resource))
} else {
fmt.Fprintf(o.ErrOut, "Warning: the server doesn't have a resource type '%s' in group '%s'\n", groupResource.Resource, groupResource.Group)
o.warningPrinter.Print(fmt.Sprintf("the server doesn't have a resource type '%s' in group '%s'\n", groupResource.Resource, groupResource.Group))
}
}
return schema.GroupVersionResource{Resource: resourceArg}
@ -323,7 +330,7 @@ func (o *CanIOptions) resourceFor(mapper meta.RESTMapper, resourceArg string) sc
func (o *CanIOptions) printStatus(status authorizationv1.SubjectRulesReviewStatus) error {
if status.Incomplete {
fmt.Fprintf(o.ErrOut, "warning: the list may be incomplete: %v\n", status.EvaluationError)
o.warningPrinter.Print(fmt.Sprintf("the list may be incomplete: %v", status.EvaluationError))
}
breakdownRules := []rbacv1.PolicyRule{}

View File

@ -28,6 +28,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/printers"
restclient "k8s.io/client-go/rest"
"k8s.io/client-go/rest/fake"
cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
@ -281,7 +282,7 @@ func TestRunResourceFor(t *testing.T) {
expectGVR: schema.GroupVersionResource{
Resource: "invalid",
},
expectedErrOut: "Warning: the server doesn't have a resource type 'invalid'\n",
expectedErrOut: "Warning: the server doesn't have a resource type 'invalid'\n\n",
},
}
@ -292,6 +293,7 @@ func TestRunResourceFor(t *testing.T) {
ioStreams, _, _, buf := genericclioptions.NewTestIOStreams()
test.o.IOStreams = ioStreams
test.o.warningPrinter = printers.NewWarningPrinter(test.o.IOStreams.ErrOut, printers.WarningPrinterOptions{Color: false})
restMapper, err := tf.ToRESTMapper()
if err != nil {

View File

@ -37,6 +37,7 @@ import (
"k8s.io/apimachinery/pkg/util/strategicpatch"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/printers"
"k8s.io/cli-runtime/pkg/resource"
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
"k8s.io/client-go/tools/cache"
@ -50,6 +51,7 @@ import (
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/interrupt"
"k8s.io/kubectl/pkg/util/templates"
"k8s.io/kubectl/pkg/util/term"
"k8s.io/utils/pointer"
)
@ -127,6 +129,7 @@ type DebugOptions struct {
podClient corev1client.CoreV1Interface
genericclioptions.IOStreams
warningPrinter *printers.WarningPrinter
}
// NewDebugOptions returns a DebugOptions initialized with default values.
@ -217,6 +220,9 @@ func (o *DebugOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
o.attachChanged = cmd.Flags().Changed("attach")
o.shareProcessedChanged = cmd.Flags().Changed("share-processes")
// Warning printer
o.warningPrinter = printers.NewWarningPrinter(o.ErrOut, printers.WarningPrinterOptions{Color: term.AllowsColorOutput(o.ErrOut)})
return nil
}
@ -293,6 +299,11 @@ func (o *DebugOptions) Validate() error {
return fmt.Errorf("-i/--stdin is required for containers with -t/--tty=true")
}
// warningPrinter
if o.warningPrinter == nil {
return fmt.Errorf("warningPrinter can not be used without initialization")
}
return nil
}
@ -742,7 +753,7 @@ func (o *DebugOptions) waitForContainer(ctx context.Context, ns, podName, contai
return true, nil
}
if !o.Quiet && s.State.Waiting != nil && s.State.Waiting.Message != "" {
fmt.Fprintf(o.ErrOut, "Warning: container %s: %s\n", containerName, s.State.Waiting.Message)
o.warningPrinter.Print(fmt.Sprintf("container %s: %s", containerName, s.State.Waiting.Message))
}
return false, nil
})

View File

@ -39,6 +39,7 @@ import (
"k8s.io/kubectl/pkg/util/completion"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"k8s.io/kubectl/pkg/util/term"
)
var (
@ -133,6 +134,7 @@ type DeleteOptions struct {
Result *resource.Result
genericclioptions.IOStreams
warningPrinter *printers.WarningPrinter
}
func NewCmdDelete(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
@ -230,6 +232,8 @@ func (o *DeleteOptions) Complete(f cmdutil.Factory, args []string, cmd *cobra.Co
}
}
o.warningPrinter = printers.NewWarningPrinter(o.ErrOut, printers.WarningPrinterOptions{Color: term.AllowsColorOutput(o.ErrOut)})
return nil
}
@ -244,10 +248,13 @@ func (o *DeleteOptions) Validate() error {
if o.DeleteAll && len(o.FieldSelector) > 0 {
return fmt.Errorf("cannot set --all and --field-selector at the same time")
}
if o.warningPrinter == nil {
return fmt.Errorf("warningPrinter can not be used without initialization")
}
switch {
case o.GracePeriod == 0 && o.ForceDeletion:
fmt.Fprintf(o.ErrOut, "warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.\n")
o.warningPrinter.Print("Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.")
case o.GracePeriod > 0 && o.ForceDeletion:
return fmt.Errorf("--force and --grace-period greater than 0 cannot be specified together")
}
@ -311,7 +318,7 @@ func (o *DeleteOptions) DeleteResult(r *resource.Result) error {
options.PropagationPolicy = &o.CascadingStrategy
if warnClusterScope && info.Mapping.Scope.Name() == meta.RESTScopeNameRoot {
fmt.Fprintf(o.ErrOut, "warning: deleting cluster-scoped resources, not scoped to the provided namespace\n")
o.warningPrinter.Print("deleting cluster-scoped resources, not scoped to the provided namespace")
warnClusterScope = false
}

View File

@ -290,7 +290,7 @@ func TestGracePeriodScenarios(t *testing.T) {
forceFlag: true,
expectedGracePeriod: "0",
expectedOut: "pod/foo\n",
expectedErrOut: "warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.\n",
expectedErrOut: "Warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.\n",
expectedDeleteRequestPath: "/namespaces/test/pods/foo",
},
{
@ -300,7 +300,7 @@ func TestGracePeriodScenarios(t *testing.T) {
gracePeriodFlag: "0",
expectedGracePeriod: "0",
expectedOut: "pod/foo\n",
expectedErrOut: "warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.\n",
expectedErrOut: "Warning: Immediate deletion does not wait for confirmation that the running resource has been terminated. The resource may continue to run on the cluster indefinitely.\n",
expectedDeleteRequestPath: "/namespaces/test/pods/foo",
},
{

View File

@ -27,7 +27,6 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
"k8s.io/apimachinery/pkg/util/sets"
"k8s.io/cli-runtime/pkg/genericclioptions"
"k8s.io/cli-runtime/pkg/printers"
"k8s.io/cli-runtime/pkg/resource"
@ -37,6 +36,7 @@ import (
"k8s.io/kubectl/pkg/util/completion"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"k8s.io/kubectl/pkg/util/term"
)
type DrainCmdOptions struct {
@ -49,6 +49,7 @@ type DrainCmdOptions struct {
nodeInfos []*resource.Info
genericclioptions.IOStreams
warningPrinter *printers.WarningPrinter
}
var (
@ -258,6 +259,8 @@ func (o *DrainCmdOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [
return printer.PrintObj, nil
}
o.warningPrinter = printers.NewWarningPrinter(o.ErrOut, printers.WarningPrinterOptions{Color: term.AllowsColorOutput(o.ErrOut)})
builder := f.NewBuilder().
WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
NamespaceParam(o.Namespace).DefaultNamespace().
@ -338,7 +341,7 @@ func (o *DrainCmdOptions) deleteOrEvictPodsSimple(nodeInfo *resource.Info) error
return utilerrors.NewAggregate(errs)
}
if warnings := list.Warnings(); warnings != "" {
fmt.Fprintf(o.ErrOut, "WARNING: %s\n", warnings)
o.warningPrinter.Print(warnings)
}
if o.drainer.DryRunStrategy == cmdutil.DryRunClient {
for _, pod := range list.Pods() {

View File

@ -599,7 +599,7 @@ func TestDrain(t *testing.T) {
args: []string{"node", "--force"},
expectFatal: false,
expectDelete: true,
expectWarning: "WARNING: deleting Pods that declare no controller: default/bar",
expectWarning: "Warning: deleting Pods that declare no controller: default/bar",
expectOutputToContain: "node/node drained",
},
{
@ -620,7 +620,7 @@ func TestDrain(t *testing.T) {
pods: []corev1.Pod{dsPodWithEmptyDir},
rcs: []corev1.ReplicationController{rc},
args: []string{"node", "--ignore-daemonsets"},
expectWarning: "WARNING: ignoring DaemonSet-managed Pods: default/bar",
expectWarning: "Warning: ignoring DaemonSet-managed Pods: default/bar",
expectFatal: false,
expectDelete: false,
expectOutputToContain: "node/node drained",

View File

@ -40,6 +40,7 @@ import (
"k8s.io/kubectl/pkg/scheme"
"k8s.io/kubectl/pkg/util/i18n"
"k8s.io/kubectl/pkg/util/templates"
"k8s.io/kubectl/pkg/util/term"
)
var (
@ -130,6 +131,7 @@ type EnvOptions struct {
clientset *kubernetes.Clientset
genericclioptions.IOStreams
warningPrinter *printers.WarningPrinter
}
// NewEnvOptions returns an EnvOptions indicating all containers in the selected
@ -140,7 +142,6 @@ func NewEnvOptions(streams genericclioptions.IOStreams) *EnvOptions {
ContainerSelector: "*",
Overwrite: true,
IOStreams: streams,
}
}
@ -148,6 +149,7 @@ func NewEnvOptions(streams genericclioptions.IOStreams) *EnvOptions {
// NewCmdEnv implements the OpenShift cli env command
func NewCmdEnv(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
o := NewEnvOptions(streams)
cmd := &cobra.Command{
Use: "env RESOURCE/NAME KEY_1=VAL_1 ... KEY_N=VAL_N",
DisableFlagsInUseLine: true,
@ -206,7 +208,7 @@ func contains(key string, keyList []string) bool {
func (o *EnvOptions) keyToEnvName(key string) string {
envName := strings.ToUpper(validEnvNameRegexp.ReplaceAllString(key, "_"))
if envName != key {
fmt.Fprintf(o.ErrOut, "warning: key %s transferred to %s\n", key, envName)
o.warningPrinter.Print(fmt.Sprintf("key %s transferred to %s", key, envName))
}
return envName
}
@ -251,6 +253,7 @@ func (o *EnvOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []stri
return err
}
o.builder = f.NewBuilder
o.warningPrinter = printers.NewWarningPrinter(o.ErrOut, printers.WarningPrinterOptions{Color: term.AllowsColorOutput(o.ErrOut)})
return nil
}
@ -269,6 +272,9 @@ func (o *EnvOptions) Validate() error {
if len(o.Keys) > 0 && len(o.From) == 0 {
return fmt.Errorf("when specifying --keys, a configmap or secret must be provided with --from")
}
if o.warningPrinter == nil {
return fmt.Errorf("warningPrinter can not be used without initialization")
}
return nil
}
@ -421,7 +427,7 @@ func (o *EnvOptions) RunEnv() error {
}
}
fmt.Fprintf(o.ErrOut, "warning: %s/%s does not have any containers matching %q\n", objKind, objName, o.ContainerSelector)
o.warningPrinter.Print(fmt.Sprintf("%s/%s does not have any containers matching %q", objKind, objName, o.ContainerSelector))
}
return nil
}

View File

@ -720,9 +720,9 @@ func TestSetEnvFromResource(t *testing.T) {
assert.NoError(t, err)
err = opts.RunEnv()
if input.warning {
assert.Contains(t, errOut.String(), "warning")
assert.Contains(t, errOut.String(), "Warning")
} else {
assert.NotContains(t, errOut.String(), "warning")
assert.NotContains(t, errOut.String(), "Warning")
}
assert.NoError(t, err)
})