mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-19 18:02:01 +00:00
add server-side validation support to kubectl
This commit is contained in:
parent
083c3ac4e8
commit
fe3772890f
24
hack/testdata/invalid-deployment-unknown-and-duplicate-fields.yaml
vendored
Normal file
24
hack/testdata/invalid-deployment-unknown-and-duplicate-fields.yaml
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: invalid-nginx-deployment
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
replicas: 3
|
||||
replicas: 4
|
||||
foo: bar
|
||||
baz: baq
|
||||
selector:
|
||||
matchLabels:
|
||||
app: nginx
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: nginx
|
||||
spec:
|
||||
containers:
|
||||
- name: nginx
|
||||
image: nginx:1.14.2
|
||||
ports:
|
||||
- containerPort: 80
|
@ -124,7 +124,16 @@ func (o *ConvertOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) (err er
|
||||
}
|
||||
|
||||
o.validator = func() (validation.Schema, error) {
|
||||
return f.Validator(cmdutil.GetFlagBool(cmd, "validate"))
|
||||
directive, err := cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dynamicClient, err := f.DynamicClient()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
verifier := resource.NewQueryParamVerifier(dynamicClient, f.OpenAPIGetter(), resource.QueryParamFieldValidation)
|
||||
return f.Validator(directive, verifier)
|
||||
}
|
||||
|
||||
// build the printer
|
||||
|
@ -54,6 +54,10 @@ type Helper struct {
|
||||
// FieldManager is the name associated with the actor or entity that is making
|
||||
// changes.
|
||||
FieldManager string
|
||||
|
||||
// FieldValidation is the directive used to indicate how the server should perform
|
||||
// field validation (Ignore, Warn, or Strict)
|
||||
FieldValidation string
|
||||
}
|
||||
|
||||
// NewHelper creates a Helper from a ResourceMapping
|
||||
@ -79,6 +83,13 @@ func (m *Helper) WithFieldManager(fieldManager string) *Helper {
|
||||
return m
|
||||
}
|
||||
|
||||
// WithFieldValidation sets the field validation option to indicate
|
||||
// how the server should perform field validation (Ignore, Warn, or Strict).
|
||||
func (m *Helper) WithFieldValidation(validationDirective string) *Helper {
|
||||
m.FieldValidation = validationDirective
|
||||
return m
|
||||
}
|
||||
|
||||
// Subresource sets the helper to access (<resource>/[ns/<namespace>/]<name>/<subresource>)
|
||||
func (m *Helper) WithSubresource(subresource string) *Helper {
|
||||
m.Subresource = subresource
|
||||
@ -206,6 +217,9 @@ func (m *Helper) CreateWithOptions(namespace string, modify bool, obj runtime.Ob
|
||||
if m.FieldManager != "" {
|
||||
options.FieldManager = m.FieldManager
|
||||
}
|
||||
if m.FieldValidation != "" {
|
||||
options.FieldValidation = m.FieldValidation
|
||||
}
|
||||
if modify {
|
||||
// Attempt to version the object based on client logic.
|
||||
version, err := metadataAccessor.ResourceVersion(obj)
|
||||
@ -242,6 +256,9 @@ func (m *Helper) Patch(namespace, name string, pt types.PatchType, data []byte,
|
||||
if m.FieldManager != "" {
|
||||
options.FieldManager = m.FieldManager
|
||||
}
|
||||
if m.FieldValidation != "" {
|
||||
options.FieldValidation = m.FieldValidation
|
||||
}
|
||||
return m.RESTClient.Patch(pt).
|
||||
NamespaceIfScoped(namespace, m.NamespaceScoped).
|
||||
Resource(m.Resource).
|
||||
@ -262,6 +279,9 @@ func (m *Helper) Replace(namespace, name string, overwrite bool, obj runtime.Obj
|
||||
if m.FieldManager != "" {
|
||||
options.FieldManager = m.FieldManager
|
||||
}
|
||||
if m.FieldValidation != "" {
|
||||
options.FieldValidation = m.FieldValidation
|
||||
}
|
||||
|
||||
// Attempt to version the object based on client logic.
|
||||
version, err := metadataAccessor.ResourceVersion(obj)
|
||||
|
@ -62,6 +62,11 @@ type QueryParamVerifier struct {
|
||||
queryParam VerifiableQueryParam
|
||||
}
|
||||
|
||||
// Verifier is the generic verifier interface used for testing QueryParamVerifier
|
||||
type Verifier interface {
|
||||
HasSupport(gvk schema.GroupVersionKind) error
|
||||
}
|
||||
|
||||
// VerifiableQueryParam is a query parameter who's enablement on the
|
||||
// apiserver can be determined by evaluating the OpenAPI for a specific
|
||||
// GVK.
|
||||
@ -72,6 +77,7 @@ const (
|
||||
QueryParamFieldValidation VerifiableQueryParam = "fieldValidation"
|
||||
)
|
||||
|
||||
// HasSupport checks if the given gvk supports the query param configured on v
|
||||
func (v *QueryParamVerifier) HasSupport(gvk schema.GroupVersionKind) error {
|
||||
oapi, err := v.openAPIGetter.OpenAPISchema()
|
||||
if err != nil {
|
||||
@ -90,7 +96,7 @@ func (v *QueryParamVerifier) HasSupport(gvk schema.GroupVersionKind) error {
|
||||
}
|
||||
}
|
||||
if !supports {
|
||||
return newParamUnsupportedError(gvk, v.queryParam)
|
||||
return NewParamUnsupportedError(gvk, v.queryParam)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -100,7 +106,7 @@ type paramUnsupportedError struct {
|
||||
param VerifiableQueryParam
|
||||
}
|
||||
|
||||
func newParamUnsupportedError(gvk schema.GroupVersionKind, param VerifiableQueryParam) error {
|
||||
func NewParamUnsupportedError(gvk schema.GroupVersionKind, param VerifiableQueryParam) error {
|
||||
return ¶mUnsupportedError{
|
||||
gvk: gvk,
|
||||
param: param,
|
||||
|
@ -80,25 +80,27 @@ type ApplyOptions struct {
|
||||
|
||||
DeleteOptions *delete.DeleteOptions
|
||||
|
||||
ServerSideApply bool
|
||||
ForceConflicts bool
|
||||
FieldManager string
|
||||
Selector string
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
Prune bool
|
||||
PruneResources []prune.Resource
|
||||
cmdBaseName string
|
||||
All bool
|
||||
Overwrite bool
|
||||
OpenAPIPatch bool
|
||||
PruneWhitelist []string
|
||||
ServerSideApply bool
|
||||
ForceConflicts bool
|
||||
FieldManager string
|
||||
Selector string
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
FieldValidationVerifier *resource.QueryParamVerifier
|
||||
Prune bool
|
||||
PruneResources []prune.Resource
|
||||
cmdBaseName string
|
||||
All bool
|
||||
Overwrite bool
|
||||
OpenAPIPatch bool
|
||||
PruneWhitelist []string
|
||||
|
||||
Validator validation.Schema
|
||||
Builder *resource.Builder
|
||||
Mapper meta.RESTMapper
|
||||
DynamicClient dynamic.Interface
|
||||
OpenAPISchema openapi.Resources
|
||||
ValidationDirective string
|
||||
Validator validation.Schema
|
||||
Builder *resource.Builder
|
||||
Mapper meta.RESTMapper
|
||||
DynamicClient dynamic.Interface
|
||||
OpenAPISchema openapi.Resources
|
||||
|
||||
Namespace string
|
||||
EnforceNamespace bool
|
||||
@ -238,6 +240,7 @@ func (flags *ApplyFlags) ToOptions(cmd *cobra.Command, baseName string, args []s
|
||||
}
|
||||
|
||||
dryRunVerifier := resource.NewQueryParamVerifier(dynamicClient, flags.Factory.OpenAPIGetter(), resource.QueryParamDryRun)
|
||||
fieldValidationVerifier := resource.NewQueryParamVerifier(dynamicClient, flags.Factory.OpenAPIGetter(), resource.QueryParamFieldValidation)
|
||||
fieldManager := GetApplyFieldManagerFlag(cmd, serverSideApply)
|
||||
|
||||
// allow for a success message operation to be specified at print time
|
||||
@ -264,7 +267,12 @@ func (flags *ApplyFlags) ToOptions(cmd *cobra.Command, baseName string, args []s
|
||||
}
|
||||
|
||||
openAPISchema, _ := flags.Factory.OpenAPISchema()
|
||||
validator, err := flags.Factory.Validator(cmdutil.GetFlagBool(cmd, "validate"))
|
||||
|
||||
validationDirective, err := cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
validator, err := flags.Factory.Validator(validationDirective, fieldValidationVerifier)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -308,14 +316,15 @@ func (flags *ApplyFlags) ToOptions(cmd *cobra.Command, baseName string, args []s
|
||||
OpenAPIPatch: flags.OpenAPIPatch,
|
||||
PruneWhitelist: flags.PruneWhitelist,
|
||||
|
||||
Recorder: recorder,
|
||||
Namespace: namespace,
|
||||
EnforceNamespace: enforceNamespace,
|
||||
Validator: validator,
|
||||
Builder: builder,
|
||||
Mapper: mapper,
|
||||
DynamicClient: dynamicClient,
|
||||
OpenAPISchema: openAPISchema,
|
||||
Recorder: recorder,
|
||||
Namespace: namespace,
|
||||
EnforceNamespace: enforceNamespace,
|
||||
Validator: validator,
|
||||
ValidationDirective: validationDirective,
|
||||
Builder: builder,
|
||||
Mapper: mapper,
|
||||
DynamicClient: dynamicClient,
|
||||
OpenAPISchema: openAPISchema,
|
||||
|
||||
IOStreams: flags.IOStreams,
|
||||
|
||||
@ -407,7 +416,6 @@ func (o *ApplyOptions) SetObjects(infos []*resource.Info) {
|
||||
|
||||
// Run executes the `apply` command.
|
||||
func (o *ApplyOptions) Run() error {
|
||||
|
||||
if o.PreProcessorFn != nil {
|
||||
klog.V(4).Infof("Running apply pre-processor function")
|
||||
if err := o.PreProcessorFn(); err != nil {
|
||||
@ -472,7 +480,8 @@ func (o *ApplyOptions) applyOneObject(info *resource.Info) error {
|
||||
|
||||
helper := resource.NewHelper(info.Client, info.Mapping).
|
||||
DryRun(o.DryRunStrategy == cmdutil.DryRunServer).
|
||||
WithFieldManager(o.FieldManager)
|
||||
WithFieldManager(o.FieldManager).
|
||||
WithFieldValidation(o.ValidationDirective)
|
||||
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
// Ensure the APIServer supports server-side dry-run for the resource,
|
||||
|
@ -83,6 +83,7 @@ func NewCmdApplyEditLastApplied(f cmdutil.Factory, ioStreams genericclioptions.I
|
||||
cmd.Flags().BoolVar(&o.WindowsLineEndings, "windows-line-endings", o.WindowsLineEndings,
|
||||
"Defaults to the line ending native to your platform.")
|
||||
cmdutil.AddFieldManagerFlagVar(cmd, &o.FieldManager, FieldManagerClientSideApply)
|
||||
cmdutil.AddValidateFlags(cmd)
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
@ -51,8 +51,11 @@ type CreateOptions struct {
|
||||
PrintFlags *genericclioptions.PrintFlags
|
||||
RecordFlags *genericclioptions.RecordFlags
|
||||
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
FieldValidationVerifier *resource.QueryParamVerifier
|
||||
|
||||
ValidationDirective string
|
||||
|
||||
fieldManager string
|
||||
|
||||
@ -208,6 +211,12 @@ func (o *CreateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
return err
|
||||
}
|
||||
o.DryRunVerifier = resource.NewQueryParamVerifier(dynamicClient, f.OpenAPIGetter(), resource.QueryParamDryRun)
|
||||
o.FieldValidationVerifier = resource.NewQueryParamVerifier(dynamicClient, f.OpenAPIGetter(), resource.QueryParamFieldValidation)
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
printer, err := o.PrintFlags.ToPrinter()
|
||||
if err != nil {
|
||||
@ -236,7 +245,8 @@ func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
if o.EditBeforeCreate {
|
||||
return RunEditOnCreate(f, o.PrintFlags, o.RecordFlags, o.IOStreams, cmd, &o.FilenameOptions, o.fieldManager)
|
||||
}
|
||||
schema, err := f.Validator(cmdutil.GetFlagBool(cmd, "validate"))
|
||||
|
||||
schema, err := f.Validator(o.ValidationDirective, o.FieldValidationVerifier)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -283,6 +293,7 @@ func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
NewHelper(info.Client, info.Mapping).
|
||||
DryRun(o.DryRunStrategy == cmdutil.DryRunServer).
|
||||
WithFieldManager(o.fieldManager).
|
||||
WithFieldValidation(o.ValidationDirective).
|
||||
Create(info.Namespace, true, info.Object)
|
||||
if err != nil {
|
||||
return cmdutil.AddSourceToErr("creating", info.Source, err)
|
||||
@ -307,15 +318,19 @@ func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error {
|
||||
func RunEditOnCreate(f cmdutil.Factory, printFlags *genericclioptions.PrintFlags, recordFlags *genericclioptions.RecordFlags, ioStreams genericclioptions.IOStreams, cmd *cobra.Command, options *resource.FilenameOptions, fieldManager string) error {
|
||||
editOptions := editor.NewEditOptions(editor.EditBeforeCreateMode, ioStreams)
|
||||
editOptions.FilenameOptions = *options
|
||||
validationDirective, err := cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
editOptions.ValidateOptions = cmdutil.ValidateOptions{
|
||||
EnableValidation: cmdutil.GetFlagBool(cmd, "validate"),
|
||||
ValidationDirective: string(validationDirective),
|
||||
}
|
||||
editOptions.PrintFlags = printFlags
|
||||
editOptions.ApplyAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
|
||||
editOptions.RecordFlags = recordFlags
|
||||
editOptions.FieldManager = "kubectl-create"
|
||||
|
||||
err := editOptions.Complete(f, []string{}, cmd)
|
||||
err = editOptions.Complete(f, []string{}, cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -347,6 +362,7 @@ type CreateSubcommandOptions struct {
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
CreateAnnotation bool
|
||||
FieldManager string
|
||||
ValidationDirective string
|
||||
|
||||
Namespace string
|
||||
EnforceNamespace bool
|
||||
@ -393,6 +409,11 @@ func (o *CreateSubcommandOptions) Complete(f cmdutil.Factory, cmd *cobra.Command
|
||||
return err
|
||||
}
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.PrintObj = func(obj kruntime.Object, out io.Writer) error {
|
||||
return printer.PrintObj(obj, out)
|
||||
}
|
||||
@ -447,6 +468,8 @@ func (o *CreateSubcommandOptions) Run() error {
|
||||
if o.FieldManager != "" {
|
||||
createOptions.FieldManager = o.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = o.ValidationDirective
|
||||
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
if err := o.DryRunVerifier.HasSupport(mapping.GroupVersionKind); err != nil {
|
||||
return err
|
||||
|
@ -213,6 +213,7 @@ func (c *CreateClusterRoleOptions) RunCreateRole() error {
|
||||
if c.FieldManager != "" {
|
||||
createOptions.FieldManager = c.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = c.ValidationDirective
|
||||
if c.DryRunStrategy == cmdutil.DryRunServer {
|
||||
if err := c.DryRunVerifier.HasSupport(clusterRole.GroupVersionKind()); err != nil {
|
||||
return err
|
||||
|
@ -59,9 +59,10 @@ type ClusterRoleBindingOptions struct {
|
||||
FieldManager string
|
||||
CreateAnnotation bool
|
||||
|
||||
Client rbacclientv1.RbacV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
Client rbacclientv1.RbacV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
ValidationDirective string
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -149,6 +150,10 @@ func (o *ClusterRoleBindingOptions) Complete(f cmdutil.Factory, cmd *cobra.Comma
|
||||
o.PrintObj = func(obj runtime.Object) error {
|
||||
return printer.PrintObj(obj, o.Out)
|
||||
}
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@ -169,6 +174,7 @@ func (o *ClusterRoleBindingOptions) Run() error {
|
||||
if o.FieldManager != "" {
|
||||
createOptions.FieldManager = o.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = o.ValidationDirective
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
if err := o.DryRunVerifier.HasSupport(clusterRoleBinding.GroupVersionKind()); err != nil {
|
||||
return err
|
||||
|
@ -96,9 +96,10 @@ type ConfigMapOptions struct {
|
||||
Namespace string
|
||||
EnforceNamespace bool
|
||||
|
||||
Client corev1client.CoreV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
Client corev1client.CoreV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
ValidationDirective string
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -194,6 +195,11 @@ func (o *ConfigMapOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
|
||||
return printer.PrintObj(obj, o.Out)
|
||||
}
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -222,6 +228,7 @@ func (o *ConfigMapOptions) Run() error {
|
||||
if o.FieldManager != "" {
|
||||
createOptions.FieldManager = o.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = o.ValidationDirective
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
if err := o.DryRunVerifier.HasSupport(configMap.GroupVersionKind()); err != nil {
|
||||
return err
|
||||
|
@ -60,14 +60,15 @@ type CreateCronJobOptions struct {
|
||||
Command []string
|
||||
Restart string
|
||||
|
||||
Namespace string
|
||||
EnforceNamespace bool
|
||||
Client batchv1client.BatchV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
Builder *resource.Builder
|
||||
FieldManager string
|
||||
CreateAnnotation bool
|
||||
Namespace string
|
||||
EnforceNamespace bool
|
||||
Client batchv1client.BatchV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
ValidationDirective string
|
||||
Builder *resource.Builder
|
||||
FieldManager string
|
||||
CreateAnnotation bool
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -160,6 +161,11 @@ func (o *CreateCronJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, a
|
||||
return printer.PrintObj(obj, o.Out)
|
||||
}
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -175,6 +181,7 @@ func (o *CreateCronJobOptions) Run() error {
|
||||
if o.FieldManager != "" {
|
||||
createOptions.FieldManager = o.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = o.ValidationDirective
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
if err := o.DryRunVerifier.HasSupport(cronJob.GroupVersionKind()); err != nil {
|
||||
return err
|
||||
|
@ -72,9 +72,10 @@ type CreateDeploymentOptions struct {
|
||||
FieldManager string
|
||||
CreateAnnotation bool
|
||||
|
||||
Client appsv1client.AppsV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
Client appsv1client.AppsV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
ValidationDirective string
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -167,6 +168,11 @@ func (o *CreateDeploymentOptions) Complete(f cmdutil.Factory, cmd *cobra.Command
|
||||
return printer.PrintObj(obj, o.Out)
|
||||
}
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -191,6 +197,7 @@ func (o *CreateDeploymentOptions) Run() error {
|
||||
if o.FieldManager != "" {
|
||||
createOptions.FieldManager = o.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = o.ValidationDirective
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
if err := o.DryRunVerifier.HasSupport(deploy.GroupVersionKind()); err != nil {
|
||||
return err
|
||||
|
@ -116,9 +116,10 @@ type CreateIngressOptions struct {
|
||||
EnforceNamespace bool
|
||||
CreateAnnotation bool
|
||||
|
||||
Client networkingv1client.NetworkingV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
Client networkingv1client.NetworkingV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
ValidationDirective string
|
||||
|
||||
FieldManager string
|
||||
|
||||
@ -208,6 +209,11 @@ func (o *CreateIngressOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, a
|
||||
o.PrintObj = func(obj runtime.Object) error {
|
||||
return printer.PrintObj(obj, o.Out)
|
||||
}
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -254,6 +260,7 @@ func (o *CreateIngressOptions) Run() error {
|
||||
if o.FieldManager != "" {
|
||||
createOptions.FieldManager = o.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = o.ValidationDirective
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
if err := o.DryRunVerifier.HasSupport(ingress.GroupVersionKind()); err != nil {
|
||||
return err
|
||||
|
@ -62,14 +62,15 @@ type CreateJobOptions struct {
|
||||
From string
|
||||
Command []string
|
||||
|
||||
Namespace string
|
||||
EnforceNamespace bool
|
||||
Client batchv1client.BatchV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
Builder *resource.Builder
|
||||
FieldManager string
|
||||
CreateAnnotation bool
|
||||
Namespace string
|
||||
EnforceNamespace bool
|
||||
Client batchv1client.BatchV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
ValidationDirective string
|
||||
Builder *resource.Builder
|
||||
FieldManager string
|
||||
CreateAnnotation bool
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -155,6 +156,11 @@ func (o *CreateJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
|
||||
return printer.PrintObj(obj, o.Out)
|
||||
}
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -207,6 +213,7 @@ func (o *CreateJobOptions) Run() error {
|
||||
if o.FieldManager != "" {
|
||||
createOptions.FieldManager = o.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = o.ValidationDirective
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
if err := o.DryRunVerifier.HasSupport(job.GroupVersionKind()); err != nil {
|
||||
return err
|
||||
|
@ -52,10 +52,11 @@ type NamespaceOptions struct {
|
||||
// Name of resource being created
|
||||
Name string
|
||||
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
CreateAnnotation bool
|
||||
FieldManager string
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
ValidationDirective string
|
||||
CreateAnnotation bool
|
||||
FieldManager string
|
||||
|
||||
Client *coreclient.CoreV1Client
|
||||
|
||||
@ -140,6 +141,11 @@ func (o *NamespaceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
|
||||
o.PrintObj = func(obj runtime.Object) error {
|
||||
return printer.PrintObj(obj, o.Out)
|
||||
}
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -155,6 +161,7 @@ func (o *NamespaceOptions) Run() error {
|
||||
if o.FieldManager != "" {
|
||||
createOptions.FieldManager = o.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = o.ValidationDirective
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
if err := o.DryRunVerifier.HasSupport(namespace.GroupVersionKind()); err != nil {
|
||||
return err
|
||||
|
@ -70,9 +70,10 @@ type PodDisruptionBudgetOpts struct {
|
||||
Namespace string
|
||||
EnforceNamespace bool
|
||||
|
||||
Client *policyv1client.PolicyV1Client
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resourcecli.QueryParamVerifier
|
||||
Client *policyv1client.PolicyV1Client
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resourcecli.QueryParamVerifier
|
||||
ValidationDirective string
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -165,6 +166,11 @@ func (o *PodDisruptionBudgetOpts) Complete(f cmdutil.Factory, cmd *cobra.Command
|
||||
return printer.PrintObj(obj, o.Out)
|
||||
}
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -217,6 +223,7 @@ func (o *PodDisruptionBudgetOpts) Run() error {
|
||||
if o.FieldManager != "" {
|
||||
createOptions.FieldManager = o.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = o.ValidationDirective
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
if err := o.DryRunVerifier.HasSupport(podDisruptionBudget.GroupVersionKind()); err != nil {
|
||||
return err
|
||||
|
@ -64,9 +64,10 @@ type PriorityClassOptions struct {
|
||||
FieldManager string
|
||||
CreateAnnotation bool
|
||||
|
||||
Client *schedulingv1client.SchedulingV1Client
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
Client *schedulingv1client.SchedulingV1Client
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
ValidationDirective string
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -149,6 +150,11 @@ func (o *PriorityClassOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, a
|
||||
return printer.PrintObj(obj, o.Out)
|
||||
}
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -168,6 +174,7 @@ func (o *PriorityClassOptions) Run() error {
|
||||
if o.FieldManager != "" {
|
||||
createOptions.FieldManager = o.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = o.ValidationDirective
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
if err := o.DryRunVerifier.HasSupport(priorityClass.GroupVersionKind()); err != nil {
|
||||
return err
|
||||
|
@ -66,9 +66,10 @@ type QuotaOpts struct {
|
||||
Namespace string
|
||||
EnforceNamespace bool
|
||||
|
||||
Client *coreclient.CoreV1Client
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resourcecli.QueryParamVerifier
|
||||
Client *coreclient.CoreV1Client
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resourcecli.QueryParamVerifier
|
||||
ValidationDirective string
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -155,6 +156,11 @@ func (o *QuotaOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []strin
|
||||
return printer.PrintObj(obj, o.Out)
|
||||
}
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -182,6 +188,7 @@ func (o *QuotaOpts) Run() error {
|
||||
if o.FieldManager != "" {
|
||||
createOptions.FieldManager = o.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = o.ValidationDirective
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
if err := o.DryRunVerifier.HasSupport(resourceQuota.GroupVersionKind()); err != nil {
|
||||
return err
|
||||
|
@ -136,16 +136,17 @@ type CreateRoleOptions struct {
|
||||
Resources []ResourceOptions
|
||||
ResourceNames []string
|
||||
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
OutputFormat string
|
||||
Namespace string
|
||||
EnforceNamespace bool
|
||||
Client clientgorbacv1.RbacV1Interface
|
||||
Mapper meta.RESTMapper
|
||||
PrintObj func(obj runtime.Object) error
|
||||
FieldManager string
|
||||
CreateAnnotation bool
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
ValidationDirective string
|
||||
OutputFormat string
|
||||
Namespace string
|
||||
EnforceNamespace bool
|
||||
Client clientgorbacv1.RbacV1Interface
|
||||
Mapper meta.RESTMapper
|
||||
PrintObj func(obj runtime.Object) error
|
||||
FieldManager string
|
||||
CreateAnnotation bool
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -271,6 +272,11 @@ func (o *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
|
||||
return printer.PrintObj(obj, o.Out)
|
||||
}
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -374,6 +380,7 @@ func (o *CreateRoleOptions) RunCreateRole() error {
|
||||
if o.FieldManager != "" {
|
||||
createOptions.FieldManager = o.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = o.ValidationDirective
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
if err := o.DryRunVerifier.HasSupport(role.GroupVersionKind()); err != nil {
|
||||
return err
|
||||
|
@ -61,9 +61,10 @@ type RoleBindingOptions struct {
|
||||
FieldManager string
|
||||
CreateAnnotation bool
|
||||
|
||||
Client rbacclientv1.RbacV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
Client rbacclientv1.RbacV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
ValidationDirective string
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -149,6 +150,11 @@ func (o *RoleBindingOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg
|
||||
o.PrintObj = func(obj runtime.Object) error {
|
||||
return printer.PrintObj(obj, o.Out)
|
||||
}
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -178,6 +184,7 @@ func (o *RoleBindingOptions) Run() error {
|
||||
if o.FieldManager != "" {
|
||||
createOptions.FieldManager = o.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = o.ValidationDirective
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
if err := o.DryRunVerifier.HasSupport(roleBinding.GroupVersionKind()); err != nil {
|
||||
return err
|
||||
|
@ -112,9 +112,10 @@ type CreateSecretOptions struct {
|
||||
Namespace string
|
||||
EnforceNamespace bool
|
||||
|
||||
Client corev1client.CoreV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
Client corev1client.CoreV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
ValidationDirective string
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -212,6 +213,11 @@ func (o *CreateSecretOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, ar
|
||||
return printer.PrintObj(obj, o.Out)
|
||||
}
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -242,6 +248,7 @@ func (o *CreateSecretOptions) Run() error {
|
||||
if o.FieldManager != "" {
|
||||
createOptions.FieldManager = o.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = o.ValidationDirective
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
err := o.DryRunVerifier.HasSupport(secret.GroupVersionKind())
|
||||
if err != nil {
|
||||
|
@ -108,9 +108,10 @@ type CreateSecretDockerRegistryOptions struct {
|
||||
Namespace string
|
||||
EnforceNamespace bool
|
||||
|
||||
Client corev1client.CoreV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
Client corev1client.CoreV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
ValidationDirective string
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -211,6 +212,11 @@ func (o *CreateSecretDockerRegistryOptions) Complete(f cmdutil.Factory, cmd *cob
|
||||
return printer.PrintObj(obj, o.Out)
|
||||
}
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -241,6 +247,7 @@ func (o *CreateSecretDockerRegistryOptions) Run() error {
|
||||
if o.FieldManager != "" {
|
||||
createOptions.FieldManager = o.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = o.ValidationDirective
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
err := o.DryRunVerifier.HasSupport(secretDockerRegistry.GroupVersionKind())
|
||||
if err != nil {
|
||||
|
@ -69,9 +69,10 @@ type CreateSecretTLSOptions struct {
|
||||
Namespace string
|
||||
EnforceNamespace bool
|
||||
|
||||
Client corev1client.CoreV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
Client corev1client.CoreV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
ValidationDirective string
|
||||
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
@ -168,6 +169,11 @@ func (o *CreateSecretTLSOptions) Complete(f cmdutil.Factory, cmd *cobra.Command,
|
||||
return printer.PrintObj(obj, o.Out)
|
||||
}
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -198,6 +204,7 @@ func (o *CreateSecretTLSOptions) Run() error {
|
||||
if o.FieldManager != "" {
|
||||
createOptions.FieldManager = o.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = o.ValidationDirective
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
err := o.DryRunVerifier.HasSupport(secretTLS.GroupVersionKind())
|
||||
if err != nil {
|
||||
|
@ -74,9 +74,10 @@ type ServiceOptions struct {
|
||||
Namespace string
|
||||
EnforceNamespace bool
|
||||
|
||||
Client corev1client.CoreV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
Client corev1client.CoreV1Interface
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
ValidationDirective string
|
||||
genericclioptions.IOStreams
|
||||
}
|
||||
|
||||
@ -131,6 +132,11 @@ func (o *ServiceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
||||
return printer.PrintObj(obj, o.Out)
|
||||
}
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -214,6 +220,7 @@ func (o *ServiceOptions) Run() error {
|
||||
if o.FieldManager != "" {
|
||||
createOptions.FieldManager = o.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = o.ValidationDirective
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
createOptions.DryRun = []string{metav1.DryRunAll}
|
||||
}
|
||||
|
@ -51,11 +51,12 @@ type ServiceAccountOpts struct {
|
||||
PrintFlags *genericclioptions.PrintFlags
|
||||
PrintObj func(obj runtime.Object) error
|
||||
// Name of resource being created
|
||||
Name string
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
CreateAnnotation bool
|
||||
FieldManager string
|
||||
Name string
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
ValidationDirective string
|
||||
CreateAnnotation bool
|
||||
FieldManager string
|
||||
|
||||
Namespace string
|
||||
EnforceNamespace bool
|
||||
@ -146,6 +147,11 @@ func (o *ServiceAccountOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, arg
|
||||
return printer.PrintObj(obj, o.Out)
|
||||
}
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -173,6 +179,7 @@ func (o *ServiceAccountOpts) Run() error {
|
||||
if o.FieldManager != "" {
|
||||
createOptions.FieldManager = o.FieldManager
|
||||
}
|
||||
createOptions.FieldValidation = o.ValidationDirective
|
||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||
if err := o.DryRunVerifier.HasSupport(serviceAccount.GroupVersionKind()); err != nil {
|
||||
return err
|
||||
|
@ -72,8 +72,6 @@ var (
|
||||
// NewCmdEdit creates the `edit` command
|
||||
func NewCmdEdit(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||
o := editor.NewEditOptions(editor.NormalEditMode, ioStreams)
|
||||
o.ValidateOptions = cmdutil.ValidateOptions{EnableValidation: true}
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "edit (RESOURCE/NAME | -f FILENAME)",
|
||||
DisableFlagsInUseLine: true,
|
||||
@ -94,7 +92,7 @@ func NewCmdEdit(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra
|
||||
|
||||
usage := "to use to edit the resource"
|
||||
cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage)
|
||||
cmdutil.AddValidateOptionFlags(cmd, &o.ValidateOptions)
|
||||
cmdutil.AddValidateFlags(cmd)
|
||||
cmd.Flags().BoolVarP(&o.OutputPatch, "output-patch", "", o.OutputPatch, "Output the patch if the resource is edited.")
|
||||
cmd.Flags().BoolVar(&o.WindowsLineEndings, "windows-line-endings", o.WindowsLineEndings,
|
||||
"Defaults to the line ending native to your platform.")
|
||||
|
@ -77,13 +77,14 @@ type ReplaceOptions struct {
|
||||
DeleteFlags *delete.DeleteFlags
|
||||
DeleteOptions *delete.DeleteOptions
|
||||
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
FieldValidationVerifier *resource.QueryParamVerifier
|
||||
validationDirective string
|
||||
|
||||
PrintObj func(obj runtime.Object) error
|
||||
|
||||
createAnnotation bool
|
||||
validate bool
|
||||
|
||||
Schema validation.Schema
|
||||
Builder func() *resource.Builder
|
||||
@ -151,7 +152,10 @@ func (o *ReplaceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
||||
return err
|
||||
}
|
||||
|
||||
o.validate = cmdutil.GetFlagBool(cmd, "validate")
|
||||
o.validationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.createAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
|
||||
|
||||
o.DryRunStrategy, err = cmdutil.GetDryRunStrategy(cmd)
|
||||
@ -163,6 +167,7 @@ func (o *ReplaceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
||||
return err
|
||||
}
|
||||
o.DryRunVerifier = resource.NewQueryParamVerifier(dynamicClient, f.OpenAPIGetter(), resource.QueryParamDryRun)
|
||||
o.FieldValidationVerifier = resource.NewQueryParamVerifier(dynamicClient, f.OpenAPIGetter(), resource.QueryParamFieldValidation)
|
||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
||||
|
||||
printer, err := o.PrintFlags.ToPrinter()
|
||||
@ -196,7 +201,7 @@ func (o *ReplaceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
||||
return err
|
||||
}
|
||||
|
||||
schema, err := f.Validator(o.validate)
|
||||
schema, err := f.Validator(o.validationDirective, o.FieldValidationVerifier)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -306,6 +311,7 @@ func (o *ReplaceOptions) Run(f cmdutil.Factory) error {
|
||||
NewHelper(info.Client, info.Mapping).
|
||||
DryRun(o.DryRunStrategy == cmdutil.DryRunServer).
|
||||
WithFieldManager(o.fieldManager).
|
||||
WithFieldValidation(o.validationDirective).
|
||||
WithSubresource(o.Subresource).
|
||||
Replace(info.Namespace, info.Name, true, info.Object)
|
||||
if err != nil {
|
||||
@ -409,6 +415,7 @@ func (o *ReplaceOptions) forceReplace() error {
|
||||
|
||||
obj, err := resource.NewHelper(info.Client, info.Mapping).
|
||||
WithFieldManager(o.fieldManager).
|
||||
WithFieldValidation(o.validationDirective).
|
||||
Create(info.Namespace, true, info.Object)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -47,8 +47,9 @@ type TaintOptions struct {
|
||||
PrintFlags *genericclioptions.PrintFlags
|
||||
ToPrinter func(string) (printers.ResourcePrinter, error)
|
||||
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
DryRunStrategy cmdutil.DryRunStrategy
|
||||
DryRunVerifier *resource.QueryParamVerifier
|
||||
ValidationDirective string
|
||||
|
||||
resources []string
|
||||
taintsToAdd []v1.Taint
|
||||
@ -150,6 +151,11 @@ func (o *TaintOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []st
|
||||
o.DryRunVerifier = resource.NewQueryParamVerifier(dynamicClient, f.OpenAPIGetter(), resource.QueryParamDryRun)
|
||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// retrieves resource and taint args from args
|
||||
// also checks args to verify that all resources are specified before taints
|
||||
taintArgs := []string{}
|
||||
@ -337,8 +343,9 @@ func (o TaintOptions) RunTaint() error {
|
||||
}
|
||||
helper := resource.
|
||||
NewHelper(client, mapping).
|
||||
DryRun(o.DryRunStrategy == cmdutil.DryRunServer).
|
||||
WithFieldManager(o.fieldManager).
|
||||
DryRun(o.DryRunStrategy == cmdutil.DryRunServer)
|
||||
WithFieldValidation(o.ValidationDirective)
|
||||
|
||||
var outputObj runtime.Object
|
||||
if createdPatch {
|
||||
|
@ -499,7 +499,7 @@ func (f *TestFactory) UnstructuredClientForMapping(mapping *meta.RESTMapping) (r
|
||||
}
|
||||
|
||||
// Validator returns a validation schema
|
||||
func (f *TestFactory) Validator(validate bool) (validation.Schema, error) {
|
||||
func (f *TestFactory) Validator(validateDirective string, verifier *resource.QueryParamVerifier) (validation.Schema, error) {
|
||||
return validation.NullSchema{}, nil
|
||||
}
|
||||
|
||||
|
@ -68,6 +68,8 @@ type EditOptions struct {
|
||||
WindowsLineEndings bool
|
||||
|
||||
cmdutil.ValidateOptions
|
||||
ValidationDirective string
|
||||
FieldValidationVerifier *resource.QueryParamVerifier
|
||||
|
||||
OriginalResult *resource.Result
|
||||
|
||||
@ -215,6 +217,17 @@ func (o *EditOptions) Complete(f cmdutil.Factory, args []string, cmd *cobra.Comm
|
||||
return o.PrintFlags.ToPrinter()
|
||||
}
|
||||
|
||||
dynamicClient, err := f.DynamicClient()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
o.FieldValidationVerifier = resource.NewQueryParamVerifier(dynamicClient, f.OpenAPIGetter(), resource.QueryParamFieldValidation)
|
||||
|
||||
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
o.CmdNamespace = cmdNamespace
|
||||
o.f = f
|
||||
|
||||
@ -309,7 +322,7 @@ func (o *EditOptions) Run() error {
|
||||
klog.V(4).Infof("User edited:\n%s", string(edited))
|
||||
|
||||
// Apply validation
|
||||
schema, err := o.f.Validator(o.EnableValidation)
|
||||
schema, err := o.f.Validator(o.ValidationDirective, o.FieldValidationVerifier)
|
||||
if err != nil {
|
||||
return preservedFile(err, file, o.ErrOut)
|
||||
}
|
||||
@ -571,7 +584,10 @@ func (o *EditOptions) annotationPatch(update *resource.Info) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
helper := resource.NewHelper(client, mapping).WithFieldManager(o.FieldManager).WithSubresource(o.Subresource)
|
||||
helper := resource.NewHelper(client, mapping).
|
||||
WithFieldManager(o.FieldManager).
|
||||
WithFieldValidation(o.ValidationDirective).
|
||||
WithSubresource(o.Subresource)
|
||||
_, err = helper.Patch(o.CmdNamespace, update.Name, patchType, patch, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -709,7 +725,9 @@ func (o *EditOptions) visitToPatch(originalInfos []*resource.Info, patchVisitor
|
||||
}
|
||||
|
||||
patched, err := resource.NewHelper(info.Client, info.Mapping).
|
||||
WithFieldManager(o.FieldManager).WithSubresource(o.Subresource).
|
||||
WithFieldManager(o.FieldManager).
|
||||
WithFieldValidation(o.ValidationDirective).
|
||||
WithSubresource(o.Subresource).
|
||||
Patch(info.Namespace, info.Name, patchType, patch, nil)
|
||||
if err != nil {
|
||||
fmt.Fprintln(o.ErrOut, results.addError(err, info))
|
||||
@ -729,6 +747,7 @@ func (o *EditOptions) visitToCreate(createVisitor resource.Visitor) error {
|
||||
err := createVisitor.Visit(func(info *resource.Info, incomingErr error) error {
|
||||
obj, err := resource.NewHelper(info.Client, info.Mapping).
|
||||
WithFieldManager(o.FieldManager).
|
||||
WithFieldValidation(o.ValidationDirective).
|
||||
Create(info.Namespace, true, info.Object)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -61,7 +61,7 @@ type Factory interface {
|
||||
UnstructuredClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error)
|
||||
|
||||
// Returns a schema that can validate objects stored on disk.
|
||||
Validator(validate bool) (validation.Schema, error)
|
||||
Validator(validationDirective string, verifier *resource.QueryParamVerifier) (validation.Schema, error)
|
||||
// OpenAPISchema returns the parsed openapi schema definition
|
||||
OpenAPISchema() (openapi.Resources, error)
|
||||
// OpenAPIGetter returns a getter for the openapi schema document
|
||||
|
@ -24,6 +24,7 @@ import (
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
"k8s.io/cli-runtime/pkg/resource"
|
||||
"k8s.io/client-go/discovery"
|
||||
@ -141,8 +142,14 @@ func (f *factoryImpl) UnstructuredClientForMapping(mapping *meta.RESTMapping) (r
|
||||
return restclient.RESTClientFor(cfg)
|
||||
}
|
||||
|
||||
func (f *factoryImpl) Validator(validate bool) (validation.Schema, error) {
|
||||
if !validate {
|
||||
func (f *factoryImpl) Validator(validationDirective string, verifier *resource.QueryParamVerifier) (validation.Schema, error) {
|
||||
// client-side schema validation is only performed
|
||||
// when the validationDirective is strict.
|
||||
// If the directive is warn, we rely on the ParamVerifyingSchema
|
||||
// to ignore the client-side validation and provide a warning
|
||||
// to the user that attempting warn validation when SS validation
|
||||
// is unsupported is inert.
|
||||
if validationDirective == metav1.FieldValidationIgnore {
|
||||
return validation.NullSchema{}, nil
|
||||
}
|
||||
|
||||
@ -151,10 +158,11 @@ func (f *factoryImpl) Validator(validate bool) (validation.Schema, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return validation.ConjunctiveSchema{
|
||||
schema := validation.ConjunctiveSchema{
|
||||
openapivalidation.NewSchemaValidation(resources),
|
||||
validation.NoDoubleKeySchema{},
|
||||
}, nil
|
||||
}
|
||||
return validation.NewParamVerifyingSchema(schema, verifier, string(validationDirective)), nil
|
||||
}
|
||||
|
||||
// OpenAPISchema returns metadata and structural information about
|
||||
|
@ -399,11 +399,14 @@ func GetPodRunningTimeoutFlag(cmd *cobra.Command) (time.Duration, error) {
|
||||
}
|
||||
|
||||
func AddValidateFlags(cmd *cobra.Command) {
|
||||
cmd.Flags().Bool("validate", true, "If true, use a schema to validate the input before sending it")
|
||||
}
|
||||
|
||||
func AddValidateOptionFlags(cmd *cobra.Command, options *ValidateOptions) {
|
||||
cmd.Flags().BoolVar(&options.EnableValidation, "validate", options.EnableValidation, "If true, use a schema to validate the input before sending it")
|
||||
cmd.Flags().String(
|
||||
"validate",
|
||||
"strict",
|
||||
`Must be one of: strict (or true), warn, ignore (or false).
|
||||
"true" or "strict" will use a schema to validate the input and fail the request if invalid. It will perform server side validation if ServerSideFieldValidation is enabled on the api-server, but will fall back to less reliable client-side validation if not.
|
||||
"warn" will warn about unknown or duplicate fields without blocking the request if server-side field validation is enabled on the API server, and behave as "ignore" otherwise.
|
||||
"false" or "ignore" will not perform any schema validation, silently dropping any unknown or duplicate fields.`,
|
||||
)
|
||||
}
|
||||
|
||||
func AddFilenameOptionFlags(cmd *cobra.Command, options *resource.FilenameOptions, usage string) {
|
||||
@ -475,7 +478,7 @@ func AddSubresourceFlags(cmd *cobra.Command, subresource *string, usage string,
|
||||
}
|
||||
|
||||
type ValidateOptions struct {
|
||||
EnableValidation bool
|
||||
ValidationDirective string
|
||||
}
|
||||
|
||||
// Merge converts the passed in object to JSON, merges the fragment into it using an RFC7396 JSON Merge Patch,
|
||||
@ -576,6 +579,30 @@ func GetFieldManagerFlag(cmd *cobra.Command) string {
|
||||
return GetFlagString(cmd, "field-manager")
|
||||
}
|
||||
|
||||
func GetValidationDirective(cmd *cobra.Command) (string, error) {
|
||||
var validateFlag = GetFlagString(cmd, "validate")
|
||||
b, err := strconv.ParseBool(validateFlag)
|
||||
if err != nil {
|
||||
switch validateFlag {
|
||||
case cmd.Flag("validate").NoOptDefVal:
|
||||
return metav1.FieldValidationStrict, nil
|
||||
case "strict":
|
||||
return metav1.FieldValidationStrict, nil
|
||||
case "warn":
|
||||
return metav1.FieldValidationWarn, nil
|
||||
case "ignore":
|
||||
return metav1.FieldValidationIgnore, nil
|
||||
default:
|
||||
return metav1.FieldValidationStrict, fmt.Errorf(`invalid - validate option %q; must be one of: strict (or true), warn, ignore (or false)`, validateFlag)
|
||||
}
|
||||
}
|
||||
// The flag was a boolean
|
||||
if b {
|
||||
return metav1.FieldValidationStrict, nil
|
||||
}
|
||||
return metav1.FieldValidationIgnore, nil
|
||||
}
|
||||
|
||||
type DryRunStrategy int
|
||||
|
||||
const (
|
||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
||||
package util
|
||||
|
||||
import (
|
||||
goerrors "errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
@ -27,6 +28,7 @@ import (
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||
@ -467,3 +469,68 @@ func TestDifferenceFunc(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetValidationDirective(t *testing.T) {
|
||||
tests := []struct {
|
||||
validateFlag string
|
||||
expectedDirective string
|
||||
expectedErr error
|
||||
}{
|
||||
{
|
||||
expectedDirective: metav1.FieldValidationStrict,
|
||||
},
|
||||
{
|
||||
validateFlag: "true",
|
||||
expectedDirective: metav1.FieldValidationStrict,
|
||||
},
|
||||
{
|
||||
validateFlag: "True",
|
||||
expectedDirective: metav1.FieldValidationStrict,
|
||||
},
|
||||
{
|
||||
validateFlag: "strict",
|
||||
expectedDirective: metav1.FieldValidationStrict,
|
||||
},
|
||||
{
|
||||
validateFlag: "warn",
|
||||
expectedDirective: metav1.FieldValidationWarn,
|
||||
},
|
||||
{
|
||||
validateFlag: "ignore",
|
||||
expectedDirective: metav1.FieldValidationIgnore,
|
||||
},
|
||||
{
|
||||
validateFlag: "false",
|
||||
expectedDirective: metav1.FieldValidationIgnore,
|
||||
},
|
||||
{
|
||||
validateFlag: "False",
|
||||
expectedDirective: metav1.FieldValidationIgnore,
|
||||
},
|
||||
{
|
||||
validateFlag: "foo",
|
||||
expectedDirective: metav1.FieldValidationStrict,
|
||||
expectedErr: goerrors.New(`invalid - validate option "foo"; must be one of: strict (or true), warn, ignore (or false)`),
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
cmd := &cobra.Command{}
|
||||
AddValidateFlags(cmd)
|
||||
cmd.Flags().Set("validate", tc.validateFlag)
|
||||
directive, err := GetValidationDirective(cmd)
|
||||
if directive != tc.expectedDirective {
|
||||
t.Errorf("validation directive, expected: %v, but got: %v", tc.expectedDirective, directive)
|
||||
}
|
||||
if tc.expectedErr != nil {
|
||||
if err.Error() != tc.expectedErr.Error() {
|
||||
t.Errorf("GetValidationDirective error, expected: %v, but got: %v", tc.expectedErr, err)
|
||||
}
|
||||
} else {
|
||||
if err != nil {
|
||||
t.Errorf("expecte no error, but got: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -43,12 +43,12 @@ func NewSchemaValidation(resources openapi.Resources) *SchemaValidation {
|
||||
// ValidateBytes will validates the object against using the Resources
|
||||
// object.
|
||||
func (v *SchemaValidation) ValidateBytes(data []byte) error {
|
||||
obj, err := parse(data)
|
||||
obj, err := Parse(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gvk, errs := getObjectKind(obj)
|
||||
gvk, errs := GetObjectKind(obj)
|
||||
if errs != nil {
|
||||
return utilerrors.NewAggregate(errs)
|
||||
}
|
||||
@ -71,7 +71,7 @@ func (v *SchemaValidation) validateList(object interface{}) []error {
|
||||
return []error{errors.New("invalid object to validate")}
|
||||
}
|
||||
for _, item := range fields["items"].([]interface{}) {
|
||||
if gvk, errs := getObjectKind(item); errs != nil {
|
||||
if gvk, errs := GetObjectKind(item); errs != nil {
|
||||
allErrors = append(allErrors, errs...)
|
||||
} else {
|
||||
allErrors = append(allErrors, v.validateResource(item, gvk)...)
|
||||
@ -90,7 +90,7 @@ func (v *SchemaValidation) validateResource(obj interface{}, gvk schema.GroupVer
|
||||
return validation.ValidateModel(obj, resource, gvk.Kind)
|
||||
}
|
||||
|
||||
func parse(data []byte) (interface{}, error) {
|
||||
func Parse(data []byte) (interface{}, error) {
|
||||
var obj interface{}
|
||||
out, err := yaml.ToJSON(data)
|
||||
if err != nil {
|
||||
@ -102,7 +102,7 @@ func parse(data []byte) (interface{}, error) {
|
||||
return obj, nil
|
||||
}
|
||||
|
||||
func getObjectKind(object interface{}) (schema.GroupVersionKind, []error) {
|
||||
func GetObjectKind(object interface{}) (schema.GroupVersionKind, []error) {
|
||||
var listErrors []error
|
||||
fields, ok := object.(map[string]interface{})
|
||||
if !ok || fields == nil {
|
||||
|
@ -22,7 +22,11 @@ import (
|
||||
"fmt"
|
||||
|
||||
ejson "github.com/exponent-io/jsonpath"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
||||
"k8s.io/cli-runtime/pkg/resource"
|
||||
"k8s.io/klog/v2"
|
||||
schemavalidation "k8s.io/kubectl/pkg/util/openapi/validation"
|
||||
)
|
||||
|
||||
// Schema is an interface that knows how to validate an API object serialized to a byte array.
|
||||
@ -101,3 +105,50 @@ func (c ConjunctiveSchema) ValidateBytes(data []byte) error {
|
||||
}
|
||||
return utilerrors.NewAggregate(list)
|
||||
}
|
||||
|
||||
func NewParamVerifyingSchema(s Schema, verifier resource.Verifier, directive string) Schema {
|
||||
return ¶mVerifyingSchema{
|
||||
schema: s,
|
||||
verifier: verifier,
|
||||
directive: directive,
|
||||
}
|
||||
}
|
||||
|
||||
// paramVerifyingSchema only performs validation
|
||||
// based on the fieldValidation query param
|
||||
// being unsupported by the apiserver, because
|
||||
// server-side validation will be performed instead
|
||||
// of client-side validation.
|
||||
type paramVerifyingSchema struct {
|
||||
schema Schema
|
||||
verifier resource.Verifier
|
||||
directive string
|
||||
}
|
||||
|
||||
// ValidateBytes validates bytes per a ParamVerifyingSchema
|
||||
func (c *paramVerifyingSchema) ValidateBytes(data []byte) error {
|
||||
obj, err := schemavalidation.Parse(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
gvk, errs := schemavalidation.GetObjectKind(obj)
|
||||
if errs != nil {
|
||||
return utilerrors.NewAggregate(errs)
|
||||
}
|
||||
|
||||
err = c.verifier.HasSupport(gvk)
|
||||
if resource.IsParamUnsupportedError(err) {
|
||||
switch c.directive {
|
||||
case metav1.FieldValidationStrict:
|
||||
return c.schema.ValidateBytes(data)
|
||||
case metav1.FieldValidationWarn:
|
||||
klog.Warningf("cannot perform warn validation if server-side field validation is unsupported, skipping validation")
|
||||
default:
|
||||
// can't be reached
|
||||
klog.Warningf("unexpected field validation directive: %s, skipping validation", c.directive)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
@ -19,6 +19,9 @@ package validation
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/cli-runtime/pkg/resource"
|
||||
)
|
||||
|
||||
func TestValidateDuplicateLabelsFailCases(t *testing.T) {
|
||||
@ -139,3 +142,121 @@ func TestConjunctiveSchema(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
type mockVerifier struct {
|
||||
supported bool
|
||||
}
|
||||
|
||||
func (v *mockVerifier) HasSupport(gvk schema.GroupVersionKind) error {
|
||||
if !v.supported {
|
||||
return resource.NewParamUnsupportedError(gvk, resource.QueryParamFieldValidation)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// TestParamVerifyingSchema tests that client-side schema validation
|
||||
// should be bypassed (and therefore validation succeeds) in all cases
|
||||
// except when the field validation is "Strict" and server-side validation is
|
||||
// unsupported.
|
||||
func TestParamVerifyingSchema(t *testing.T) {
|
||||
bytes := []byte(`
|
||||
{
|
||||
"kind": "Pod",
|
||||
"apiVersion": "v1",
|
||||
"metadata": {
|
||||
"name": "name",
|
||||
"labels": {
|
||||
"name": "redis-master"
|
||||
}
|
||||
},
|
||||
"spec": {
|
||||
"containers": [
|
||||
{
|
||||
"name": "master",
|
||||
"image": "gcr.io/fake_project/fake_image:fake_tag",
|
||||
"args": "this is a bad command"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
`)
|
||||
supportedVerifier := &mockVerifier{true}
|
||||
unsupportedVerifier := &mockVerifier{false}
|
||||
tests := []struct {
|
||||
name string
|
||||
supported bool
|
||||
schema Schema
|
||||
verifier resource.Verifier
|
||||
directive string
|
||||
shouldPass bool
|
||||
}{
|
||||
{
|
||||
name: "supported, strict",
|
||||
schema: NullSchema{},
|
||||
verifier: supportedVerifier,
|
||||
directive: "Strict",
|
||||
shouldPass: true,
|
||||
},
|
||||
{
|
||||
name: "supported, warn",
|
||||
schema: NullSchema{},
|
||||
verifier: supportedVerifier,
|
||||
directive: "Warn",
|
||||
shouldPass: true,
|
||||
},
|
||||
{
|
||||
name: "unsupported, strict",
|
||||
schema: NullSchema{},
|
||||
verifier: unsupportedVerifier,
|
||||
directive: "Strict",
|
||||
shouldPass: true,
|
||||
},
|
||||
{
|
||||
name: "unsupported, warn",
|
||||
schema: NullSchema{},
|
||||
verifier: unsupportedVerifier,
|
||||
directive: "Warn",
|
||||
shouldPass: true,
|
||||
},
|
||||
{
|
||||
name: "supported, strict, invalid schema",
|
||||
schema: AlwaysInvalidSchema{},
|
||||
verifier: supportedVerifier,
|
||||
directive: "Strict",
|
||||
shouldPass: true,
|
||||
},
|
||||
{
|
||||
name: "supported, warn, invalid schema",
|
||||
schema: AlwaysInvalidSchema{},
|
||||
verifier: supportedVerifier,
|
||||
directive: "Warn",
|
||||
shouldPass: true,
|
||||
},
|
||||
{
|
||||
name: "unsupported, strict, invalid schema",
|
||||
schema: AlwaysInvalidSchema{},
|
||||
verifier: unsupportedVerifier,
|
||||
directive: "Strict",
|
||||
shouldPass: false,
|
||||
},
|
||||
{
|
||||
name: "unsupported, warn, invalid schema",
|
||||
schema: AlwaysInvalidSchema{},
|
||||
verifier: unsupportedVerifier,
|
||||
directive: "Warn",
|
||||
shouldPass: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
schema := NewParamVerifyingSchema(tt.schema, tt.verifier, tt.directive)
|
||||
err := schema.ValidateBytes(bytes)
|
||||
if err != nil && tt.shouldPass {
|
||||
t.Errorf("Unexpected error: %v in %s", err, tt.name)
|
||||
}
|
||||
if err == nil && !tt.shouldPass {
|
||||
t.Errorf("Unexpected non-error: %s", tt.name)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -153,3 +153,62 @@ run_kubectl_create_kustomization_directory_tests() {
|
||||
set +o nounset
|
||||
set +o errexit
|
||||
}
|
||||
|
||||
# Runs tests related to kubectl create --validate
|
||||
run_kubectl_create_validate_tests() {
|
||||
set -o nounset
|
||||
set -o errexit
|
||||
|
||||
create_and_use_new_namespace
|
||||
|
||||
## test --validate=true
|
||||
kube::log::status "Testing kubectl create --validate=true"
|
||||
# create and verify
|
||||
output_message=$(! kubectl create -f hack/testdata/invalid-deployment-unknown-and-duplicate-fields.yaml --validate=true 2>&1)
|
||||
kube::test::if_has_string "${output_message}" 'error validating data'
|
||||
|
||||
## test --validate=false
|
||||
kube::log::status "Testing kubectl create --validate=false"
|
||||
# create and verify
|
||||
output_message=$(kubectl create -f hack/testdata/invalid-deployment-unknown-and-duplicate-fields.yaml --validate=false)
|
||||
kube::test::if_has_string "${output_message}" "deployment.apps/invalid-nginx-deployment created"
|
||||
# cleanup
|
||||
kubectl delete deployment invalid-nginx-deployment
|
||||
|
||||
## test --validate=strict
|
||||
kube::log::status "Testing kubectl create --validate=strict"
|
||||
# create and verify
|
||||
output_message=$(! kubectl create -f hack/testdata/invalid-deployment-unknown-and-duplicate-fields.yaml --validate=strict 2>&1)
|
||||
kube::test::if_has_string "${output_message}" 'error validating data'
|
||||
|
||||
## test --validate=warn
|
||||
kube::log::status "Testing kubectl create --validate=warn"
|
||||
# create and verify
|
||||
output_message=$(kubectl create -f hack/testdata/invalid-deployment-unknown-and-duplicate-fields.yaml --validate=warn)
|
||||
kube::test::if_has_string "${output_message}" "deployment.apps/invalid-nginx-deployment created"
|
||||
# cleanup
|
||||
kubectl delete deployment invalid-nginx-deployment
|
||||
|
||||
## test --validate=ignore
|
||||
kube::log::status "Testing kubectl create --validate=ignore"
|
||||
# create and verify
|
||||
output_message=$(kubectl create -f hack/testdata/invalid-deployment-unknown-and-duplicate-fields.yaml --validate=ignore)
|
||||
kube::test::if_has_string "${output_message}" "deployment.apps/invalid-nginx-deployment created"
|
||||
# cleanup
|
||||
kubectl delete deployment invalid-nginx-deployment
|
||||
|
||||
## test default is strict validation
|
||||
kube::log::status "Testing kubectl create"
|
||||
# create and verify
|
||||
output_message=$(! kubectl create -f hack/testdata/invalid-deployment-unknown-and-duplicate-fields.yaml 2>&1)
|
||||
kube::test::if_has_string "${output_message}" 'error validating data'
|
||||
|
||||
## test invalid validate value
|
||||
kube::log::status "Testing kubectl create --validate=foo"
|
||||
# create and verify
|
||||
output_message=$(! kubectl create -f hack/testdata/invalid-deployment-unknown-and-duplicate-fields.yaml --validate=foo 2>&1)
|
||||
kube::test::if_has_string "${output_message}" 'invalid - validate option "foo"'
|
||||
|
||||
set +o nounset
|
||||
set +o errexit
|
||||
}
|
||||
|
@ -573,6 +573,7 @@ runTests() {
|
||||
fi
|
||||
if kube::test::if_supports_resource "${deployments}"; then
|
||||
record_command run_kubectl_create_kustomization_directory_tests
|
||||
record_command run_kubectl_create_validate_tests
|
||||
fi
|
||||
|
||||
######################
|
||||
|
Loading…
Reference in New Issue
Block a user