mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 10:51:29 +00:00
add a warning printer in cli-runtime to coordinate warning style
modified: staging/src/k8s.io/kubectl/pkg/cmd/auth/auth.go
This commit is contained in:
parent
e7a2ce75e5
commit
272e245f06
@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2022 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package printers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
yellowColor = "\u001b[33;1m"
|
||||||
|
resetColor = "\u001b[0m"
|
||||||
|
)
|
||||||
|
|
||||||
|
type WarningPrinter struct {
|
||||||
|
// out is the writer to output warnings to
|
||||||
|
out io.Writer
|
||||||
|
// opts contains options controlling warning output
|
||||||
|
opts WarningPrinterOptions
|
||||||
|
}
|
||||||
|
|
||||||
|
// WarningPrinterOptions controls the behavior of a WarningPrinter constructed using NewWarningPrinter()
|
||||||
|
type WarningPrinterOptions struct {
|
||||||
|
// Color indicates that warning output can include ANSI color codes
|
||||||
|
Color bool
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewWarningPrinter returns an implementation of warningPrinter that outputs warnings to the specified writer.
|
||||||
|
func NewWarningPrinter(out io.Writer, opts WarningPrinterOptions) *WarningPrinter {
|
||||||
|
h := &WarningPrinter{out: out, opts: opts}
|
||||||
|
return h
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print prints warnings to the configured writer.
|
||||||
|
func (w *WarningPrinter) Print(message string) {
|
||||||
|
if w.opts.Color {
|
||||||
|
fmt.Fprintf(w.out, "%sWarning:%s %s\n", yellowColor, resetColor, message)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(w.out, "Warning: %s\n", message)
|
||||||
|
}
|
||||||
|
}
|
@ -43,6 +43,7 @@ import (
|
|||||||
"k8s.io/kubectl/pkg/describe"
|
"k8s.io/kubectl/pkg/describe"
|
||||||
rbacutil "k8s.io/kubectl/pkg/util/rbac"
|
rbacutil "k8s.io/kubectl/pkg/util/rbac"
|
||||||
"k8s.io/kubectl/pkg/util/templates"
|
"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
|
// 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
|
List bool
|
||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
|
warningPrinter *printers.WarningPrinter
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -144,6 +146,8 @@ func NewCmdCanI(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.C
|
|||||||
|
|
||||||
// Complete completes all the required options
|
// Complete completes all the required options
|
||||||
func (o *CanIOptions) Complete(f cmdutil.Factory, args []string) error {
|
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 o.List {
|
||||||
if len(args) != 0 {
|
if len(args) != 0 {
|
||||||
return errors.New("list option must be specified with no arguments")
|
return errors.New("list option must be specified with no arguments")
|
||||||
@ -201,6 +205,10 @@ func (o *CanIOptions) Validate() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if o.warningPrinter == nil {
|
||||||
|
return fmt.Errorf("warningPrinter can not be used without initialization")
|
||||||
|
}
|
||||||
|
|
||||||
if o.NonResourceURL != "" {
|
if o.NonResourceURL != "" {
|
||||||
if o.Subresource != "" {
|
if o.Subresource != "" {
|
||||||
return fmt.Errorf("--subresource can not be used with NonResourceURL")
|
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")
|
return fmt.Errorf("NonResourceURL and ResourceName can not specified together")
|
||||||
}
|
}
|
||||||
if !isKnownNonResourceVerb(o.Verb) {
|
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 {
|
} else if !o.Resource.Empty() && !o.AllNamespaces && o.DiscoveryClient != nil {
|
||||||
if namespaced, err := isNamespaced(o.Resource, o.DiscoveryClient); err == nil && !namespaced {
|
if namespaced, err := isNamespaced(o.Resource, o.DiscoveryClient); err == nil && !namespaced {
|
||||||
if len(o.Resource.Group) == 0 {
|
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 {
|
} 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) {
|
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 {
|
if o.NoHeaders {
|
||||||
@ -309,9 +316,9 @@ func (o *CanIOptions) resourceFor(mapper meta.RESTMapper, resourceArg string) sc
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
if !nonStandardResourceNames.Has(groupResource.String()) {
|
if !nonStandardResourceNames.Has(groupResource.String()) {
|
||||||
if len(groupResource.Group) == 0 {
|
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 {
|
} 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}
|
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 {
|
func (o *CanIOptions) printStatus(status authorizationv1.SubjectRulesReviewStatus) error {
|
||||||
if status.Incomplete {
|
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{}
|
breakdownRules := []rbacv1.PolicyRule{}
|
||||||
|
@ -28,6 +28,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
|
"k8s.io/cli-runtime/pkg/printers"
|
||||||
restclient "k8s.io/client-go/rest"
|
restclient "k8s.io/client-go/rest"
|
||||||
"k8s.io/client-go/rest/fake"
|
"k8s.io/client-go/rest/fake"
|
||||||
cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
|
cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
|
||||||
@ -281,7 +282,7 @@ func TestRunResourceFor(t *testing.T) {
|
|||||||
expectGVR: schema.GroupVersionResource{
|
expectGVR: schema.GroupVersionResource{
|
||||||
Resource: "invalid",
|
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()
|
ioStreams, _, _, buf := genericclioptions.NewTestIOStreams()
|
||||||
test.o.IOStreams = ioStreams
|
test.o.IOStreams = ioStreams
|
||||||
|
test.o.warningPrinter = printers.NewWarningPrinter(test.o.IOStreams.ErrOut, printers.WarningPrinterOptions{Color: false})
|
||||||
|
|
||||||
restMapper, err := tf.ToRESTMapper()
|
restMapper, err := tf.ToRESTMapper()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -37,6 +37,7 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
"k8s.io/apimachinery/pkg/util/strategicpatch"
|
||||||
"k8s.io/apimachinery/pkg/watch"
|
"k8s.io/apimachinery/pkg/watch"
|
||||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
|
"k8s.io/cli-runtime/pkg/printers"
|
||||||
"k8s.io/cli-runtime/pkg/resource"
|
"k8s.io/cli-runtime/pkg/resource"
|
||||||
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
corev1client "k8s.io/client-go/kubernetes/typed/core/v1"
|
||||||
"k8s.io/client-go/tools/cache"
|
"k8s.io/client-go/tools/cache"
|
||||||
@ -50,6 +51,7 @@ import (
|
|||||||
"k8s.io/kubectl/pkg/util/i18n"
|
"k8s.io/kubectl/pkg/util/i18n"
|
||||||
"k8s.io/kubectl/pkg/util/interrupt"
|
"k8s.io/kubectl/pkg/util/interrupt"
|
||||||
"k8s.io/kubectl/pkg/util/templates"
|
"k8s.io/kubectl/pkg/util/templates"
|
||||||
|
"k8s.io/kubectl/pkg/util/term"
|
||||||
"k8s.io/utils/pointer"
|
"k8s.io/utils/pointer"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -127,6 +129,7 @@ type DebugOptions struct {
|
|||||||
podClient corev1client.CoreV1Interface
|
podClient corev1client.CoreV1Interface
|
||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
|
warningPrinter *printers.WarningPrinter
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewDebugOptions returns a DebugOptions initialized with default values.
|
// 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.attachChanged = cmd.Flags().Changed("attach")
|
||||||
o.shareProcessedChanged = cmd.Flags().Changed("share-processes")
|
o.shareProcessedChanged = cmd.Flags().Changed("share-processes")
|
||||||
|
|
||||||
|
// Warning printer
|
||||||
|
o.warningPrinter = printers.NewWarningPrinter(o.ErrOut, printers.WarningPrinterOptions{Color: term.AllowsColorOutput(o.ErrOut)})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -293,6 +299,11 @@ func (o *DebugOptions) Validate(cmd *cobra.Command) error {
|
|||||||
return fmt.Errorf("-i/--stdin is required for containers with -t/--tty=true")
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -742,7 +753,7 @@ func (o *DebugOptions) waitForContainer(ctx context.Context, ns, podName, contai
|
|||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
if !o.Quiet && s.State.Waiting != nil && s.State.Waiting.Message != "" {
|
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
|
return false, nil
|
||||||
})
|
})
|
||||||
|
@ -39,6 +39,7 @@ import (
|
|||||||
"k8s.io/kubectl/pkg/util/completion"
|
"k8s.io/kubectl/pkg/util/completion"
|
||||||
"k8s.io/kubectl/pkg/util/i18n"
|
"k8s.io/kubectl/pkg/util/i18n"
|
||||||
"k8s.io/kubectl/pkg/util/templates"
|
"k8s.io/kubectl/pkg/util/templates"
|
||||||
|
"k8s.io/kubectl/pkg/util/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -133,6 +134,7 @@ type DeleteOptions struct {
|
|||||||
Result *resource.Result
|
Result *resource.Result
|
||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
|
warningPrinter *printers.WarningPrinter
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCmdDelete(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,10 +248,13 @@ func (o *DeleteOptions) Validate() error {
|
|||||||
if o.DeleteAll && len(o.FieldSelector) > 0 {
|
if o.DeleteAll && len(o.FieldSelector) > 0 {
|
||||||
return fmt.Errorf("cannot set --all and --field-selector at the same time")
|
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 {
|
switch {
|
||||||
case o.GracePeriod == 0 && o.ForceDeletion:
|
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:
|
case o.GracePeriod > 0 && o.ForceDeletion:
|
||||||
return fmt.Errorf("--force and --grace-period greater than 0 cannot be specified together")
|
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
|
options.PropagationPolicy = &o.CascadingStrategy
|
||||||
|
|
||||||
if warnClusterScope && info.Mapping.Scope.Name() == meta.RESTScopeNameRoot {
|
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
|
warnClusterScope = false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,7 +290,7 @@ func TestGracePeriodScenarios(t *testing.T) {
|
|||||||
forceFlag: true,
|
forceFlag: true,
|
||||||
expectedGracePeriod: "0",
|
expectedGracePeriod: "0",
|
||||||
expectedOut: "pod/foo\n",
|
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",
|
expectedDeleteRequestPath: "/namespaces/test/pods/foo",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -300,7 +300,7 @@ func TestGracePeriodScenarios(t *testing.T) {
|
|||||||
gracePeriodFlag: "0",
|
gracePeriodFlag: "0",
|
||||||
expectedGracePeriod: "0",
|
expectedGracePeriod: "0",
|
||||||
expectedOut: "pod/foo\n",
|
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",
|
expectedDeleteRequestPath: "/namespaces/test/pods/foo",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -27,7 +27,6 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||||
"k8s.io/apimachinery/pkg/util/sets"
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
|
||||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
"k8s.io/cli-runtime/pkg/printers"
|
"k8s.io/cli-runtime/pkg/printers"
|
||||||
"k8s.io/cli-runtime/pkg/resource"
|
"k8s.io/cli-runtime/pkg/resource"
|
||||||
@ -37,6 +36,7 @@ import (
|
|||||||
"k8s.io/kubectl/pkg/util/completion"
|
"k8s.io/kubectl/pkg/util/completion"
|
||||||
"k8s.io/kubectl/pkg/util/i18n"
|
"k8s.io/kubectl/pkg/util/i18n"
|
||||||
"k8s.io/kubectl/pkg/util/templates"
|
"k8s.io/kubectl/pkg/util/templates"
|
||||||
|
"k8s.io/kubectl/pkg/util/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
type DrainCmdOptions struct {
|
type DrainCmdOptions struct {
|
||||||
@ -49,6 +49,7 @@ type DrainCmdOptions struct {
|
|||||||
nodeInfos []*resource.Info
|
nodeInfos []*resource.Info
|
||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
|
warningPrinter *printers.WarningPrinter
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -258,6 +259,8 @@ func (o *DrainCmdOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args [
|
|||||||
return printer.PrintObj, nil
|
return printer.PrintObj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o.warningPrinter = printers.NewWarningPrinter(o.ErrOut, printers.WarningPrinterOptions{Color: term.AllowsColorOutput(o.ErrOut)})
|
||||||
|
|
||||||
builder := f.NewBuilder().
|
builder := f.NewBuilder().
|
||||||
WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
|
WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
|
||||||
NamespaceParam(o.Namespace).DefaultNamespace().
|
NamespaceParam(o.Namespace).DefaultNamespace().
|
||||||
@ -338,7 +341,7 @@ func (o *DrainCmdOptions) deleteOrEvictPodsSimple(nodeInfo *resource.Info) error
|
|||||||
return utilerrors.NewAggregate(errs)
|
return utilerrors.NewAggregate(errs)
|
||||||
}
|
}
|
||||||
if warnings := list.Warnings(); warnings != "" {
|
if warnings := list.Warnings(); warnings != "" {
|
||||||
fmt.Fprintf(o.ErrOut, "WARNING: %s\n", warnings)
|
o.warningPrinter.Print(warnings)
|
||||||
}
|
}
|
||||||
if o.drainer.DryRunStrategy == cmdutil.DryRunClient {
|
if o.drainer.DryRunStrategy == cmdutil.DryRunClient {
|
||||||
for _, pod := range list.Pods() {
|
for _, pod := range list.Pods() {
|
||||||
|
@ -599,7 +599,7 @@ func TestDrain(t *testing.T) {
|
|||||||
args: []string{"node", "--force"},
|
args: []string{"node", "--force"},
|
||||||
expectFatal: false,
|
expectFatal: false,
|
||||||
expectDelete: true,
|
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",
|
expectOutputToContain: "node/node drained",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -620,7 +620,7 @@ func TestDrain(t *testing.T) {
|
|||||||
pods: []corev1.Pod{dsPodWithEmptyDir},
|
pods: []corev1.Pod{dsPodWithEmptyDir},
|
||||||
rcs: []corev1.ReplicationController{rc},
|
rcs: []corev1.ReplicationController{rc},
|
||||||
args: []string{"node", "--ignore-daemonsets"},
|
args: []string{"node", "--ignore-daemonsets"},
|
||||||
expectWarning: "WARNING: ignoring DaemonSet-managed Pods: default/bar",
|
expectWarning: "Warning: ignoring DaemonSet-managed Pods: default/bar",
|
||||||
expectFatal: false,
|
expectFatal: false,
|
||||||
expectDelete: false,
|
expectDelete: false,
|
||||||
expectOutputToContain: "node/node drained",
|
expectOutputToContain: "node/node drained",
|
||||||
|
@ -40,6 +40,7 @@ import (
|
|||||||
"k8s.io/kubectl/pkg/scheme"
|
"k8s.io/kubectl/pkg/scheme"
|
||||||
"k8s.io/kubectl/pkg/util/i18n"
|
"k8s.io/kubectl/pkg/util/i18n"
|
||||||
"k8s.io/kubectl/pkg/util/templates"
|
"k8s.io/kubectl/pkg/util/templates"
|
||||||
|
"k8s.io/kubectl/pkg/util/term"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -130,6 +131,7 @@ type EnvOptions struct {
|
|||||||
clientset *kubernetes.Clientset
|
clientset *kubernetes.Clientset
|
||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
|
warningPrinter *printers.WarningPrinter
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewEnvOptions returns an EnvOptions indicating all containers in the selected
|
// NewEnvOptions returns an EnvOptions indicating all containers in the selected
|
||||||
@ -140,14 +142,14 @@ func NewEnvOptions(streams genericclioptions.IOStreams) *EnvOptions {
|
|||||||
|
|
||||||
ContainerSelector: "*",
|
ContainerSelector: "*",
|
||||||
Overwrite: true,
|
Overwrite: true,
|
||||||
|
IOStreams: streams,
|
||||||
IOStreams: streams,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCmdEnv implements the OpenShift cli env command
|
// NewCmdEnv implements the OpenShift cli env command
|
||||||
func NewCmdEnv(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
|
func NewCmdEnv(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
|
||||||
o := NewEnvOptions(streams)
|
o := NewEnvOptions(streams)
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "env RESOURCE/NAME KEY_1=VAL_1 ... KEY_N=VAL_N",
|
Use: "env RESOURCE/NAME KEY_1=VAL_1 ... KEY_N=VAL_N",
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
@ -206,7 +208,7 @@ func contains(key string, keyList []string) bool {
|
|||||||
func (o *EnvOptions) keyToEnvName(key string) string {
|
func (o *EnvOptions) keyToEnvName(key string) string {
|
||||||
envName := strings.ToUpper(validEnvNameRegexp.ReplaceAllString(key, "_"))
|
envName := strings.ToUpper(validEnvNameRegexp.ReplaceAllString(key, "_"))
|
||||||
if envName != 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
|
return envName
|
||||||
}
|
}
|
||||||
@ -251,6 +253,7 @@ func (o *EnvOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []stri
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
o.builder = f.NewBuilder
|
o.builder = f.NewBuilder
|
||||||
|
o.warningPrinter = printers.NewWarningPrinter(o.ErrOut, printers.WarningPrinterOptions{Color: term.AllowsColorOutput(o.ErrOut)})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -269,6 +272,9 @@ func (o *EnvOptions) Validate() error {
|
|||||||
if len(o.Keys) > 0 && len(o.From) == 0 {
|
if len(o.Keys) > 0 && len(o.From) == 0 {
|
||||||
return fmt.Errorf("when specifying --keys, a configmap or secret must be provided with --from")
|
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
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -720,9 +720,9 @@ func TestSetEnvFromResource(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
err = opts.RunEnv()
|
err = opts.RunEnv()
|
||||||
if input.warning {
|
if input.warning {
|
||||||
assert.Contains(t, errOut.String(), "warning")
|
assert.Contains(t, errOut.String(), "Warning")
|
||||||
} else {
|
} else {
|
||||||
assert.NotContains(t, errOut.String(), "warning")
|
assert.NotContains(t, errOut.String(), "Warning")
|
||||||
}
|
}
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
})
|
})
|
||||||
|
@ -1481,7 +1481,7 @@ run_namespace_tests() {
|
|||||||
kubectl create namespace my-namespace
|
kubectl create namespace my-namespace
|
||||||
kube::test::get_object_assert 'namespaces/my-namespace' "{{$id_field}}" 'my-namespace'
|
kube::test::get_object_assert 'namespaces/my-namespace' "{{$id_field}}" 'my-namespace'
|
||||||
output_message=$(! kubectl delete namespace -n my-namespace --all 2>&1 "${kube_flags[@]}")
|
output_message=$(! kubectl delete namespace -n my-namespace --all 2>&1 "${kube_flags[@]}")
|
||||||
kube::test::if_has_string "${output_message}" 'warning: deleting cluster-scoped resources'
|
kube::test::if_has_string "${output_message}" 'Warning: deleting cluster-scoped resources'
|
||||||
kube::test::if_has_string "${output_message}" 'namespace "my-namespace" deleted'
|
kube::test::if_has_string "${output_message}" 'namespace "my-namespace" deleted'
|
||||||
|
|
||||||
### Quota
|
### Quota
|
||||||
|
@ -41,7 +41,7 @@ run_clusterroles_tests() {
|
|||||||
kubectl create "${kube_flags[@]:?}" clusterrole pod-admin --verb=* --resource=pods
|
kubectl create "${kube_flags[@]:?}" clusterrole pod-admin --verb=* --resource=pods
|
||||||
kube::test::get_object_assert clusterrole/pod-admin "{{range.rules}}{{range.verbs}}{{.}}:{{end}}{{end}}" '\*:'
|
kube::test::get_object_assert clusterrole/pod-admin "{{range.rules}}{{range.verbs}}{{.}}:{{end}}{{end}}" '\*:'
|
||||||
output_message=$(kubectl delete clusterrole pod-admin -n test 2>&1 "${kube_flags[@]}")
|
output_message=$(kubectl delete clusterrole pod-admin -n test 2>&1 "${kube_flags[@]}")
|
||||||
kube::test::if_has_string "${output_message}" 'warning: deleting cluster-scoped resources'
|
kube::test::if_has_string "${output_message}" 'Warning: deleting cluster-scoped resources'
|
||||||
kube::test::if_has_string "${output_message}" 'clusterrole.rbac.authorization.k8s.io "pod-admin" deleted'
|
kube::test::if_has_string "${output_message}" 'clusterrole.rbac.authorization.k8s.io "pod-admin" deleted'
|
||||||
|
|
||||||
kubectl create "${kube_flags[@]}" clusterrole pod-admin --verb=* --resource=pods
|
kubectl create "${kube_flags[@]}" clusterrole pod-admin --verb=* --resource=pods
|
||||||
|
@ -46,7 +46,7 @@ run_persistent_volumes_tests() {
|
|||||||
kubectl create -f test/fixtures/doc-yaml/user-guide/persistent-volumes/volumes/local-01.yaml "${kube_flags[@]}"
|
kubectl create -f test/fixtures/doc-yaml/user-guide/persistent-volumes/volumes/local-01.yaml "${kube_flags[@]}"
|
||||||
kube::test::get_object_assert pv "{{range.items}}{{$id_field}}:{{end}}" 'pv0001:'
|
kube::test::get_object_assert pv "{{range.items}}{{$id_field}}:{{end}}" 'pv0001:'
|
||||||
output_message=$(kubectl delete pv -n test --all 2>&1 "${kube_flags[@]}")
|
output_message=$(kubectl delete pv -n test --all 2>&1 "${kube_flags[@]}")
|
||||||
kube::test::if_has_string "${output_message}" 'warning: deleting cluster-scoped resources'
|
kube::test::if_has_string "${output_message}" 'Warning: deleting cluster-scoped resources'
|
||||||
kube::test::if_has_string "${output_message}" 'persistentvolume "pv0001" deleted'
|
kube::test::if_has_string "${output_message}" 'persistentvolume "pv0001" deleted'
|
||||||
kube::test::get_object_assert pv "{{range.items}}{{$id_field}}:{{end}}" ''
|
kube::test::get_object_assert pv "{{range.items}}{{$id_field}}:{{end}}" ''
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user