mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-21 19:01:49 +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) {
|
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
|
// build the printer
|
||||||
|
@ -54,6 +54,10 @@ type Helper struct {
|
|||||||
// FieldManager is the name associated with the actor or entity that is making
|
// FieldManager is the name associated with the actor or entity that is making
|
||||||
// changes.
|
// changes.
|
||||||
FieldManager string
|
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
|
// NewHelper creates a Helper from a ResourceMapping
|
||||||
@ -79,6 +83,13 @@ func (m *Helper) WithFieldManager(fieldManager string) *Helper {
|
|||||||
return m
|
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>)
|
// Subresource sets the helper to access (<resource>/[ns/<namespace>/]<name>/<subresource>)
|
||||||
func (m *Helper) WithSubresource(subresource string) *Helper {
|
func (m *Helper) WithSubresource(subresource string) *Helper {
|
||||||
m.Subresource = subresource
|
m.Subresource = subresource
|
||||||
@ -206,6 +217,9 @@ func (m *Helper) CreateWithOptions(namespace string, modify bool, obj runtime.Ob
|
|||||||
if m.FieldManager != "" {
|
if m.FieldManager != "" {
|
||||||
options.FieldManager = m.FieldManager
|
options.FieldManager = m.FieldManager
|
||||||
}
|
}
|
||||||
|
if m.FieldValidation != "" {
|
||||||
|
options.FieldValidation = m.FieldValidation
|
||||||
|
}
|
||||||
if modify {
|
if modify {
|
||||||
// Attempt to version the object based on client logic.
|
// Attempt to version the object based on client logic.
|
||||||
version, err := metadataAccessor.ResourceVersion(obj)
|
version, err := metadataAccessor.ResourceVersion(obj)
|
||||||
@ -242,6 +256,9 @@ func (m *Helper) Patch(namespace, name string, pt types.PatchType, data []byte,
|
|||||||
if m.FieldManager != "" {
|
if m.FieldManager != "" {
|
||||||
options.FieldManager = m.FieldManager
|
options.FieldManager = m.FieldManager
|
||||||
}
|
}
|
||||||
|
if m.FieldValidation != "" {
|
||||||
|
options.FieldValidation = m.FieldValidation
|
||||||
|
}
|
||||||
return m.RESTClient.Patch(pt).
|
return m.RESTClient.Patch(pt).
|
||||||
NamespaceIfScoped(namespace, m.NamespaceScoped).
|
NamespaceIfScoped(namespace, m.NamespaceScoped).
|
||||||
Resource(m.Resource).
|
Resource(m.Resource).
|
||||||
@ -262,6 +279,9 @@ func (m *Helper) Replace(namespace, name string, overwrite bool, obj runtime.Obj
|
|||||||
if m.FieldManager != "" {
|
if m.FieldManager != "" {
|
||||||
options.FieldManager = m.FieldManager
|
options.FieldManager = m.FieldManager
|
||||||
}
|
}
|
||||||
|
if m.FieldValidation != "" {
|
||||||
|
options.FieldValidation = m.FieldValidation
|
||||||
|
}
|
||||||
|
|
||||||
// Attempt to version the object based on client logic.
|
// Attempt to version the object based on client logic.
|
||||||
version, err := metadataAccessor.ResourceVersion(obj)
|
version, err := metadataAccessor.ResourceVersion(obj)
|
||||||
|
@ -62,6 +62,11 @@ type QueryParamVerifier struct {
|
|||||||
queryParam VerifiableQueryParam
|
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
|
// VerifiableQueryParam is a query parameter who's enablement on the
|
||||||
// apiserver can be determined by evaluating the OpenAPI for a specific
|
// apiserver can be determined by evaluating the OpenAPI for a specific
|
||||||
// GVK.
|
// GVK.
|
||||||
@ -72,6 +77,7 @@ const (
|
|||||||
QueryParamFieldValidation VerifiableQueryParam = "fieldValidation"
|
QueryParamFieldValidation VerifiableQueryParam = "fieldValidation"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// HasSupport checks if the given gvk supports the query param configured on v
|
||||||
func (v *QueryParamVerifier) HasSupport(gvk schema.GroupVersionKind) error {
|
func (v *QueryParamVerifier) HasSupport(gvk schema.GroupVersionKind) error {
|
||||||
oapi, err := v.openAPIGetter.OpenAPISchema()
|
oapi, err := v.openAPIGetter.OpenAPISchema()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -90,7 +96,7 @@ func (v *QueryParamVerifier) HasSupport(gvk schema.GroupVersionKind) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !supports {
|
if !supports {
|
||||||
return newParamUnsupportedError(gvk, v.queryParam)
|
return NewParamUnsupportedError(gvk, v.queryParam)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -100,7 +106,7 @@ type paramUnsupportedError struct {
|
|||||||
param VerifiableQueryParam
|
param VerifiableQueryParam
|
||||||
}
|
}
|
||||||
|
|
||||||
func newParamUnsupportedError(gvk schema.GroupVersionKind, param VerifiableQueryParam) error {
|
func NewParamUnsupportedError(gvk schema.GroupVersionKind, param VerifiableQueryParam) error {
|
||||||
return ¶mUnsupportedError{
|
return ¶mUnsupportedError{
|
||||||
gvk: gvk,
|
gvk: gvk,
|
||||||
param: param,
|
param: param,
|
||||||
|
@ -80,25 +80,27 @@ type ApplyOptions struct {
|
|||||||
|
|
||||||
DeleteOptions *delete.DeleteOptions
|
DeleteOptions *delete.DeleteOptions
|
||||||
|
|
||||||
ServerSideApply bool
|
ServerSideApply bool
|
||||||
ForceConflicts bool
|
ForceConflicts bool
|
||||||
FieldManager string
|
FieldManager string
|
||||||
Selector string
|
Selector string
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
Prune bool
|
FieldValidationVerifier *resource.QueryParamVerifier
|
||||||
PruneResources []prune.Resource
|
Prune bool
|
||||||
cmdBaseName string
|
PruneResources []prune.Resource
|
||||||
All bool
|
cmdBaseName string
|
||||||
Overwrite bool
|
All bool
|
||||||
OpenAPIPatch bool
|
Overwrite bool
|
||||||
PruneWhitelist []string
|
OpenAPIPatch bool
|
||||||
|
PruneWhitelist []string
|
||||||
|
|
||||||
Validator validation.Schema
|
ValidationDirective string
|
||||||
Builder *resource.Builder
|
Validator validation.Schema
|
||||||
Mapper meta.RESTMapper
|
Builder *resource.Builder
|
||||||
DynamicClient dynamic.Interface
|
Mapper meta.RESTMapper
|
||||||
OpenAPISchema openapi.Resources
|
DynamicClient dynamic.Interface
|
||||||
|
OpenAPISchema openapi.Resources
|
||||||
|
|
||||||
Namespace string
|
Namespace string
|
||||||
EnforceNamespace bool
|
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)
|
dryRunVerifier := resource.NewQueryParamVerifier(dynamicClient, flags.Factory.OpenAPIGetter(), resource.QueryParamDryRun)
|
||||||
|
fieldValidationVerifier := resource.NewQueryParamVerifier(dynamicClient, flags.Factory.OpenAPIGetter(), resource.QueryParamFieldValidation)
|
||||||
fieldManager := GetApplyFieldManagerFlag(cmd, serverSideApply)
|
fieldManager := GetApplyFieldManagerFlag(cmd, serverSideApply)
|
||||||
|
|
||||||
// allow for a success message operation to be specified at print time
|
// 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()
|
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 {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -308,14 +316,15 @@ func (flags *ApplyFlags) ToOptions(cmd *cobra.Command, baseName string, args []s
|
|||||||
OpenAPIPatch: flags.OpenAPIPatch,
|
OpenAPIPatch: flags.OpenAPIPatch,
|
||||||
PruneWhitelist: flags.PruneWhitelist,
|
PruneWhitelist: flags.PruneWhitelist,
|
||||||
|
|
||||||
Recorder: recorder,
|
Recorder: recorder,
|
||||||
Namespace: namespace,
|
Namespace: namespace,
|
||||||
EnforceNamespace: enforceNamespace,
|
EnforceNamespace: enforceNamespace,
|
||||||
Validator: validator,
|
Validator: validator,
|
||||||
Builder: builder,
|
ValidationDirective: validationDirective,
|
||||||
Mapper: mapper,
|
Builder: builder,
|
||||||
DynamicClient: dynamicClient,
|
Mapper: mapper,
|
||||||
OpenAPISchema: openAPISchema,
|
DynamicClient: dynamicClient,
|
||||||
|
OpenAPISchema: openAPISchema,
|
||||||
|
|
||||||
IOStreams: flags.IOStreams,
|
IOStreams: flags.IOStreams,
|
||||||
|
|
||||||
@ -407,7 +416,6 @@ func (o *ApplyOptions) SetObjects(infos []*resource.Info) {
|
|||||||
|
|
||||||
// Run executes the `apply` command.
|
// Run executes the `apply` command.
|
||||||
func (o *ApplyOptions) Run() error {
|
func (o *ApplyOptions) Run() error {
|
||||||
|
|
||||||
if o.PreProcessorFn != nil {
|
if o.PreProcessorFn != nil {
|
||||||
klog.V(4).Infof("Running apply pre-processor function")
|
klog.V(4).Infof("Running apply pre-processor function")
|
||||||
if err := o.PreProcessorFn(); err != nil {
|
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).
|
helper := resource.NewHelper(info.Client, info.Mapping).
|
||||||
DryRun(o.DryRunStrategy == cmdutil.DryRunServer).
|
DryRun(o.DryRunStrategy == cmdutil.DryRunServer).
|
||||||
WithFieldManager(o.FieldManager)
|
WithFieldManager(o.FieldManager).
|
||||||
|
WithFieldValidation(o.ValidationDirective)
|
||||||
|
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
// Ensure the APIServer supports server-side dry-run for the resource,
|
// 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,
|
cmd.Flags().BoolVar(&o.WindowsLineEndings, "windows-line-endings", o.WindowsLineEndings,
|
||||||
"Defaults to the line ending native to your platform.")
|
"Defaults to the line ending native to your platform.")
|
||||||
cmdutil.AddFieldManagerFlagVar(cmd, &o.FieldManager, FieldManagerClientSideApply)
|
cmdutil.AddFieldManagerFlagVar(cmd, &o.FieldManager, FieldManagerClientSideApply)
|
||||||
|
cmdutil.AddValidateFlags(cmd)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
@ -51,8 +51,11 @@ type CreateOptions struct {
|
|||||||
PrintFlags *genericclioptions.PrintFlags
|
PrintFlags *genericclioptions.PrintFlags
|
||||||
RecordFlags *genericclioptions.RecordFlags
|
RecordFlags *genericclioptions.RecordFlags
|
||||||
|
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
|
FieldValidationVerifier *resource.QueryParamVerifier
|
||||||
|
|
||||||
|
ValidationDirective string
|
||||||
|
|
||||||
fieldManager string
|
fieldManager string
|
||||||
|
|
||||||
@ -208,6 +211,12 @@ func (o *CreateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
o.DryRunVerifier = resource.NewQueryParamVerifier(dynamicClient, f.OpenAPIGetter(), resource.QueryParamDryRun)
|
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()
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -236,7 +245,8 @@ func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error {
|
|||||||
if o.EditBeforeCreate {
|
if o.EditBeforeCreate {
|
||||||
return RunEditOnCreate(f, o.PrintFlags, o.RecordFlags, o.IOStreams, cmd, &o.FilenameOptions, o.fieldManager)
|
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 {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -283,6 +293,7 @@ func (o *CreateOptions) RunCreate(f cmdutil.Factory, cmd *cobra.Command) error {
|
|||||||
NewHelper(info.Client, info.Mapping).
|
NewHelper(info.Client, info.Mapping).
|
||||||
DryRun(o.DryRunStrategy == cmdutil.DryRunServer).
|
DryRun(o.DryRunStrategy == cmdutil.DryRunServer).
|
||||||
WithFieldManager(o.fieldManager).
|
WithFieldManager(o.fieldManager).
|
||||||
|
WithFieldValidation(o.ValidationDirective).
|
||||||
Create(info.Namespace, true, info.Object)
|
Create(info.Namespace, true, info.Object)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return cmdutil.AddSourceToErr("creating", info.Source, err)
|
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 {
|
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 := editor.NewEditOptions(editor.EditBeforeCreateMode, ioStreams)
|
||||||
editOptions.FilenameOptions = *options
|
editOptions.FilenameOptions = *options
|
||||||
|
validationDirective, err := cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
editOptions.ValidateOptions = cmdutil.ValidateOptions{
|
editOptions.ValidateOptions = cmdutil.ValidateOptions{
|
||||||
EnableValidation: cmdutil.GetFlagBool(cmd, "validate"),
|
ValidationDirective: string(validationDirective),
|
||||||
}
|
}
|
||||||
editOptions.PrintFlags = printFlags
|
editOptions.PrintFlags = printFlags
|
||||||
editOptions.ApplyAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
|
editOptions.ApplyAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
|
||||||
editOptions.RecordFlags = recordFlags
|
editOptions.RecordFlags = recordFlags
|
||||||
editOptions.FieldManager = "kubectl-create"
|
editOptions.FieldManager = "kubectl-create"
|
||||||
|
|
||||||
err := editOptions.Complete(f, []string{}, cmd)
|
err = editOptions.Complete(f, []string{}, cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -347,6 +362,7 @@ type CreateSubcommandOptions struct {
|
|||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
CreateAnnotation bool
|
CreateAnnotation bool
|
||||||
FieldManager string
|
FieldManager string
|
||||||
|
ValidationDirective string
|
||||||
|
|
||||||
Namespace string
|
Namespace string
|
||||||
EnforceNamespace bool
|
EnforceNamespace bool
|
||||||
@ -393,6 +409,11 @@ func (o *CreateSubcommandOptions) Complete(f cmdutil.Factory, cmd *cobra.Command
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
o.PrintObj = func(obj kruntime.Object, out io.Writer) error {
|
o.PrintObj = func(obj kruntime.Object, out io.Writer) error {
|
||||||
return printer.PrintObj(obj, out)
|
return printer.PrintObj(obj, out)
|
||||||
}
|
}
|
||||||
@ -447,6 +468,8 @@ func (o *CreateSubcommandOptions) Run() error {
|
|||||||
if o.FieldManager != "" {
|
if o.FieldManager != "" {
|
||||||
createOptions.FieldManager = o.FieldManager
|
createOptions.FieldManager = o.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = o.ValidationDirective
|
||||||
|
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
if err := o.DryRunVerifier.HasSupport(mapping.GroupVersionKind); err != nil {
|
if err := o.DryRunVerifier.HasSupport(mapping.GroupVersionKind); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -213,6 +213,7 @@ func (c *CreateClusterRoleOptions) RunCreateRole() error {
|
|||||||
if c.FieldManager != "" {
|
if c.FieldManager != "" {
|
||||||
createOptions.FieldManager = c.FieldManager
|
createOptions.FieldManager = c.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = c.ValidationDirective
|
||||||
if c.DryRunStrategy == cmdutil.DryRunServer {
|
if c.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
if err := c.DryRunVerifier.HasSupport(clusterRole.GroupVersionKind()); err != nil {
|
if err := c.DryRunVerifier.HasSupport(clusterRole.GroupVersionKind()); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -59,9 +59,10 @@ type ClusterRoleBindingOptions struct {
|
|||||||
FieldManager string
|
FieldManager string
|
||||||
CreateAnnotation bool
|
CreateAnnotation bool
|
||||||
|
|
||||||
Client rbacclientv1.RbacV1Interface
|
Client rbacclientv1.RbacV1Interface
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
|
ValidationDirective string
|
||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
}
|
}
|
||||||
@ -149,6 +150,10 @@ func (o *ClusterRoleBindingOptions) Complete(f cmdutil.Factory, cmd *cobra.Comma
|
|||||||
o.PrintObj = func(obj runtime.Object) error {
|
o.PrintObj = func(obj runtime.Object) error {
|
||||||
return printer.PrintObj(obj, o.Out)
|
return printer.PrintObj(obj, o.Out)
|
||||||
}
|
}
|
||||||
|
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -169,6 +174,7 @@ func (o *ClusterRoleBindingOptions) Run() error {
|
|||||||
if o.FieldManager != "" {
|
if o.FieldManager != "" {
|
||||||
createOptions.FieldManager = o.FieldManager
|
createOptions.FieldManager = o.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = o.ValidationDirective
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
if err := o.DryRunVerifier.HasSupport(clusterRoleBinding.GroupVersionKind()); err != nil {
|
if err := o.DryRunVerifier.HasSupport(clusterRoleBinding.GroupVersionKind()); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -96,9 +96,10 @@ type ConfigMapOptions struct {
|
|||||||
Namespace string
|
Namespace string
|
||||||
EnforceNamespace bool
|
EnforceNamespace bool
|
||||||
|
|
||||||
Client corev1client.CoreV1Interface
|
Client corev1client.CoreV1Interface
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
|
ValidationDirective string
|
||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
}
|
}
|
||||||
@ -194,6 +195,11 @@ func (o *ConfigMapOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
|
|||||||
return printer.PrintObj(obj, o.Out)
|
return printer.PrintObj(obj, o.Out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -222,6 +228,7 @@ func (o *ConfigMapOptions) Run() error {
|
|||||||
if o.FieldManager != "" {
|
if o.FieldManager != "" {
|
||||||
createOptions.FieldManager = o.FieldManager
|
createOptions.FieldManager = o.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = o.ValidationDirective
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
if err := o.DryRunVerifier.HasSupport(configMap.GroupVersionKind()); err != nil {
|
if err := o.DryRunVerifier.HasSupport(configMap.GroupVersionKind()); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -60,14 +60,15 @@ type CreateCronJobOptions struct {
|
|||||||
Command []string
|
Command []string
|
||||||
Restart string
|
Restart string
|
||||||
|
|
||||||
Namespace string
|
Namespace string
|
||||||
EnforceNamespace bool
|
EnforceNamespace bool
|
||||||
Client batchv1client.BatchV1Interface
|
Client batchv1client.BatchV1Interface
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
Builder *resource.Builder
|
ValidationDirective string
|
||||||
FieldManager string
|
Builder *resource.Builder
|
||||||
CreateAnnotation bool
|
FieldManager string
|
||||||
|
CreateAnnotation bool
|
||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
}
|
}
|
||||||
@ -160,6 +161,11 @@ func (o *CreateCronJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, a
|
|||||||
return printer.PrintObj(obj, o.Out)
|
return printer.PrintObj(obj, o.Out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,6 +181,7 @@ func (o *CreateCronJobOptions) Run() error {
|
|||||||
if o.FieldManager != "" {
|
if o.FieldManager != "" {
|
||||||
createOptions.FieldManager = o.FieldManager
|
createOptions.FieldManager = o.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = o.ValidationDirective
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
if err := o.DryRunVerifier.HasSupport(cronJob.GroupVersionKind()); err != nil {
|
if err := o.DryRunVerifier.HasSupport(cronJob.GroupVersionKind()); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -72,9 +72,10 @@ type CreateDeploymentOptions struct {
|
|||||||
FieldManager string
|
FieldManager string
|
||||||
CreateAnnotation bool
|
CreateAnnotation bool
|
||||||
|
|
||||||
Client appsv1client.AppsV1Interface
|
Client appsv1client.AppsV1Interface
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
|
ValidationDirective string
|
||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
}
|
}
|
||||||
@ -167,6 +168,11 @@ func (o *CreateDeploymentOptions) Complete(f cmdutil.Factory, cmd *cobra.Command
|
|||||||
return printer.PrintObj(obj, o.Out)
|
return printer.PrintObj(obj, o.Out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -191,6 +197,7 @@ func (o *CreateDeploymentOptions) Run() error {
|
|||||||
if o.FieldManager != "" {
|
if o.FieldManager != "" {
|
||||||
createOptions.FieldManager = o.FieldManager
|
createOptions.FieldManager = o.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = o.ValidationDirective
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
if err := o.DryRunVerifier.HasSupport(deploy.GroupVersionKind()); err != nil {
|
if err := o.DryRunVerifier.HasSupport(deploy.GroupVersionKind()); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -116,9 +116,10 @@ type CreateIngressOptions struct {
|
|||||||
EnforceNamespace bool
|
EnforceNamespace bool
|
||||||
CreateAnnotation bool
|
CreateAnnotation bool
|
||||||
|
|
||||||
Client networkingv1client.NetworkingV1Interface
|
Client networkingv1client.NetworkingV1Interface
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
|
ValidationDirective string
|
||||||
|
|
||||||
FieldManager 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 {
|
o.PrintObj = func(obj runtime.Object) error {
|
||||||
return printer.PrintObj(obj, o.Out)
|
return printer.PrintObj(obj, o.Out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -254,6 +260,7 @@ func (o *CreateIngressOptions) Run() error {
|
|||||||
if o.FieldManager != "" {
|
if o.FieldManager != "" {
|
||||||
createOptions.FieldManager = o.FieldManager
|
createOptions.FieldManager = o.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = o.ValidationDirective
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
if err := o.DryRunVerifier.HasSupport(ingress.GroupVersionKind()); err != nil {
|
if err := o.DryRunVerifier.HasSupport(ingress.GroupVersionKind()); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -62,14 +62,15 @@ type CreateJobOptions struct {
|
|||||||
From string
|
From string
|
||||||
Command []string
|
Command []string
|
||||||
|
|
||||||
Namespace string
|
Namespace string
|
||||||
EnforceNamespace bool
|
EnforceNamespace bool
|
||||||
Client batchv1client.BatchV1Interface
|
Client batchv1client.BatchV1Interface
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
Builder *resource.Builder
|
ValidationDirective string
|
||||||
FieldManager string
|
Builder *resource.Builder
|
||||||
CreateAnnotation bool
|
FieldManager string
|
||||||
|
CreateAnnotation bool
|
||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
}
|
}
|
||||||
@ -155,6 +156,11 @@ func (o *CreateJobOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
|
|||||||
return printer.PrintObj(obj, o.Out)
|
return printer.PrintObj(obj, o.Out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,6 +213,7 @@ func (o *CreateJobOptions) Run() error {
|
|||||||
if o.FieldManager != "" {
|
if o.FieldManager != "" {
|
||||||
createOptions.FieldManager = o.FieldManager
|
createOptions.FieldManager = o.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = o.ValidationDirective
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
if err := o.DryRunVerifier.HasSupport(job.GroupVersionKind()); err != nil {
|
if err := o.DryRunVerifier.HasSupport(job.GroupVersionKind()); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -52,10 +52,11 @@ type NamespaceOptions struct {
|
|||||||
// Name of resource being created
|
// Name of resource being created
|
||||||
Name string
|
Name string
|
||||||
|
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
CreateAnnotation bool
|
ValidationDirective string
|
||||||
FieldManager string
|
CreateAnnotation bool
|
||||||
|
FieldManager string
|
||||||
|
|
||||||
Client *coreclient.CoreV1Client
|
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 {
|
o.PrintObj = func(obj runtime.Object) error {
|
||||||
return printer.PrintObj(obj, o.Out)
|
return printer.PrintObj(obj, o.Out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -155,6 +161,7 @@ func (o *NamespaceOptions) Run() error {
|
|||||||
if o.FieldManager != "" {
|
if o.FieldManager != "" {
|
||||||
createOptions.FieldManager = o.FieldManager
|
createOptions.FieldManager = o.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = o.ValidationDirective
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
if err := o.DryRunVerifier.HasSupport(namespace.GroupVersionKind()); err != nil {
|
if err := o.DryRunVerifier.HasSupport(namespace.GroupVersionKind()); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -70,9 +70,10 @@ type PodDisruptionBudgetOpts struct {
|
|||||||
Namespace string
|
Namespace string
|
||||||
EnforceNamespace bool
|
EnforceNamespace bool
|
||||||
|
|
||||||
Client *policyv1client.PolicyV1Client
|
Client *policyv1client.PolicyV1Client
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resourcecli.QueryParamVerifier
|
DryRunVerifier *resourcecli.QueryParamVerifier
|
||||||
|
ValidationDirective string
|
||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
}
|
}
|
||||||
@ -165,6 +166,11 @@ func (o *PodDisruptionBudgetOpts) Complete(f cmdutil.Factory, cmd *cobra.Command
|
|||||||
return printer.PrintObj(obj, o.Out)
|
return printer.PrintObj(obj, o.Out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,6 +223,7 @@ func (o *PodDisruptionBudgetOpts) Run() error {
|
|||||||
if o.FieldManager != "" {
|
if o.FieldManager != "" {
|
||||||
createOptions.FieldManager = o.FieldManager
|
createOptions.FieldManager = o.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = o.ValidationDirective
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
if err := o.DryRunVerifier.HasSupport(podDisruptionBudget.GroupVersionKind()); err != nil {
|
if err := o.DryRunVerifier.HasSupport(podDisruptionBudget.GroupVersionKind()); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -64,9 +64,10 @@ type PriorityClassOptions struct {
|
|||||||
FieldManager string
|
FieldManager string
|
||||||
CreateAnnotation bool
|
CreateAnnotation bool
|
||||||
|
|
||||||
Client *schedulingv1client.SchedulingV1Client
|
Client *schedulingv1client.SchedulingV1Client
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
|
ValidationDirective string
|
||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
}
|
}
|
||||||
@ -149,6 +150,11 @@ func (o *PriorityClassOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, a
|
|||||||
return printer.PrintObj(obj, o.Out)
|
return printer.PrintObj(obj, o.Out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -168,6 +174,7 @@ func (o *PriorityClassOptions) Run() error {
|
|||||||
if o.FieldManager != "" {
|
if o.FieldManager != "" {
|
||||||
createOptions.FieldManager = o.FieldManager
|
createOptions.FieldManager = o.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = o.ValidationDirective
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
if err := o.DryRunVerifier.HasSupport(priorityClass.GroupVersionKind()); err != nil {
|
if err := o.DryRunVerifier.HasSupport(priorityClass.GroupVersionKind()); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -66,9 +66,10 @@ type QuotaOpts struct {
|
|||||||
Namespace string
|
Namespace string
|
||||||
EnforceNamespace bool
|
EnforceNamespace bool
|
||||||
|
|
||||||
Client *coreclient.CoreV1Client
|
Client *coreclient.CoreV1Client
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resourcecli.QueryParamVerifier
|
DryRunVerifier *resourcecli.QueryParamVerifier
|
||||||
|
ValidationDirective string
|
||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
}
|
}
|
||||||
@ -155,6 +156,11 @@ func (o *QuotaOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, args []strin
|
|||||||
return printer.PrintObj(obj, o.Out)
|
return printer.PrintObj(obj, o.Out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -182,6 +188,7 @@ func (o *QuotaOpts) Run() error {
|
|||||||
if o.FieldManager != "" {
|
if o.FieldManager != "" {
|
||||||
createOptions.FieldManager = o.FieldManager
|
createOptions.FieldManager = o.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = o.ValidationDirective
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
if err := o.DryRunVerifier.HasSupport(resourceQuota.GroupVersionKind()); err != nil {
|
if err := o.DryRunVerifier.HasSupport(resourceQuota.GroupVersionKind()); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -136,16 +136,17 @@ type CreateRoleOptions struct {
|
|||||||
Resources []ResourceOptions
|
Resources []ResourceOptions
|
||||||
ResourceNames []string
|
ResourceNames []string
|
||||||
|
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
OutputFormat string
|
ValidationDirective string
|
||||||
Namespace string
|
OutputFormat string
|
||||||
EnforceNamespace bool
|
Namespace string
|
||||||
Client clientgorbacv1.RbacV1Interface
|
EnforceNamespace bool
|
||||||
Mapper meta.RESTMapper
|
Client clientgorbacv1.RbacV1Interface
|
||||||
PrintObj func(obj runtime.Object) error
|
Mapper meta.RESTMapper
|
||||||
FieldManager string
|
PrintObj func(obj runtime.Object) error
|
||||||
CreateAnnotation bool
|
FieldManager string
|
||||||
|
CreateAnnotation bool
|
||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
}
|
}
|
||||||
@ -271,6 +272,11 @@ func (o *CreateRoleOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args
|
|||||||
return printer.PrintObj(obj, o.Out)
|
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()
|
o.Namespace, o.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -374,6 +380,7 @@ func (o *CreateRoleOptions) RunCreateRole() error {
|
|||||||
if o.FieldManager != "" {
|
if o.FieldManager != "" {
|
||||||
createOptions.FieldManager = o.FieldManager
|
createOptions.FieldManager = o.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = o.ValidationDirective
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
if err := o.DryRunVerifier.HasSupport(role.GroupVersionKind()); err != nil {
|
if err := o.DryRunVerifier.HasSupport(role.GroupVersionKind()); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -61,9 +61,10 @@ type RoleBindingOptions struct {
|
|||||||
FieldManager string
|
FieldManager string
|
||||||
CreateAnnotation bool
|
CreateAnnotation bool
|
||||||
|
|
||||||
Client rbacclientv1.RbacV1Interface
|
Client rbacclientv1.RbacV1Interface
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
|
ValidationDirective string
|
||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
}
|
}
|
||||||
@ -149,6 +150,11 @@ func (o *RoleBindingOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, arg
|
|||||||
o.PrintObj = func(obj runtime.Object) error {
|
o.PrintObj = func(obj runtime.Object) error {
|
||||||
return printer.PrintObj(obj, o.Out)
|
return printer.PrintObj(obj, o.Out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,6 +184,7 @@ func (o *RoleBindingOptions) Run() error {
|
|||||||
if o.FieldManager != "" {
|
if o.FieldManager != "" {
|
||||||
createOptions.FieldManager = o.FieldManager
|
createOptions.FieldManager = o.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = o.ValidationDirective
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
if err := o.DryRunVerifier.HasSupport(roleBinding.GroupVersionKind()); err != nil {
|
if err := o.DryRunVerifier.HasSupport(roleBinding.GroupVersionKind()); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -112,9 +112,10 @@ type CreateSecretOptions struct {
|
|||||||
Namespace string
|
Namespace string
|
||||||
EnforceNamespace bool
|
EnforceNamespace bool
|
||||||
|
|
||||||
Client corev1client.CoreV1Interface
|
Client corev1client.CoreV1Interface
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
|
ValidationDirective string
|
||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
}
|
}
|
||||||
@ -212,6 +213,11 @@ func (o *CreateSecretOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, ar
|
|||||||
return printer.PrintObj(obj, o.Out)
|
return printer.PrintObj(obj, o.Out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,6 +248,7 @@ func (o *CreateSecretOptions) Run() error {
|
|||||||
if o.FieldManager != "" {
|
if o.FieldManager != "" {
|
||||||
createOptions.FieldManager = o.FieldManager
|
createOptions.FieldManager = o.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = o.ValidationDirective
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
err := o.DryRunVerifier.HasSupport(secret.GroupVersionKind())
|
err := o.DryRunVerifier.HasSupport(secret.GroupVersionKind())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -108,9 +108,10 @@ type CreateSecretDockerRegistryOptions struct {
|
|||||||
Namespace string
|
Namespace string
|
||||||
EnforceNamespace bool
|
EnforceNamespace bool
|
||||||
|
|
||||||
Client corev1client.CoreV1Interface
|
Client corev1client.CoreV1Interface
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
|
ValidationDirective string
|
||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
}
|
}
|
||||||
@ -211,6 +212,11 @@ func (o *CreateSecretDockerRegistryOptions) Complete(f cmdutil.Factory, cmd *cob
|
|||||||
return printer.PrintObj(obj, o.Out)
|
return printer.PrintObj(obj, o.Out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,6 +247,7 @@ func (o *CreateSecretDockerRegistryOptions) Run() error {
|
|||||||
if o.FieldManager != "" {
|
if o.FieldManager != "" {
|
||||||
createOptions.FieldManager = o.FieldManager
|
createOptions.FieldManager = o.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = o.ValidationDirective
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
err := o.DryRunVerifier.HasSupport(secretDockerRegistry.GroupVersionKind())
|
err := o.DryRunVerifier.HasSupport(secretDockerRegistry.GroupVersionKind())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -69,9 +69,10 @@ type CreateSecretTLSOptions struct {
|
|||||||
Namespace string
|
Namespace string
|
||||||
EnforceNamespace bool
|
EnforceNamespace bool
|
||||||
|
|
||||||
Client corev1client.CoreV1Interface
|
Client corev1client.CoreV1Interface
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
|
ValidationDirective string
|
||||||
|
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
}
|
}
|
||||||
@ -168,6 +169,11 @@ func (o *CreateSecretTLSOptions) Complete(f cmdutil.Factory, cmd *cobra.Command,
|
|||||||
return printer.PrintObj(obj, o.Out)
|
return printer.PrintObj(obj, o.Out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -198,6 +204,7 @@ func (o *CreateSecretTLSOptions) Run() error {
|
|||||||
if o.FieldManager != "" {
|
if o.FieldManager != "" {
|
||||||
createOptions.FieldManager = o.FieldManager
|
createOptions.FieldManager = o.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = o.ValidationDirective
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
err := o.DryRunVerifier.HasSupport(secretTLS.GroupVersionKind())
|
err := o.DryRunVerifier.HasSupport(secretTLS.GroupVersionKind())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -74,9 +74,10 @@ type ServiceOptions struct {
|
|||||||
Namespace string
|
Namespace string
|
||||||
EnforceNamespace bool
|
EnforceNamespace bool
|
||||||
|
|
||||||
Client corev1client.CoreV1Interface
|
Client corev1client.CoreV1Interface
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
|
ValidationDirective string
|
||||||
genericclioptions.IOStreams
|
genericclioptions.IOStreams
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,6 +132,11 @@ func (o *ServiceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
|||||||
return printer.PrintObj(obj, o.Out)
|
return printer.PrintObj(obj, o.Out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,6 +220,7 @@ func (o *ServiceOptions) Run() error {
|
|||||||
if o.FieldManager != "" {
|
if o.FieldManager != "" {
|
||||||
createOptions.FieldManager = o.FieldManager
|
createOptions.FieldManager = o.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = o.ValidationDirective
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
createOptions.DryRun = []string{metav1.DryRunAll}
|
createOptions.DryRun = []string{metav1.DryRunAll}
|
||||||
}
|
}
|
||||||
|
@ -51,11 +51,12 @@ type ServiceAccountOpts struct {
|
|||||||
PrintFlags *genericclioptions.PrintFlags
|
PrintFlags *genericclioptions.PrintFlags
|
||||||
PrintObj func(obj runtime.Object) error
|
PrintObj func(obj runtime.Object) error
|
||||||
// Name of resource being created
|
// Name of resource being created
|
||||||
Name string
|
Name string
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
CreateAnnotation bool
|
ValidationDirective string
|
||||||
FieldManager string
|
CreateAnnotation bool
|
||||||
|
FieldManager string
|
||||||
|
|
||||||
Namespace string
|
Namespace string
|
||||||
EnforceNamespace bool
|
EnforceNamespace bool
|
||||||
@ -146,6 +147,11 @@ func (o *ServiceAccountOpts) Complete(f cmdutil.Factory, cmd *cobra.Command, arg
|
|||||||
return printer.PrintObj(obj, o.Out)
|
return printer.PrintObj(obj, o.Out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -173,6 +179,7 @@ func (o *ServiceAccountOpts) Run() error {
|
|||||||
if o.FieldManager != "" {
|
if o.FieldManager != "" {
|
||||||
createOptions.FieldManager = o.FieldManager
|
createOptions.FieldManager = o.FieldManager
|
||||||
}
|
}
|
||||||
|
createOptions.FieldValidation = o.ValidationDirective
|
||||||
if o.DryRunStrategy == cmdutil.DryRunServer {
|
if o.DryRunStrategy == cmdutil.DryRunServer {
|
||||||
if err := o.DryRunVerifier.HasSupport(serviceAccount.GroupVersionKind()); err != nil {
|
if err := o.DryRunVerifier.HasSupport(serviceAccount.GroupVersionKind()); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -72,8 +72,6 @@ var (
|
|||||||
// NewCmdEdit creates the `edit` command
|
// NewCmdEdit creates the `edit` command
|
||||||
func NewCmdEdit(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
func NewCmdEdit(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
|
||||||
o := editor.NewEditOptions(editor.NormalEditMode, ioStreams)
|
o := editor.NewEditOptions(editor.NormalEditMode, ioStreams)
|
||||||
o.ValidateOptions = cmdutil.ValidateOptions{EnableValidation: true}
|
|
||||||
|
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "edit (RESOURCE/NAME | -f FILENAME)",
|
Use: "edit (RESOURCE/NAME | -f FILENAME)",
|
||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
@ -94,7 +92,7 @@ func NewCmdEdit(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra
|
|||||||
|
|
||||||
usage := "to use to edit the resource"
|
usage := "to use to edit the resource"
|
||||||
cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage)
|
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().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,
|
cmd.Flags().BoolVar(&o.WindowsLineEndings, "windows-line-endings", o.WindowsLineEndings,
|
||||||
"Defaults to the line ending native to your platform.")
|
"Defaults to the line ending native to your platform.")
|
||||||
|
@ -77,13 +77,14 @@ type ReplaceOptions struct {
|
|||||||
DeleteFlags *delete.DeleteFlags
|
DeleteFlags *delete.DeleteFlags
|
||||||
DeleteOptions *delete.DeleteOptions
|
DeleteOptions *delete.DeleteOptions
|
||||||
|
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
|
FieldValidationVerifier *resource.QueryParamVerifier
|
||||||
|
validationDirective string
|
||||||
|
|
||||||
PrintObj func(obj runtime.Object) error
|
PrintObj func(obj runtime.Object) error
|
||||||
|
|
||||||
createAnnotation bool
|
createAnnotation bool
|
||||||
validate bool
|
|
||||||
|
|
||||||
Schema validation.Schema
|
Schema validation.Schema
|
||||||
Builder func() *resource.Builder
|
Builder func() *resource.Builder
|
||||||
@ -151,7 +152,10 @@ func (o *ReplaceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
|||||||
return err
|
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.createAnnotation = cmdutil.GetFlagBool(cmd, cmdutil.ApplyAnnotationsFlag)
|
||||||
|
|
||||||
o.DryRunStrategy, err = cmdutil.GetDryRunStrategy(cmd)
|
o.DryRunStrategy, err = cmdutil.GetDryRunStrategy(cmd)
|
||||||
@ -163,6 +167,7 @@ func (o *ReplaceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
o.DryRunVerifier = resource.NewQueryParamVerifier(dynamicClient, f.OpenAPIGetter(), resource.QueryParamDryRun)
|
o.DryRunVerifier = resource.NewQueryParamVerifier(dynamicClient, f.OpenAPIGetter(), resource.QueryParamDryRun)
|
||||||
|
o.FieldValidationVerifier = resource.NewQueryParamVerifier(dynamicClient, f.OpenAPIGetter(), resource.QueryParamFieldValidation)
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
||||||
|
|
||||||
printer, err := o.PrintFlags.ToPrinter()
|
printer, err := o.PrintFlags.ToPrinter()
|
||||||
@ -196,7 +201,7 @@ func (o *ReplaceOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
schema, err := f.Validator(o.validate)
|
schema, err := f.Validator(o.validationDirective, o.FieldValidationVerifier)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -306,6 +311,7 @@ func (o *ReplaceOptions) Run(f cmdutil.Factory) error {
|
|||||||
NewHelper(info.Client, info.Mapping).
|
NewHelper(info.Client, info.Mapping).
|
||||||
DryRun(o.DryRunStrategy == cmdutil.DryRunServer).
|
DryRun(o.DryRunStrategy == cmdutil.DryRunServer).
|
||||||
WithFieldManager(o.fieldManager).
|
WithFieldManager(o.fieldManager).
|
||||||
|
WithFieldValidation(o.validationDirective).
|
||||||
WithSubresource(o.Subresource).
|
WithSubresource(o.Subresource).
|
||||||
Replace(info.Namespace, info.Name, true, info.Object)
|
Replace(info.Namespace, info.Name, true, info.Object)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -409,6 +415,7 @@ func (o *ReplaceOptions) forceReplace() error {
|
|||||||
|
|
||||||
obj, err := resource.NewHelper(info.Client, info.Mapping).
|
obj, err := resource.NewHelper(info.Client, info.Mapping).
|
||||||
WithFieldManager(o.fieldManager).
|
WithFieldManager(o.fieldManager).
|
||||||
|
WithFieldValidation(o.validationDirective).
|
||||||
Create(info.Namespace, true, info.Object)
|
Create(info.Namespace, true, info.Object)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -47,8 +47,9 @@ type TaintOptions struct {
|
|||||||
PrintFlags *genericclioptions.PrintFlags
|
PrintFlags *genericclioptions.PrintFlags
|
||||||
ToPrinter func(string) (printers.ResourcePrinter, error)
|
ToPrinter func(string) (printers.ResourcePrinter, error)
|
||||||
|
|
||||||
DryRunStrategy cmdutil.DryRunStrategy
|
DryRunStrategy cmdutil.DryRunStrategy
|
||||||
DryRunVerifier *resource.QueryParamVerifier
|
DryRunVerifier *resource.QueryParamVerifier
|
||||||
|
ValidationDirective string
|
||||||
|
|
||||||
resources []string
|
resources []string
|
||||||
taintsToAdd []v1.Taint
|
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)
|
o.DryRunVerifier = resource.NewQueryParamVerifier(dynamicClient, f.OpenAPIGetter(), resource.QueryParamDryRun)
|
||||||
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
cmdutil.PrintFlagsWithDryRunStrategy(o.PrintFlags, o.DryRunStrategy)
|
||||||
|
|
||||||
|
o.ValidationDirective, err = cmdutil.GetValidationDirective(cmd)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// retrieves resource and taint args from args
|
// retrieves resource and taint args from args
|
||||||
// also checks args to verify that all resources are specified before taints
|
// also checks args to verify that all resources are specified before taints
|
||||||
taintArgs := []string{}
|
taintArgs := []string{}
|
||||||
@ -337,8 +343,9 @@ func (o TaintOptions) RunTaint() error {
|
|||||||
}
|
}
|
||||||
helper := resource.
|
helper := resource.
|
||||||
NewHelper(client, mapping).
|
NewHelper(client, mapping).
|
||||||
|
DryRun(o.DryRunStrategy == cmdutil.DryRunServer).
|
||||||
WithFieldManager(o.fieldManager).
|
WithFieldManager(o.fieldManager).
|
||||||
DryRun(o.DryRunStrategy == cmdutil.DryRunServer)
|
WithFieldValidation(o.ValidationDirective)
|
||||||
|
|
||||||
var outputObj runtime.Object
|
var outputObj runtime.Object
|
||||||
if createdPatch {
|
if createdPatch {
|
||||||
|
@ -499,7 +499,7 @@ func (f *TestFactory) UnstructuredClientForMapping(mapping *meta.RESTMapping) (r
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validator returns a validation schema
|
// 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
|
return validation.NullSchema{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,6 +68,8 @@ type EditOptions struct {
|
|||||||
WindowsLineEndings bool
|
WindowsLineEndings bool
|
||||||
|
|
||||||
cmdutil.ValidateOptions
|
cmdutil.ValidateOptions
|
||||||
|
ValidationDirective string
|
||||||
|
FieldValidationVerifier *resource.QueryParamVerifier
|
||||||
|
|
||||||
OriginalResult *resource.Result
|
OriginalResult *resource.Result
|
||||||
|
|
||||||
@ -215,6 +217,17 @@ func (o *EditOptions) Complete(f cmdutil.Factory, args []string, cmd *cobra.Comm
|
|||||||
return o.PrintFlags.ToPrinter()
|
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.CmdNamespace = cmdNamespace
|
||||||
o.f = f
|
o.f = f
|
||||||
|
|
||||||
@ -309,7 +322,7 @@ func (o *EditOptions) Run() error {
|
|||||||
klog.V(4).Infof("User edited:\n%s", string(edited))
|
klog.V(4).Infof("User edited:\n%s", string(edited))
|
||||||
|
|
||||||
// Apply validation
|
// Apply validation
|
||||||
schema, err := o.f.Validator(o.EnableValidation)
|
schema, err := o.f.Validator(o.ValidationDirective, o.FieldValidationVerifier)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return preservedFile(err, file, o.ErrOut)
|
return preservedFile(err, file, o.ErrOut)
|
||||||
}
|
}
|
||||||
@ -571,7 +584,10 @@ func (o *EditOptions) annotationPatch(update *resource.Info) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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)
|
_, err = helper.Patch(o.CmdNamespace, update.Name, patchType, patch, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -709,7 +725,9 @@ func (o *EditOptions) visitToPatch(originalInfos []*resource.Info, patchVisitor
|
|||||||
}
|
}
|
||||||
|
|
||||||
patched, err := resource.NewHelper(info.Client, info.Mapping).
|
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)
|
Patch(info.Namespace, info.Name, patchType, patch, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Fprintln(o.ErrOut, results.addError(err, info))
|
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 {
|
err := createVisitor.Visit(func(info *resource.Info, incomingErr error) error {
|
||||||
obj, err := resource.NewHelper(info.Client, info.Mapping).
|
obj, err := resource.NewHelper(info.Client, info.Mapping).
|
||||||
WithFieldManager(o.FieldManager).
|
WithFieldManager(o.FieldManager).
|
||||||
|
WithFieldValidation(o.ValidationDirective).
|
||||||
Create(info.Namespace, true, info.Object)
|
Create(info.Namespace, true, info.Object)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
@ -61,7 +61,7 @@ type Factory interface {
|
|||||||
UnstructuredClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error)
|
UnstructuredClientForMapping(mapping *meta.RESTMapping) (resource.RESTClient, error)
|
||||||
|
|
||||||
// Returns a schema that can validate objects stored on disk.
|
// 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 returns the parsed openapi schema definition
|
||||||
OpenAPISchema() (openapi.Resources, error)
|
OpenAPISchema() (openapi.Resources, error)
|
||||||
// OpenAPIGetter returns a getter for the openapi schema document
|
// OpenAPIGetter returns a getter for the openapi schema document
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/api/meta"
|
"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/genericclioptions"
|
||||||
"k8s.io/cli-runtime/pkg/resource"
|
"k8s.io/cli-runtime/pkg/resource"
|
||||||
"k8s.io/client-go/discovery"
|
"k8s.io/client-go/discovery"
|
||||||
@ -141,8 +142,14 @@ func (f *factoryImpl) UnstructuredClientForMapping(mapping *meta.RESTMapping) (r
|
|||||||
return restclient.RESTClientFor(cfg)
|
return restclient.RESTClientFor(cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *factoryImpl) Validator(validate bool) (validation.Schema, error) {
|
func (f *factoryImpl) Validator(validationDirective string, verifier *resource.QueryParamVerifier) (validation.Schema, error) {
|
||||||
if !validate {
|
// 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
|
return validation.NullSchema{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -151,10 +158,11 @@ func (f *factoryImpl) Validator(validate bool) (validation.Schema, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return validation.ConjunctiveSchema{
|
schema := validation.ConjunctiveSchema{
|
||||||
openapivalidation.NewSchemaValidation(resources),
|
openapivalidation.NewSchemaValidation(resources),
|
||||||
validation.NoDoubleKeySchema{},
|
validation.NoDoubleKeySchema{},
|
||||||
}, nil
|
}
|
||||||
|
return validation.NewParamVerifyingSchema(schema, verifier, string(validationDirective)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenAPISchema returns metadata and structural information about
|
// OpenAPISchema returns metadata and structural information about
|
||||||
|
@ -399,11 +399,14 @@ func GetPodRunningTimeoutFlag(cmd *cobra.Command) (time.Duration, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func AddValidateFlags(cmd *cobra.Command) {
|
func AddValidateFlags(cmd *cobra.Command) {
|
||||||
cmd.Flags().Bool("validate", true, "If true, use a schema to validate the input before sending it")
|
cmd.Flags().String(
|
||||||
}
|
"validate",
|
||||||
|
"strict",
|
||||||
func AddValidateOptionFlags(cmd *cobra.Command, options *ValidateOptions) {
|
`Must be one of: strict (or true), warn, ignore (or false).
|
||||||
cmd.Flags().BoolVar(&options.EnableValidation, "validate", options.EnableValidation, "If true, use a schema to validate the input before sending it")
|
"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) {
|
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 {
|
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,
|
// 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")
|
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
|
type DryRunStrategy int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -17,6 +17,7 @@ limitations under the License.
|
|||||||
package util
|
package util
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
goerrors "errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
@ -27,6 +28,7 @@ import (
|
|||||||
|
|
||||||
"github.com/google/go-cmp/cmp"
|
"github.com/google/go-cmp/cmp"
|
||||||
"github.com/google/go-cmp/cmp/cmpopts"
|
"github.com/google/go-cmp/cmp/cmpopts"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
corev1 "k8s.io/api/core/v1"
|
corev1 "k8s.io/api/core/v1"
|
||||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
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
|
// ValidateBytes will validates the object against using the Resources
|
||||||
// object.
|
// object.
|
||||||
func (v *SchemaValidation) ValidateBytes(data []byte) error {
|
func (v *SchemaValidation) ValidateBytes(data []byte) error {
|
||||||
obj, err := parse(data)
|
obj, err := Parse(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
gvk, errs := getObjectKind(obj)
|
gvk, errs := GetObjectKind(obj)
|
||||||
if errs != nil {
|
if errs != nil {
|
||||||
return utilerrors.NewAggregate(errs)
|
return utilerrors.NewAggregate(errs)
|
||||||
}
|
}
|
||||||
@ -71,7 +71,7 @@ func (v *SchemaValidation) validateList(object interface{}) []error {
|
|||||||
return []error{errors.New("invalid object to validate")}
|
return []error{errors.New("invalid object to validate")}
|
||||||
}
|
}
|
||||||
for _, item := range fields["items"].([]interface{}) {
|
for _, item := range fields["items"].([]interface{}) {
|
||||||
if gvk, errs := getObjectKind(item); errs != nil {
|
if gvk, errs := GetObjectKind(item); errs != nil {
|
||||||
allErrors = append(allErrors, errs...)
|
allErrors = append(allErrors, errs...)
|
||||||
} else {
|
} else {
|
||||||
allErrors = append(allErrors, v.validateResource(item, gvk)...)
|
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)
|
return validation.ValidateModel(obj, resource, gvk.Kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
func parse(data []byte) (interface{}, error) {
|
func Parse(data []byte) (interface{}, error) {
|
||||||
var obj interface{}
|
var obj interface{}
|
||||||
out, err := yaml.ToJSON(data)
|
out, err := yaml.ToJSON(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -102,7 +102,7 @@ func parse(data []byte) (interface{}, error) {
|
|||||||
return obj, nil
|
return obj, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getObjectKind(object interface{}) (schema.GroupVersionKind, []error) {
|
func GetObjectKind(object interface{}) (schema.GroupVersionKind, []error) {
|
||||||
var listErrors []error
|
var listErrors []error
|
||||||
fields, ok := object.(map[string]interface{})
|
fields, ok := object.(map[string]interface{})
|
||||||
if !ok || fields == nil {
|
if !ok || fields == nil {
|
||||||
|
@ -22,7 +22,11 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
ejson "github.com/exponent-io/jsonpath"
|
ejson "github.com/exponent-io/jsonpath"
|
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
utilerrors "k8s.io/apimachinery/pkg/util/errors"
|
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.
|
// 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)
|
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 (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
|
"k8s.io/cli-runtime/pkg/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestValidateDuplicateLabelsFailCases(t *testing.T) {
|
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 nounset
|
||||||
set +o errexit
|
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
|
fi
|
||||||
if kube::test::if_supports_resource "${deployments}"; then
|
if kube::test::if_supports_resource "${deployments}"; then
|
||||||
record_command run_kubectl_create_kustomization_directory_tests
|
record_command run_kubectl_create_kustomization_directory_tests
|
||||||
|
record_command run_kubectl_create_validate_tests
|
||||||
fi
|
fi
|
||||||
|
|
||||||
######################
|
######################
|
||||||
|
Loading…
Reference in New Issue
Block a user