mirror of
https://github.com/kubernetes/kubernetes.git
synced 2026-06-09 08:55:55 -04:00
manual change
This commit is contained in:
parent
4f3334b7ce
commit
a3ecea296c
19 changed files with 1220 additions and 370 deletions
|
|
@ -171,6 +171,10 @@ func TestDefaulting(t *testing.T) {
|
|||
{Group: "admissionregistration.k8s.io", Version: "v1beta1", Kind: "ValidatingAdmissionPolicyList"}: {},
|
||||
{Group: "admissionregistration.k8s.io", Version: "v1beta1", Kind: "ValidatingAdmissionPolicyBinding"}: {},
|
||||
{Group: "admissionregistration.k8s.io", Version: "v1beta1", Kind: "ValidatingAdmissionPolicyBindingList"}: {},
|
||||
{Group: "admissionregistration.k8s.io", Version: "v1beta1", Kind: "MutatingAdmissionPolicy"}: {},
|
||||
{Group: "admissionregistration.k8s.io", Version: "v1beta1", Kind: "MutatingAdmissionPolicyList"}: {},
|
||||
{Group: "admissionregistration.k8s.io", Version: "v1beta1", Kind: "MutatingAdmissionPolicyBinding"}: {},
|
||||
{Group: "admissionregistration.k8s.io", Version: "v1beta1", Kind: "MutatingAdmissionPolicyBindingList"}: {},
|
||||
{Group: "admissionregistration.k8s.io", Version: "v1", Kind: "ValidatingAdmissionPolicy"}: {},
|
||||
{Group: "admissionregistration.k8s.io", Version: "v1", Kind: "ValidatingAdmissionPolicyList"}: {},
|
||||
{Group: "admissionregistration.k8s.io", Version: "v1", Kind: "ValidatingAdmissionPolicyBinding"}: {},
|
||||
|
|
|
|||
|
|
@ -127,3 +127,11 @@ func SetDefaults_ServiceReference(obj *admissionregistrationv1beta1.ServiceRefer
|
|||
obj.Port = ptr.To[int32](443)
|
||||
}
|
||||
}
|
||||
|
||||
// SetDefaults_MutatingAdmissionPolicySpec sets defaults for MutatingAdmissionPolicySpec
|
||||
func SetDefaults_MutatingAdmissionPolicySpec(obj *admissionregistrationv1beta1.MutatingAdmissionPolicySpec) {
|
||||
if obj.FailurePolicy == nil {
|
||||
policy := admissionregistrationv1beta1.Fail
|
||||
obj.FailurePolicy = &policy
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ func TestDefaultAdmissionWebhook(t *testing.T) {
|
|||
|
||||
func TestDefaultAdmissionPolicy(t *testing.T) {
|
||||
fail := v1beta1.Fail
|
||||
never := v1beta1.NeverReinvocationPolicy
|
||||
equivalent := v1beta1.Equivalent
|
||||
allScopes := v1beta1.AllScopes
|
||||
|
||||
|
|
@ -216,6 +217,42 @@ func TestDefaultAdmissionPolicy(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "MutatingAdmissionPolicy",
|
||||
original: &v1beta1.MutatingAdmissionPolicy{
|
||||
Spec: v1beta1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &v1beta1.MatchResources{},
|
||||
ReinvocationPolicy: never,
|
||||
Mutations: []v1beta1.Mutation{
|
||||
{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: "fake string",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
expected: &v1beta1.MutatingAdmissionPolicy{
|
||||
Spec: v1beta1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &v1beta1.MatchResources{
|
||||
MatchPolicy: &equivalent,
|
||||
NamespaceSelector: &metav1.LabelSelector{},
|
||||
ObjectSelector: &metav1.LabelSelector{},
|
||||
},
|
||||
FailurePolicy: &fail,
|
||||
ReinvocationPolicy: never,
|
||||
Mutations: []v1beta1.Mutation{
|
||||
{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: "fake string",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
|
|
|||
|
|
@ -81,8 +81,8 @@ func NewStorageFactoryConfigEffectiveVersion(effectiveVersion basecompatibility.
|
|||
// TODO (https://github.com/kubernetes/kubernetes/issues/108451): remove the override in 1.25.
|
||||
// apisstorage.Resource("csistoragecapacities").WithVersion("v1beta1"),
|
||||
coordination.Resource("leasecandidates").WithVersion("v1beta1"),
|
||||
admissionregistration.Resource("mutatingadmissionpolicies").WithVersion("v1alpha1"),
|
||||
admissionregistration.Resource("mutatingadmissionpolicybindings").WithVersion("v1alpha1"),
|
||||
admissionregistration.Resource("mutatingadmissionpolicies").WithVersion("v1beta1"),
|
||||
admissionregistration.Resource("mutatingadmissionpolicybindings").WithVersion("v1beta1"),
|
||||
certificates.Resource("clustertrustbundles").WithVersion("v1beta1"),
|
||||
storage.Resource("volumeattributesclasses").WithVersion("v1beta1"),
|
||||
storagemigration.Resource("storagemigrations").WithVersion("v1alpha1"),
|
||||
|
|
|
|||
|
|
@ -183,6 +183,25 @@ func (p RESTStorageProvider) v1beta1Storage(apiResourceConfigSource serverstorag
|
|||
storage[resource] = policyBindingStorage
|
||||
}
|
||||
|
||||
// mutatingadmissionpolicies
|
||||
if resource := "mutatingadmissionpolicies"; apiResourceConfigSource.ResourceEnabled(admissionregistrationv1beta1.SchemeGroupVersion.WithResource(resource)) {
|
||||
policyStorage, err := mutatingadmissionpolicystorage.NewREST(restOptionsGetter, p.Authorizer, r)
|
||||
if err != nil {
|
||||
return storage, err
|
||||
}
|
||||
policyGetter = policyStorage
|
||||
storage[resource] = policyStorage
|
||||
}
|
||||
|
||||
// mutatingadmissionpolicybindings
|
||||
if resource := "mutatingadmissionpolicybindings"; apiResourceConfigSource.ResourceEnabled(admissionregistrationv1beta1.SchemeGroupVersion.WithResource(resource)) {
|
||||
mutationpolicybindingstorage, err := mutationpolicybindingstorage.NewREST(restOptionsGetter, p.Authorizer, &mutationpolicybindingstorage.DefaultPolicyGetter{Getter: policyGetter}, r)
|
||||
if err != nil {
|
||||
return storage, err
|
||||
}
|
||||
storage[resource] = mutationpolicybindingstorage
|
||||
}
|
||||
|
||||
return storage, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,6 +54,10 @@ func addKnownTypes(scheme *runtime.Scheme) error {
|
|||
&ValidatingAdmissionPolicyList{},
|
||||
&ValidatingAdmissionPolicyBinding{},
|
||||
&ValidatingAdmissionPolicyBindingList{},
|
||||
&MutatingAdmissionPolicy{},
|
||||
&MutatingAdmissionPolicyList{},
|
||||
&MutatingAdmissionPolicyBinding{},
|
||||
&MutatingAdmissionPolicyBindingList{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
|
|
|
|||
|
|
@ -1073,7 +1073,7 @@ type MutatingWebhook struct {
|
|||
}
|
||||
|
||||
// ReinvocationPolicyType specifies what type of policy the admission hook uses.
|
||||
type ReinvocationPolicyType string
|
||||
type ReinvocationPolicyType = v1.ReinvocationPolicyType
|
||||
|
||||
const (
|
||||
// NeverReinvocationPolicy indicates that the webhook must not be called more than once in a
|
||||
|
|
@ -1197,3 +1197,332 @@ type MatchCondition struct {
|
|||
// Required.
|
||||
Expression string `json:"expression" protobuf:"bytes,2,opt,name=expression"`
|
||||
}
|
||||
|
||||
// +genclient
|
||||
// +genclient:nonNamespaced
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +k8s:prerelease-lifecycle-gen:introduced=1.34
|
||||
|
||||
// MutatingAdmissionPolicy describes the definition of an admission mutation policy that mutates the object coming into admission chain.
|
||||
type MutatingAdmissionPolicy struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata.
|
||||
// +optional
|
||||
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
// Specification of the desired behavior of the MutatingAdmissionPolicy.
|
||||
Spec MutatingAdmissionPolicySpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +k8s:prerelease-lifecycle-gen:introduced=1.34
|
||||
|
||||
// MutatingAdmissionPolicyList is a list of MutatingAdmissionPolicy.
|
||||
type MutatingAdmissionPolicyList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard list metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
// +optional
|
||||
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
// List of ValidatingAdmissionPolicy.
|
||||
Items []MutatingAdmissionPolicy `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
||||
|
||||
// MutatingAdmissionPolicySpec is the specification of the desired behavior of the admission policy.
|
||||
type MutatingAdmissionPolicySpec struct {
|
||||
// paramKind specifies the kind of resources used to parameterize this policy.
|
||||
// If absent, there are no parameters for this policy and the param CEL variable will not be provided to validation expressions.
|
||||
// If paramKind refers to a non-existent kind, this policy definition is mis-configured and the FailurePolicy is applied.
|
||||
// If paramKind is specified but paramRef is unset in MutatingAdmissionPolicyBinding, the params variable will be null.
|
||||
// +optional
|
||||
ParamKind *ParamKind `json:"paramKind,omitempty" protobuf:"bytes,1,rep,name=paramKind"`
|
||||
|
||||
// matchConstraints specifies what resources this policy is designed to validate.
|
||||
// The MutatingAdmissionPolicy cares about a request if it matches _all_ Constraints.
|
||||
// However, in order to prevent clusters from being put into an unstable state that cannot be recovered from via the API
|
||||
// MutatingAdmissionPolicy cannot match MutatingAdmissionPolicy and MutatingAdmissionPolicyBinding.
|
||||
// The CREATE, UPDATE and CONNECT operations are allowed. The DELETE operation may not be matched.
|
||||
// '*' matches CREATE, UPDATE and CONNECT.
|
||||
// Required.
|
||||
MatchConstraints *MatchResources `json:"matchConstraints,omitempty" protobuf:"bytes,2,rep,name=matchConstraints"`
|
||||
|
||||
// variables contain definitions of variables that can be used in composition of other expressions.
|
||||
// Each variable is defined as a named CEL expression.
|
||||
// The variables defined here will be available under `variables` in other expressions of the policy
|
||||
// except matchConditions because matchConditions are evaluated before the rest of the policy.
|
||||
//
|
||||
// The expression of a variable can refer to other variables defined earlier in the list but not those after.
|
||||
// Thus, variables must be sorted by the order of first appearance and acyclic.
|
||||
// +listType=atomic
|
||||
// +optional
|
||||
Variables []Variable `json:"variables,omitempty" protobuf:"bytes,3,rep,name=variables"`
|
||||
|
||||
// mutations contain operations to perform on matching objects.
|
||||
// mutations may not be empty; a minimum of one mutation is required.
|
||||
// mutations are evaluated in order, and are reinvoked according to
|
||||
// the reinvocationPolicy.
|
||||
// The mutations of a policy are invoked for each binding of this policy
|
||||
// and reinvocation of mutations occurs on a per binding basis.
|
||||
//
|
||||
// +listType=atomic
|
||||
// +optional
|
||||
Mutations []Mutation `json:"mutations,omitempty" protobuf:"bytes,4,rep,name=mutations"`
|
||||
|
||||
// failurePolicy defines how to handle failures for the admission policy. Failures can
|
||||
// occur from CEL expression parse errors, type check errors, runtime errors and invalid
|
||||
// or mis-configured policy definitions or bindings.
|
||||
//
|
||||
// A policy is invalid if paramKind refers to a non-existent Kind.
|
||||
// A binding is invalid if paramRef.name refers to a non-existent resource.
|
||||
//
|
||||
// failurePolicy does not define how validations that evaluate to false are handled.
|
||||
//
|
||||
// Allowed values are Ignore or Fail. Defaults to Fail.
|
||||
// +optional
|
||||
FailurePolicy *FailurePolicyType `json:"failurePolicy,omitempty" protobuf:"bytes,5,opt,name=failurePolicy,casttype=FailurePolicyType"`
|
||||
|
||||
// matchConditions is a list of conditions that must be met for a request to be validated.
|
||||
// Match conditions filter requests that have already been matched by the matchConstraints.
|
||||
// An empty list of matchConditions matches all requests.
|
||||
// There are a maximum of 64 match conditions allowed.
|
||||
//
|
||||
// If a parameter object is provided, it can be accessed via the `params` handle in the same
|
||||
// manner as validation expressions.
|
||||
//
|
||||
// The exact matching logic is (in order):
|
||||
// 1. If ANY matchCondition evaluates to FALSE, the policy is skipped.
|
||||
// 2. If ALL matchConditions evaluate to TRUE, the policy is evaluated.
|
||||
// 3. If any matchCondition evaluates to an error (but none are FALSE):
|
||||
// - If failurePolicy=Fail, reject the request
|
||||
// - If failurePolicy=Ignore, the policy is skipped
|
||||
//
|
||||
// +patchMergeKey=name
|
||||
// +patchStrategy=merge
|
||||
// +listType=map
|
||||
// +listMapKey=name
|
||||
// +optional
|
||||
MatchConditions []MatchCondition `json:"matchConditions,omitempty" patchStrategy:"merge" patchMergeKey:"name" protobuf:"bytes,6,rep,name=matchConditions"`
|
||||
|
||||
// reinvocationPolicy indicates whether mutations may be called multiple times per MutatingAdmissionPolicyBinding
|
||||
// as part of a single admission evaluation.
|
||||
// Allowed values are "Never" and "IfNeeded".
|
||||
//
|
||||
// Never: These mutations will not be called more than once per binding in a single admission evaluation.
|
||||
//
|
||||
// IfNeeded: These mutations may be invoked more than once per binding for a single admission request and there is no guarantee of
|
||||
// order with respect to other admission plugins, admission webhooks, bindings of this policy and admission policies. Mutations are only
|
||||
// reinvoked when mutations change the object after this mutation is invoked.
|
||||
// Required.
|
||||
ReinvocationPolicy ReinvocationPolicyType `json:"reinvocationPolicy,omitempty" protobuf:"bytes,7,opt,name=reinvocationPolicy,casttype=ReinvocationPolicyType"`
|
||||
}
|
||||
|
||||
// Mutation specifies the CEL expression which is used to apply the Mutation.
|
||||
type Mutation struct {
|
||||
// patchType indicates the patch strategy used.
|
||||
// Allowed values are "ApplyConfiguration" and "JSONPatch".
|
||||
// Required.
|
||||
//
|
||||
// +unionDiscriminator
|
||||
PatchType PatchType `json:"patchType" protobuf:"bytes,2,opt,name=patchType,casttype=PatchType"`
|
||||
|
||||
// applyConfiguration defines the desired configuration values of an object.
|
||||
// The configuration is applied to the admission object using
|
||||
// [structured merge diff](https://github.com/kubernetes-sigs/structured-merge-diff).
|
||||
// A CEL expression is used to create apply configuration.
|
||||
ApplyConfiguration *ApplyConfiguration `json:"applyConfiguration,omitempty" protobuf:"bytes,3,opt,name=applyConfiguration"`
|
||||
|
||||
// jsonPatch defines a [JSON patch](https://jsonpatch.com/) operation to perform a mutation to the object.
|
||||
// A CEL expression is used to create the JSON patch.
|
||||
JSONPatch *JSONPatch `json:"jsonPatch,omitempty" protobuf:"bytes,4,opt,name=jsonPatch"`
|
||||
}
|
||||
|
||||
// PatchType specifies the type of patch operation for a mutation.
|
||||
// +enum
|
||||
type PatchType string
|
||||
|
||||
const (
|
||||
// ApplyConfiguration indicates that the mutation is using apply configuration to mutate the object.
|
||||
PatchTypeApplyConfiguration PatchType = "ApplyConfiguration"
|
||||
// JSONPatch indicates that the object is mutated through JSON Patch.
|
||||
PatchTypeJSONPatch PatchType = "JSONPatch"
|
||||
)
|
||||
|
||||
// ApplyConfiguration defines the desired configuration values of an object.
|
||||
type ApplyConfiguration struct {
|
||||
// expression will be evaluated by CEL to create an apply configuration.
|
||||
// ref: https://github.com/google/cel-spec
|
||||
//
|
||||
// Apply configurations are declared in CEL using object initialization. For example, this CEL expression
|
||||
// returns an apply configuration to set a single field:
|
||||
//
|
||||
// Object{
|
||||
// spec: Object.spec{
|
||||
// serviceAccountName: "example"
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Apply configurations may not modify atomic structs, maps or arrays due to the risk of accidental deletion of
|
||||
// values not included in the apply configuration.
|
||||
//
|
||||
// CEL expressions have access to the object types needed to create apply configurations:
|
||||
//
|
||||
// - 'Object' - CEL type of the resource object.
|
||||
// - 'Object.<fieldName>' - CEL type of object field (such as 'Object.spec')
|
||||
// - 'Object.<fieldName1>.<fieldName2>...<fieldNameN>` - CEL type of nested field (such as 'Object.spec.containers')
|
||||
//
|
||||
// CEL expressions have access to the contents of the API request, organized into CEL variables as well as some other useful variables:
|
||||
//
|
||||
// - 'object' - The object from the incoming request. The value is null for DELETE requests.
|
||||
// - 'oldObject' - The existing object. The value is null for CREATE requests.
|
||||
// - 'request' - Attributes of the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).
|
||||
// - 'params' - Parameter resource referred to by the policy binding being evaluated. Only populated if the policy has a ParamKind.
|
||||
// - 'namespaceObject' - The namespace object that the incoming object belongs to. The value is null for cluster-scoped resources.
|
||||
// - 'variables' - Map of composited variables, from its name to its lazily evaluated value.
|
||||
// For example, a variable named 'foo' can be accessed as 'variables.foo'.
|
||||
// - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request.
|
||||
// See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz
|
||||
// - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the
|
||||
// request resource.
|
||||
//
|
||||
// The `apiVersion`, `kind`, `metadata.name` and `metadata.generateName` are always accessible from the root of the
|
||||
// object. No other metadata properties are accessible.
|
||||
//
|
||||
// Only property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` are accessible.
|
||||
// Required.
|
||||
Expression string `json:"expression,omitempty" protobuf:"bytes,1,opt,name=expression"`
|
||||
}
|
||||
|
||||
// JSONPatch defines a JSON Patch.
|
||||
type JSONPatch struct {
|
||||
// expression will be evaluated by CEL to create a [JSON patch](https://jsonpatch.com/).
|
||||
// ref: https://github.com/google/cel-spec
|
||||
//
|
||||
// expression must return an array of JSONPatch values.
|
||||
//
|
||||
// For example, this CEL expression returns a JSON patch to conditionally modify a value:
|
||||
//
|
||||
// [
|
||||
// JSONPatch{op: "test", path: "/spec/example", value: "Red"},
|
||||
// JSONPatch{op: "replace", path: "/spec/example", value: "Green"}
|
||||
// ]
|
||||
//
|
||||
// To define an object for the patch value, use Object types. For example:
|
||||
//
|
||||
// [
|
||||
// JSONPatch{
|
||||
// op: "add",
|
||||
// path: "/spec/selector",
|
||||
// value: Object.spec.selector{matchLabels: {"environment": "test"}}
|
||||
// }
|
||||
// ]
|
||||
//
|
||||
// To use strings containing '/' and '~' as JSONPatch path keys, use "jsonpatch.escapeKey". For example:
|
||||
//
|
||||
// [
|
||||
// JSONPatch{
|
||||
// op: "add",
|
||||
// path: "/metadata/labels/" + jsonpatch.escapeKey("example.com/environment"),
|
||||
// value: "test"
|
||||
// },
|
||||
// ]
|
||||
//
|
||||
// CEL expressions have access to the types needed to create JSON patches and objects:
|
||||
//
|
||||
// - 'JSONPatch' - CEL type of JSON Patch operations. JSONPatch has the fields 'op', 'from', 'path' and 'value'.
|
||||
// See [JSON patch](https://jsonpatch.com/) for more details. The 'value' field may be set to any of: string,
|
||||
// integer, array, map or object. If set, the 'path' and 'from' fields must be set to a
|
||||
// [JSON pointer](https://datatracker.ietf.org/doc/html/rfc6901/) string, where the 'jsonpatch.escapeKey()' CEL
|
||||
// function may be used to escape path keys containing '/' and '~'.
|
||||
// - 'Object' - CEL type of the resource object.
|
||||
// - 'Object.<fieldName>' - CEL type of object field (such as 'Object.spec')
|
||||
// - 'Object.<fieldName1>.<fieldName2>...<fieldNameN>` - CEL type of nested field (such as 'Object.spec.containers')
|
||||
//
|
||||
// CEL expressions have access to the contents of the API request, organized into CEL variables as well as some other useful variables:
|
||||
//
|
||||
// - 'object' - The object from the incoming request. The value is null for DELETE requests.
|
||||
// - 'oldObject' - The existing object. The value is null for CREATE requests.
|
||||
// - 'request' - Attributes of the API request([ref](/pkg/apis/admission/types.go#AdmissionRequest)).
|
||||
// - 'params' - Parameter resource referred to by the policy binding being evaluated. Only populated if the policy has a ParamKind.
|
||||
// - 'namespaceObject' - The namespace object that the incoming object belongs to. The value is null for cluster-scoped resources.
|
||||
// - 'variables' - Map of composited variables, from its name to its lazily evaluated value.
|
||||
// For example, a variable named 'foo' can be accessed as 'variables.foo'.
|
||||
// - 'authorizer' - A CEL Authorizer. May be used to perform authorization checks for the principal (user or service account) of the request.
|
||||
// See https://pkg.go.dev/k8s.io/apiserver/pkg/cel/library#Authz
|
||||
// - 'authorizer.requestResource' - A CEL ResourceCheck constructed from the 'authorizer' and configured with the
|
||||
// request resource.
|
||||
//
|
||||
// CEL expressions have access to [Kubernetes CEL function libraries](https://kubernetes.io/docs/reference/using-api/cel/#cel-options-language-features-and-libraries)
|
||||
// as well as:
|
||||
//
|
||||
// - 'jsonpatch.escapeKey' - Performs JSONPatch key escaping. '~' and '/' are escaped as '~0' and `~1' respectively).
|
||||
//
|
||||
//
|
||||
// Only property names of the form `[a-zA-Z_.-/][a-zA-Z0-9_.-/]*` are accessible.
|
||||
// Required.
|
||||
Expression string `json:"expression,omitempty" protobuf:"bytes,1,opt,name=expression"`
|
||||
}
|
||||
|
||||
// +genclient
|
||||
// +genclient:nonNamespaced
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +k8s:prerelease-lifecycle-gen:introduced=1.34
|
||||
|
||||
// MutatingAdmissionPolicyBinding binds the MutatingAdmissionPolicy with parametrized resources.
|
||||
// MutatingAdmissionPolicyBinding and the optional parameter resource together define how cluster administrators
|
||||
// configure policies for clusters.
|
||||
//
|
||||
// For a given admission request, each binding will cause its policy to be
|
||||
// evaluated N times, where N is 1 for policies/bindings that don't use
|
||||
// params, otherwise N is the number of parameters selected by the binding.
|
||||
// Each evaluation is constrained by a [runtime cost budget](https://kubernetes.io/docs/reference/using-api/cel/#runtime-cost-budget).
|
||||
//
|
||||
// Adding/removing policies, bindings, or params can not affect whether a
|
||||
// given (policy, binding, param) combination is within its own CEL budget.
|
||||
type MutatingAdmissionPolicyBinding struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object metadata; More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata.
|
||||
// +optional
|
||||
metav1.ObjectMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
// Specification of the desired behavior of the MutatingAdmissionPolicyBinding.
|
||||
Spec MutatingAdmissionPolicyBindingSpec `json:"spec,omitempty" protobuf:"bytes,2,opt,name=spec"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +k8s:prerelease-lifecycle-gen:introduced=1.34
|
||||
|
||||
// MutatingAdmissionPolicyBindingList is a list of MutatingAdmissionPolicyBinding.
|
||||
type MutatingAdmissionPolicyBindingList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard list metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
|
||||
// +optional
|
||||
metav1.ListMeta `json:"metadata,omitempty" protobuf:"bytes,1,opt,name=metadata"`
|
||||
// List of PolicyBinding.
|
||||
Items []MutatingAdmissionPolicyBinding `json:"items" protobuf:"bytes,2,rep,name=items"`
|
||||
}
|
||||
|
||||
// MutatingAdmissionPolicyBindingSpec is the specification of the MutatingAdmissionPolicyBinding.
|
||||
type MutatingAdmissionPolicyBindingSpec struct {
|
||||
// policyName references a MutatingAdmissionPolicy name which the MutatingAdmissionPolicyBinding binds to.
|
||||
// If the referenced resource does not exist, this binding is considered invalid and will be ignored
|
||||
// Required.
|
||||
PolicyName string `json:"policyName,omitempty" protobuf:"bytes,1,rep,name=policyName"`
|
||||
|
||||
// paramRef specifies the parameter resource used to configure the admission control policy.
|
||||
// It should point to a resource of the type specified in spec.ParamKind of the bound MutatingAdmissionPolicy.
|
||||
// If the policy specifies a ParamKind and the resource referred to by ParamRef does not exist, this binding is considered mis-configured and the FailurePolicy of the MutatingAdmissionPolicy applied.
|
||||
// If the policy does not specify a ParamKind then this field is ignored, and the rules are evaluated without a param.
|
||||
// +optional
|
||||
ParamRef *ParamRef `json:"paramRef,omitempty" protobuf:"bytes,2,rep,name=paramRef"`
|
||||
|
||||
// matchResources limits what resources match this binding and may be mutated by it.
|
||||
// Note that if matchResources matches a resource, the resource must also match a policy's matchConstraints and
|
||||
// matchConditions before the resource may be mutated.
|
||||
// When matchResources is unset, it does not constrain resource matching, and only the policy's matchConstraints
|
||||
// and matchConditions must match for the resource to be mutated.
|
||||
// Additionally, matchResources.resourceRules are optional and do not constraint matching when unset.
|
||||
// Note that this is differs from MutatingAdmissionPolicy matchConstraints, where resourceRules are required.
|
||||
// The CREATE, UPDATE and CONNECT operations are allowed. The DELETE operation may not be matched.
|
||||
// '*' matches CREATE, UPDATE and CONNECT.
|
||||
// +optional
|
||||
MatchResources *MatchResources `json:"matchResources,omitempty" protobuf:"bytes,3,rep,name=matchResources"`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ package mutating
|
|||
|
||||
import (
|
||||
v1 "k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/api/admissionregistration/v1alpha1"
|
||||
"k8s.io/api/admissionregistration/v1beta1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/policy/generic"
|
||||
)
|
||||
|
|
@ -66,7 +66,7 @@ func (v *mutatingAdmissionPolicyAccessor) GetFailurePolicy() *v1.FailurePolicyTy
|
|||
return toV1FailurePolicy(v.Spec.FailurePolicy)
|
||||
}
|
||||
|
||||
func toV1FailurePolicy(failurePolicy *v1alpha1.FailurePolicyType) *v1.FailurePolicyType {
|
||||
func toV1FailurePolicy(failurePolicy *v1beta1.FailurePolicyType) *v1.FailurePolicyType {
|
||||
if failurePolicy == nil {
|
||||
return nil
|
||||
}
|
||||
|
|
@ -116,7 +116,7 @@ func (v *mutatingAdmissionPolicyBindingAccessor) GetParamRef() *v1.ParamRef {
|
|||
}
|
||||
}
|
||||
|
||||
func convertV1alpha1ResourceRulesToV1(mc *v1alpha1.MatchResources) *v1.MatchResources {
|
||||
func convertV1alpha1ResourceRulesToV1(mc *v1beta1.MatchResources) *v1.MatchResources {
|
||||
if mc == nil {
|
||||
return nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ package mutating
|
|||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/api/admissionregistration/v1alpha1"
|
||||
"k8s.io/api/admissionregistration/v1beta1"
|
||||
plugincel "k8s.io/apiserver/pkg/admission/plugin/cel"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/policy/mutating/patch"
|
||||
"k8s.io/apiserver/pkg/admission/plugin/webhook/matchconditions"
|
||||
|
|
@ -62,13 +62,13 @@ func compilePolicy(policy *Policy) PolicyEvaluator {
|
|||
patchOptions.HasPatchTypes = true
|
||||
for _, m := range policy.Spec.Mutations {
|
||||
switch m.PatchType {
|
||||
case v1alpha1.PatchTypeJSONPatch:
|
||||
case v1beta1.PatchTypeJSONPatch:
|
||||
if m.JSONPatch != nil {
|
||||
accessor := &patch.JSONPatchCondition{Expression: m.JSONPatch.Expression}
|
||||
compileResult := compiler.CompileMutatingEvaluator(accessor, patchOptions, environment.StoredExpressions)
|
||||
patchers = append(patchers, patch.NewJSONPatcher(compileResult))
|
||||
}
|
||||
case v1alpha1.PatchTypeApplyConfiguration:
|
||||
case v1beta1.PatchTypeApplyConfiguration:
|
||||
if m.ApplyConfiguration != nil {
|
||||
accessor := &patch.ApplyConfigurationCondition{Expression: m.ApplyConfiguration.Expression}
|
||||
compileResult := compiler.CompileMutatingEvaluator(accessor, patchOptions, environment.StoredExpressions)
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/admissionregistration/v1alpha1"
|
||||
"k8s.io/api/admissionregistration/v1beta1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/equality"
|
||||
|
|
@ -60,9 +60,9 @@ func TestCompilation(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
name: "applyConfiguration then jsonPatch",
|
||||
policy: mutations(policy("d1"), v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
policy: mutations(policy("d1"), v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{
|
||||
spec: Object.spec{
|
||||
replicas: object.spec.replicas + 100
|
||||
|
|
@ -70,9 +70,9 @@ func TestCompilation(t *testing.T) {
|
|||
}`,
|
||||
},
|
||||
},
|
||||
v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeJSONPatch,
|
||||
JSONPatch: &v1alpha1.JSONPatch{
|
||||
v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeJSONPatch,
|
||||
JSONPatch: &v1beta1.JSONPatch{
|
||||
Expression: `[
|
||||
JSONPatch{op: "replace", path: "/spec/replicas", value: object.spec.replicas + 10}
|
||||
]`,
|
||||
|
|
@ -85,17 +85,17 @@ func TestCompilation(t *testing.T) {
|
|||
{
|
||||
name: "jsonPatch then applyConfiguration",
|
||||
policy: mutations(policy("d1"),
|
||||
v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeJSONPatch,
|
||||
JSONPatch: &v1alpha1.JSONPatch{
|
||||
v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeJSONPatch,
|
||||
JSONPatch: &v1beta1.JSONPatch{
|
||||
Expression: `[
|
||||
JSONPatch{op: "replace", path: "/spec/replicas", value: object.spec.replicas + 10}
|
||||
]`,
|
||||
},
|
||||
},
|
||||
v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{
|
||||
spec: Object.spec{
|
||||
replicas: object.spec.replicas + 100
|
||||
|
|
@ -109,7 +109,7 @@ func TestCompilation(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "jsonPatch with variable",
|
||||
policy: jsonPatches(variables(policy("d1"), v1alpha1.Variable{Name: "desired", Expression: "10"}), v1alpha1.JSONPatch{
|
||||
policy: jsonPatches(variables(policy("d1"), v1beta1.Variable{Name: "desired", Expression: "10"}), v1beta1.JSONPatch{
|
||||
Expression: `[
|
||||
JSONPatch{op: "replace", path: "/spec/replicas", value: variables.desired + 1},
|
||||
]`,
|
||||
|
|
@ -120,7 +120,7 @@ func TestCompilation(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "apply configuration with variable",
|
||||
policy: applyConfigurations(variables(policy("d1"), v1alpha1.Variable{Name: "desired", Expression: "10"}),
|
||||
policy: applyConfigurations(variables(policy("d1"), v1beta1.Variable{Name: "desired", Expression: "10"}),
|
||||
`Object{
|
||||
spec: Object.spec{
|
||||
replicas: variables.desired + 1
|
||||
|
|
@ -137,7 +137,7 @@ func TestCompilation(t *testing.T) {
|
|||
spec: Object.spec{
|
||||
replicas: int(params.data['k1'])
|
||||
}
|
||||
}`), &v1alpha1.ParamKind{Kind: "ConfigMap", APIVersion: "v1"}),
|
||||
}`), &v1beta1.ParamKind{Kind: "ConfigMap", APIVersion: "v1"}),
|
||||
params: &corev1.ConfigMap{Data: map[string]string{"k1": "100"}},
|
||||
gvr: deploymentGVR,
|
||||
object: &appsv1.Deployment{Spec: appsv1.DeploymentSpec{Replicas: ptr.To[int32](1)}},
|
||||
|
|
@ -145,7 +145,7 @@ func TestCompilation(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "jsonPatch with excessive cost",
|
||||
policy: jsonPatches(variables(policy("d1"), v1alpha1.Variable{Name: "list", Expression: "[0,1,2,3,4,5,6,7,8,9]"}), v1alpha1.JSONPatch{
|
||||
policy: jsonPatches(variables(policy("d1"), v1beta1.Variable{Name: "list", Expression: "[0,1,2,3,4,5,6,7,8,9]"}), v1beta1.JSONPatch{
|
||||
Expression: `[
|
||||
JSONPatch{op: "replace", path: "/spec/replicas",
|
||||
value: variables.list.all(x1, variables.list.all(x2, variables.list.all(x3, variables.list.all(x4, variables.list.all(x5, variables.list.all(x5, "0123456789" == "0123456789"))))))? 1 : 0
|
||||
|
|
@ -163,14 +163,14 @@ func TestCompilation(t *testing.T) {
|
|||
spec: Object.spec{
|
||||
replicas: variables.list.all(x1, variables.list.all(x2, variables.list.all(x3, variables.list.all(x4, variables.list.all(x5, variables.list.all(x5, "0123456789" == "0123456789"))))))? 1 : 0
|
||||
}
|
||||
}`), v1alpha1.Variable{Name: "list", Expression: "[0,1,2,3,4,5,6,7,8,9]"}),
|
||||
}`), v1beta1.Variable{Name: "list", Expression: "[0,1,2,3,4,5,6,7,8,9]"}),
|
||||
gvr: deploymentGVR,
|
||||
object: &appsv1.Deployment{Spec: appsv1.DeploymentSpec{Replicas: ptr.To[int32](1)}},
|
||||
expectedErr: "operation cancelled: actual cost limit exceeded",
|
||||
},
|
||||
{
|
||||
name: "request variable",
|
||||
policy: jsonPatches(policy("d1"), v1alpha1.JSONPatch{
|
||||
policy: jsonPatches(policy("d1"), v1beta1.JSONPatch{
|
||||
Expression: `[
|
||||
JSONPatch{op: "replace", path: "/spec/replicas",
|
||||
value: request.kind.group == 'apps' && request.kind.version == 'v1' && request.kind.kind == 'Deployment' ? 10 : 0
|
||||
|
|
@ -182,7 +182,7 @@ func TestCompilation(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "namespace request variable",
|
||||
policy: jsonPatches(policy("d1"), v1alpha1.JSONPatch{
|
||||
policy: jsonPatches(policy("d1"), v1beta1.JSONPatch{
|
||||
Expression: `[
|
||||
JSONPatch{op: "replace", path: "/spec/replicas",
|
||||
value: namespaceObject.metadata.name == 'ns1' ? 10 : 0
|
||||
|
|
@ -195,7 +195,7 @@ func TestCompilation(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "authorizer check",
|
||||
policy: jsonPatches(policy("d1"), v1alpha1.JSONPatch{
|
||||
policy: jsonPatches(policy("d1"), v1beta1.JSONPatch{
|
||||
Expression: `[
|
||||
JSONPatch{op: "replace", path: "/spec/replicas",
|
||||
value: authorizer.group('').resource('endpoints').check('create').allowed() ? 10 : 0
|
||||
|
|
@ -208,7 +208,7 @@ func TestCompilation(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "object type has field access",
|
||||
policy: jsonPatches(policy("d1"), v1alpha1.JSONPatch{
|
||||
policy: jsonPatches(policy("d1"), v1beta1.JSONPatch{
|
||||
Expression: `[
|
||||
JSONPatch{
|
||||
op: "add", path: "/metadata/labels",
|
||||
|
|
@ -226,7 +226,7 @@ func TestCompilation(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "object type has field testing",
|
||||
policy: jsonPatches(policy("d1"), v1alpha1.JSONPatch{
|
||||
policy: jsonPatches(policy("d1"), v1beta1.JSONPatch{
|
||||
Expression: `[
|
||||
JSONPatch{
|
||||
op: "add", path: "/metadata/labels",
|
||||
|
|
@ -246,7 +246,7 @@ func TestCompilation(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "object type equality",
|
||||
policy: jsonPatches(policy("d1"), v1alpha1.JSONPatch{
|
||||
policy: jsonPatches(policy("d1"), v1beta1.JSONPatch{
|
||||
Expression: `[
|
||||
JSONPatch{
|
||||
op: "add", path: "/metadata/labels",
|
||||
|
|
@ -274,7 +274,7 @@ func TestCompilation(t *testing.T) {
|
|||
// recompile all expressions with fully bound types before evaluation and report
|
||||
// errors if invalid Object types like this are initialized.
|
||||
name: "object types are not fully type checked",
|
||||
policy: jsonPatches(policy("d1"), v1alpha1.JSONPatch{
|
||||
policy: jsonPatches(policy("d1"), v1beta1.JSONPatch{
|
||||
Expression: `[
|
||||
JSONPatch{
|
||||
op: "add", path: "/spec",
|
||||
|
|
@ -400,52 +400,52 @@ func TestCompilation(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func policy(name string) *v1alpha1.MutatingAdmissionPolicy {
|
||||
return &v1alpha1.MutatingAdmissionPolicy{
|
||||
func policy(name string) *v1beta1.MutatingAdmissionPolicy {
|
||||
return &v1beta1.MutatingAdmissionPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicySpec{},
|
||||
Spec: v1beta1.MutatingAdmissionPolicySpec{},
|
||||
}
|
||||
}
|
||||
|
||||
func variables(policy *v1alpha1.MutatingAdmissionPolicy, variables ...v1alpha1.Variable) *v1alpha1.MutatingAdmissionPolicy {
|
||||
func variables(policy *v1beta1.MutatingAdmissionPolicy, variables ...v1beta1.Variable) *v1beta1.MutatingAdmissionPolicy {
|
||||
policy.Spec.Variables = append(policy.Spec.Variables, variables...)
|
||||
return policy
|
||||
}
|
||||
|
||||
func jsonPatches(policy *v1alpha1.MutatingAdmissionPolicy, jsonPatches ...v1alpha1.JSONPatch) *v1alpha1.MutatingAdmissionPolicy {
|
||||
func jsonPatches(policy *v1beta1.MutatingAdmissionPolicy, jsonPatches ...v1beta1.JSONPatch) *v1beta1.MutatingAdmissionPolicy {
|
||||
for _, jsonPatch := range jsonPatches {
|
||||
policy.Spec.Mutations = append(policy.Spec.Mutations, v1alpha1.Mutation{
|
||||
policy.Spec.Mutations = append(policy.Spec.Mutations, v1beta1.Mutation{
|
||||
JSONPatch: &jsonPatch,
|
||||
PatchType: v1alpha1.PatchTypeJSONPatch,
|
||||
PatchType: v1beta1.PatchTypeJSONPatch,
|
||||
})
|
||||
}
|
||||
|
||||
return policy
|
||||
}
|
||||
|
||||
func applyConfigurations(policy *v1alpha1.MutatingAdmissionPolicy, expressions ...string) *v1alpha1.MutatingAdmissionPolicy {
|
||||
func applyConfigurations(policy *v1beta1.MutatingAdmissionPolicy, expressions ...string) *v1beta1.MutatingAdmissionPolicy {
|
||||
for _, expression := range expressions {
|
||||
policy.Spec.Mutations = append(policy.Spec.Mutations, v1alpha1.Mutation{
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{Expression: expression},
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
policy.Spec.Mutations = append(policy.Spec.Mutations, v1beta1.Mutation{
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{Expression: expression},
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
})
|
||||
}
|
||||
return policy
|
||||
}
|
||||
|
||||
func paramKind(policy *v1alpha1.MutatingAdmissionPolicy, paramKind *v1alpha1.ParamKind) *v1alpha1.MutatingAdmissionPolicy {
|
||||
func paramKind(policy *v1beta1.MutatingAdmissionPolicy, paramKind *v1beta1.ParamKind) *v1beta1.MutatingAdmissionPolicy {
|
||||
policy.Spec.ParamKind = paramKind
|
||||
return policy
|
||||
}
|
||||
|
||||
func mutations(policy *v1alpha1.MutatingAdmissionPolicy, mutations ...v1alpha1.Mutation) *v1alpha1.MutatingAdmissionPolicy {
|
||||
func mutations(policy *v1beta1.MutatingAdmissionPolicy, mutations ...v1beta1.Mutation) *v1beta1.MutatingAdmissionPolicy {
|
||||
policy.Spec.Mutations = append(policy.Spec.Mutations, mutations...)
|
||||
return policy
|
||||
}
|
||||
|
||||
func matchConstraints(policy *v1alpha1.MutatingAdmissionPolicy, matchConstraints *v1alpha1.MatchResources) *v1alpha1.MutatingAdmissionPolicy {
|
||||
func matchConstraints(policy *v1beta1.MutatingAdmissionPolicy, matchConstraints *v1beta1.MatchResources) *v1beta1.MutatingAdmissionPolicy {
|
||||
policy.Spec.MatchConstraints = matchConstraints
|
||||
return policy
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"k8s.io/api/admissionregistration/v1alpha1"
|
||||
"k8s.io/api/admissionregistration/v1beta1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apiequality "k8s.io/apimachinery/pkg/api/equality"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
|
|
@ -206,7 +206,7 @@ func (d *dispatcher) dispatchInvocations(
|
|||
policyReinvokeCtx.RequireReinvokingPreviouslyInvokedPlugins()
|
||||
reinvokeCtx.SetShouldReinvoke()
|
||||
}
|
||||
if invocation.Policy.Spec.ReinvocationPolicy == v1alpha1.IfNeededReinvocationPolicy {
|
||||
if invocation.Policy.Spec.ReinvocationPolicy == v1beta1.IfNeededReinvocationPolicy {
|
||||
policyReinvokeCtx.AddReinvocablePolicyToPreviouslyInvoked(invocationKey)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ import (
|
|||
"time"
|
||||
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/api/admissionregistration/v1alpha1"
|
||||
"k8s.io/api/admissionregistration/v1beta1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/equality"
|
||||
|
|
@ -77,14 +77,14 @@ func TestDispatcher(t *testing.T) {
|
|||
}},
|
||||
policyHooks: []generic.PolicyHook[*Policy, *PolicyBinding, PolicyEvaluator]{
|
||||
{
|
||||
Policy: mutations(matchConstraints(policy("policy1"), &v1alpha1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1alpha1.Equivalent),
|
||||
Policy: mutations(matchConstraints(policy("policy1"), &v1beta1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1beta1.Equivalent),
|
||||
NamespaceSelector: &metav1.LabelSelector{},
|
||||
ObjectSelector: &metav1.LabelSelector{},
|
||||
ResourceRules: []v1alpha1.NamedRuleWithOperations{
|
||||
ResourceRules: []v1beta1.NamedRuleWithOperations{
|
||||
{
|
||||
RuleWithOperations: v1alpha1.RuleWithOperations{
|
||||
Rule: v1alpha1.Rule{
|
||||
RuleWithOperations: v1beta1.RuleWithOperations{
|
||||
Rule: v1beta1.Rule{
|
||||
APIGroups: []string{"apps"},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"deployments"},
|
||||
|
|
@ -93,9 +93,9 @@ func TestDispatcher(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
}), v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
}), v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{
|
||||
spec: Object.spec{
|
||||
replicas: object.spec.replicas + 100
|
||||
|
|
@ -104,7 +104,7 @@ func TestDispatcher(t *testing.T) {
|
|||
}}),
|
||||
Bindings: []*PolicyBinding{{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicyBindingSpec{
|
||||
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
|
||||
PolicyName: "policy1",
|
||||
},
|
||||
}},
|
||||
|
|
@ -168,14 +168,14 @@ func TestDispatcher(t *testing.T) {
|
|||
},
|
||||
policyHooks: []generic.PolicyHook[*Policy, *PolicyBinding, PolicyEvaluator]{
|
||||
{
|
||||
Policy: paramKind(mutations(matchConstraints(policy("policy1"), &v1alpha1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1alpha1.Equivalent),
|
||||
Policy: paramKind(mutations(matchConstraints(policy("policy1"), &v1beta1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1beta1.Equivalent),
|
||||
NamespaceSelector: &metav1.LabelSelector{},
|
||||
ObjectSelector: &metav1.LabelSelector{},
|
||||
ResourceRules: []v1alpha1.NamedRuleWithOperations{
|
||||
ResourceRules: []v1beta1.NamedRuleWithOperations{
|
||||
{
|
||||
RuleWithOperations: v1alpha1.RuleWithOperations{
|
||||
Rule: v1alpha1.Rule{
|
||||
RuleWithOperations: v1beta1.RuleWithOperations{
|
||||
Rule: v1beta1.Rule{
|
||||
APIGroups: []string{"apps"},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"deployments"},
|
||||
|
|
@ -184,24 +184,24 @@ func TestDispatcher(t *testing.T) {
|
|||
},
|
||||
},
|
||||
}}),
|
||||
v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{
|
||||
spec: Object.spec{
|
||||
replicas: object.spec.replicas + int(params.data['key'])
|
||||
}
|
||||
}`,
|
||||
}}),
|
||||
&v1alpha1.ParamKind{
|
||||
&v1beta1.ParamKind{
|
||||
APIVersion: "v1",
|
||||
Kind: "ConfigMap",
|
||||
}),
|
||||
Bindings: []*PolicyBinding{{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicyBindingSpec{
|
||||
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
|
||||
PolicyName: "policy1",
|
||||
ParamRef: &v1alpha1.ParamRef{Name: "cm1", Namespace: "default"},
|
||||
ParamRef: &v1beta1.ParamRef{Name: "cm1", Namespace: "default"},
|
||||
},
|
||||
}},
|
||||
},
|
||||
|
|
@ -248,14 +248,14 @@ func TestDispatcher(t *testing.T) {
|
|||
}},
|
||||
policyHooks: []generic.PolicyHook[*Policy, *PolicyBinding, PolicyEvaluator]{
|
||||
{
|
||||
Policy: mutations(matchConstraints(policy("policy1"), &v1alpha1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1alpha1.Equivalent),
|
||||
Policy: mutations(matchConstraints(policy("policy1"), &v1beta1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1beta1.Equivalent),
|
||||
NamespaceSelector: &metav1.LabelSelector{},
|
||||
ObjectSelector: &metav1.LabelSelector{},
|
||||
ResourceRules: []v1alpha1.NamedRuleWithOperations{
|
||||
ResourceRules: []v1beta1.NamedRuleWithOperations{
|
||||
{
|
||||
RuleWithOperations: v1alpha1.RuleWithOperations{
|
||||
Rule: v1alpha1.Rule{
|
||||
RuleWithOperations: v1beta1.RuleWithOperations{
|
||||
Rule: v1beta1.Rule{
|
||||
APIGroups: []string{"apps"},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"deployments"},
|
||||
|
|
@ -264,9 +264,9 @@ func TestDispatcher(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
}), v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
}), v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{
|
||||
metadata: Object.metadata{
|
||||
labels: {"policy1": string(int(object.?metadata.labels["count"].orValue("1")) + 1)}
|
||||
|
|
@ -275,20 +275,20 @@ func TestDispatcher(t *testing.T) {
|
|||
}}),
|
||||
Bindings: []*PolicyBinding{{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicyBindingSpec{
|
||||
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
|
||||
PolicyName: "policy1",
|
||||
},
|
||||
}},
|
||||
},
|
||||
{
|
||||
Policy: mutations(matchConstraints(policy("policy2"), &v1alpha1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1alpha1.Equivalent),
|
||||
Policy: mutations(matchConstraints(policy("policy2"), &v1beta1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1beta1.Equivalent),
|
||||
NamespaceSelector: &metav1.LabelSelector{},
|
||||
ObjectSelector: &metav1.LabelSelector{},
|
||||
ResourceRules: []v1alpha1.NamedRuleWithOperations{
|
||||
ResourceRules: []v1beta1.NamedRuleWithOperations{
|
||||
{
|
||||
RuleWithOperations: v1alpha1.RuleWithOperations{
|
||||
Rule: v1alpha1.Rule{
|
||||
RuleWithOperations: v1beta1.RuleWithOperations{
|
||||
Rule: v1beta1.Rule{
|
||||
APIGroups: []string{"apps"},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"deployments"},
|
||||
|
|
@ -297,9 +297,9 @@ func TestDispatcher(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
}), v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
}), v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{
|
||||
metadata: Object.metadata{
|
||||
labels: {"policy2": string(int(object.?metadata.labels["count"].orValue("1")) + 1)}
|
||||
|
|
@ -308,7 +308,7 @@ func TestDispatcher(t *testing.T) {
|
|||
}}),
|
||||
Bindings: []*PolicyBinding{{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicyBindingSpec{
|
||||
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
|
||||
PolicyName: "policy2",
|
||||
},
|
||||
}},
|
||||
|
|
@ -359,19 +359,19 @@ func TestDispatcher(t *testing.T) {
|
|||
}},
|
||||
policyHooks: []generic.PolicyHook[*Policy, *PolicyBinding, PolicyEvaluator]{
|
||||
{
|
||||
Policy: &v1alpha1.MutatingAdmissionPolicy{
|
||||
Policy: &v1beta1.MutatingAdmissionPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "policy1",
|
||||
},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &v1alpha1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1alpha1.Equivalent),
|
||||
Spec: v1beta1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &v1beta1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1beta1.Equivalent),
|
||||
NamespaceSelector: &metav1.LabelSelector{},
|
||||
ObjectSelector: &metav1.LabelSelector{},
|
||||
ResourceRules: []v1alpha1.NamedRuleWithOperations{
|
||||
ResourceRules: []v1beta1.NamedRuleWithOperations{
|
||||
{
|
||||
RuleWithOperations: v1alpha1.RuleWithOperations{
|
||||
Rule: v1alpha1.Rule{
|
||||
RuleWithOperations: v1beta1.RuleWithOperations{
|
||||
Rule: v1beta1.Rule{
|
||||
APIGroups: []string{"apps"},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"deployments"},
|
||||
|
|
@ -381,9 +381,9 @@ func TestDispatcher(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
Mutations: []v1alpha1.Mutation{{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
Mutations: []v1beta1.Mutation{{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{
|
||||
metadata: Object.metadata{
|
||||
labels: {"environment": "production"}
|
||||
|
|
@ -394,25 +394,25 @@ func TestDispatcher(t *testing.T) {
|
|||
},
|
||||
Bindings: []*PolicyBinding{{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicyBindingSpec{
|
||||
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
|
||||
PolicyName: "policy1",
|
||||
},
|
||||
}},
|
||||
},
|
||||
{
|
||||
Policy: &v1alpha1.MutatingAdmissionPolicy{
|
||||
Policy: &v1beta1.MutatingAdmissionPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "policy2",
|
||||
},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &v1alpha1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1alpha1.Equivalent),
|
||||
Spec: v1beta1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &v1beta1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1beta1.Equivalent),
|
||||
NamespaceSelector: &metav1.LabelSelector{},
|
||||
ObjectSelector: &metav1.LabelSelector{},
|
||||
ResourceRules: []v1alpha1.NamedRuleWithOperations{
|
||||
ResourceRules: []v1beta1.NamedRuleWithOperations{
|
||||
{
|
||||
RuleWithOperations: v1alpha1.RuleWithOperations{
|
||||
Rule: v1alpha1.Rule{
|
||||
RuleWithOperations: v1beta1.RuleWithOperations{
|
||||
Rule: v1beta1.Rule{
|
||||
APIGroups: []string{"apps"},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"deployments"},
|
||||
|
|
@ -422,15 +422,15 @@ func TestDispatcher(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
MatchConditions: []v1alpha1.MatchCondition{
|
||||
MatchConditions: []v1beta1.MatchCondition{
|
||||
{
|
||||
Name: "prodonly",
|
||||
Expression: `object.?metadata.labels["environment"].orValue("") == "production"`,
|
||||
},
|
||||
},
|
||||
Mutations: []v1alpha1.Mutation{{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
Mutations: []v1beta1.Mutation{{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{
|
||||
metadata: Object.metadata{
|
||||
labels: {"policy1invoked": "true"}
|
||||
|
|
@ -441,7 +441,7 @@ func TestDispatcher(t *testing.T) {
|
|||
},
|
||||
Bindings: []*PolicyBinding{{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicyBindingSpec{
|
||||
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
|
||||
PolicyName: "policy2",
|
||||
},
|
||||
}},
|
||||
|
|
@ -493,19 +493,19 @@ func TestDispatcher(t *testing.T) {
|
|||
}},
|
||||
policyHooks: []generic.PolicyHook[*Policy, *PolicyBinding, PolicyEvaluator]{
|
||||
{
|
||||
Policy: &v1alpha1.MutatingAdmissionPolicy{
|
||||
Policy: &v1beta1.MutatingAdmissionPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "policy1",
|
||||
},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &v1alpha1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1alpha1.Equivalent),
|
||||
Spec: v1beta1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &v1beta1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1beta1.Equivalent),
|
||||
NamespaceSelector: &metav1.LabelSelector{},
|
||||
ObjectSelector: &metav1.LabelSelector{},
|
||||
ResourceRules: []v1alpha1.NamedRuleWithOperations{
|
||||
ResourceRules: []v1beta1.NamedRuleWithOperations{
|
||||
{
|
||||
RuleWithOperations: v1alpha1.RuleWithOperations{
|
||||
Rule: v1alpha1.Rule{
|
||||
RuleWithOperations: v1beta1.RuleWithOperations{
|
||||
Rule: v1beta1.Rule{
|
||||
APIGroups: []string{"apps"},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"deployments"},
|
||||
|
|
@ -515,15 +515,15 @@ func TestDispatcher(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
MatchConditions: []v1alpha1.MatchCondition{
|
||||
MatchConditions: []v1beta1.MatchCondition{
|
||||
{
|
||||
Name: "prodonly",
|
||||
Expression: `object.?metadata.labels["environment"].orValue("") == "production"`,
|
||||
},
|
||||
},
|
||||
Mutations: []v1alpha1.Mutation{{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
Mutations: []v1beta1.Mutation{{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{
|
||||
metadata: Object.metadata{
|
||||
labels: {"policy1invoked": "true"}
|
||||
|
|
@ -534,25 +534,25 @@ func TestDispatcher(t *testing.T) {
|
|||
},
|
||||
Bindings: []*PolicyBinding{{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicyBindingSpec{
|
||||
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
|
||||
PolicyName: "policy1",
|
||||
},
|
||||
}},
|
||||
},
|
||||
{
|
||||
Policy: &v1alpha1.MutatingAdmissionPolicy{
|
||||
Policy: &v1beta1.MutatingAdmissionPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "policy2",
|
||||
},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &v1alpha1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1alpha1.Equivalent),
|
||||
Spec: v1beta1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &v1beta1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1beta1.Equivalent),
|
||||
NamespaceSelector: &metav1.LabelSelector{},
|
||||
ObjectSelector: &metav1.LabelSelector{},
|
||||
ResourceRules: []v1alpha1.NamedRuleWithOperations{
|
||||
ResourceRules: []v1beta1.NamedRuleWithOperations{
|
||||
{
|
||||
RuleWithOperations: v1alpha1.RuleWithOperations{
|
||||
Rule: v1alpha1.Rule{
|
||||
RuleWithOperations: v1beta1.RuleWithOperations{
|
||||
Rule: v1beta1.Rule{
|
||||
APIGroups: []string{"apps"},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"deployments"},
|
||||
|
|
@ -562,9 +562,9 @@ func TestDispatcher(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
Mutations: []v1alpha1.Mutation{{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
Mutations: []v1beta1.Mutation{{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{
|
||||
metadata: Object.metadata{
|
||||
labels: {"environment": "production"}
|
||||
|
|
@ -575,7 +575,7 @@ func TestDispatcher(t *testing.T) {
|
|||
},
|
||||
Bindings: []*PolicyBinding{{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicyBindingSpec{
|
||||
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
|
||||
PolicyName: "policy2",
|
||||
},
|
||||
}},
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import (
|
|||
celgo "github.com/google/cel-go/cel"
|
||||
"io"
|
||||
|
||||
"k8s.io/api/admissionregistration/v1alpha1"
|
||||
"k8s.io/api/admissionregistration/v1beta1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
|
@ -53,9 +53,9 @@ func Register(plugins *admission.Plugins) {
|
|||
})
|
||||
}
|
||||
|
||||
type Policy = v1alpha1.MutatingAdmissionPolicy
|
||||
type PolicyBinding = v1alpha1.MutatingAdmissionPolicyBinding
|
||||
type PolicyMutation = v1alpha1.Mutation
|
||||
type Policy = v1beta1.MutatingAdmissionPolicy
|
||||
type PolicyBinding = v1beta1.MutatingAdmissionPolicyBinding
|
||||
type PolicyMutation = v1beta1.Mutation
|
||||
type PolicyHook = generic.PolicyHook[*Policy, *PolicyBinding, PolicyEvaluator]
|
||||
|
||||
type Mutator struct {
|
||||
|
|
@ -96,8 +96,8 @@ func NewPlugin(_ io.Reader) *Plugin {
|
|||
handler,
|
||||
func(f informers.SharedInformerFactory, client kubernetes.Interface, dynamicClient dynamic.Interface, restMapper meta.RESTMapper) generic.Source[PolicyHook] {
|
||||
return generic.NewPolicySource(
|
||||
f.Admissionregistration().V1alpha1().MutatingAdmissionPolicies().Informer(),
|
||||
f.Admissionregistration().V1alpha1().MutatingAdmissionPolicyBindings().Informer(),
|
||||
f.Admissionregistration().V1beta1().MutatingAdmissionPolicies().Informer(),
|
||||
f.Admissionregistration().V1beta1().MutatingAdmissionPolicyBindings().Informer(),
|
||||
NewMutatingAdmissionPolicyAccessor,
|
||||
NewMutatingAdmissionPolicyBindingAccessor,
|
||||
compilePolicy,
|
||||
|
|
@ -142,7 +142,7 @@ func (v *Variable) GetName() string {
|
|||
return v.Name
|
||||
}
|
||||
|
||||
func convertv1alpha1Variables(variables []v1alpha1.Variable) []cel.NamedExpressionAccessor {
|
||||
func convertv1alpha1Variables(variables []v1beta1.Variable) []cel.NamedExpressionAccessor {
|
||||
namedExpressions := make([]cel.NamedExpressionAccessor, len(variables))
|
||||
for i, variable := range variables {
|
||||
namedExpressions[i] = &Variable{Name: variable.Name, Expression: variable.Expression}
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ import (
|
|||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"k8s.io/api/admissionregistration/v1alpha1"
|
||||
"k8s.io/api/admissionregistration/v1beta1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
|
@ -88,25 +88,25 @@ func TestBasicPatch(t *testing.T) {
|
|||
require.NoError(t, testContext.UpdateAndWait(
|
||||
&mutating.Policy{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "policy"},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &v1alpha1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1alpha1.Equivalent),
|
||||
Spec: v1beta1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &v1beta1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1beta1.Equivalent),
|
||||
NamespaceSelector: &metav1.LabelSelector{},
|
||||
ObjectSelector: &metav1.LabelSelector{},
|
||||
},
|
||||
Mutations: []v1alpha1.Mutation{
|
||||
Mutations: []v1beta1.Mutation{
|
||||
{
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: "ignored, but required",
|
||||
},
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&mutating.PolicyBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicyBindingSpec{
|
||||
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
|
||||
PolicyName: "policy",
|
||||
},
|
||||
},
|
||||
|
|
@ -145,25 +145,25 @@ func TestJSONPatch(t *testing.T) {
|
|||
require.NoError(t, testContext.UpdateAndWait(
|
||||
&mutating.Policy{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "policy"},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &v1alpha1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1alpha1.Equivalent),
|
||||
Spec: v1beta1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &v1beta1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1beta1.Equivalent),
|
||||
NamespaceSelector: &metav1.LabelSelector{},
|
||||
ObjectSelector: &metav1.LabelSelector{},
|
||||
},
|
||||
Mutations: []v1alpha1.Mutation{
|
||||
Mutations: []v1beta1.Mutation{
|
||||
{
|
||||
JSONPatch: &v1alpha1.JSONPatch{
|
||||
JSONPatch: &v1beta1.JSONPatch{
|
||||
Expression: "ignored, but required",
|
||||
},
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&mutating.PolicyBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicyBindingSpec{
|
||||
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
|
||||
PolicyName: "policy",
|
||||
},
|
||||
},
|
||||
|
|
@ -207,25 +207,25 @@ func TestSSAPatch(t *testing.T) {
|
|||
require.NoError(t, testContext.UpdateAndWait(
|
||||
&mutating.Policy{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "policy"},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &v1alpha1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1alpha1.Equivalent),
|
||||
Spec: v1beta1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &v1beta1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1beta1.Equivalent),
|
||||
NamespaceSelector: &metav1.LabelSelector{},
|
||||
ObjectSelector: &metav1.LabelSelector{},
|
||||
},
|
||||
Mutations: []v1alpha1.Mutation{
|
||||
Mutations: []v1beta1.Mutation{
|
||||
{
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: "ignored, but required",
|
||||
},
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&mutating.PolicyBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicyBindingSpec{
|
||||
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
|
||||
PolicyName: "policy",
|
||||
},
|
||||
},
|
||||
|
|
@ -274,25 +274,25 @@ func TestSSAMapList(t *testing.T) {
|
|||
require.NoError(t, testContext.UpdateAndWait(
|
||||
&mutating.Policy{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "policy"},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &v1alpha1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1alpha1.Equivalent),
|
||||
Spec: v1beta1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &v1beta1.MatchResources{
|
||||
MatchPolicy: ptr.To(v1beta1.Equivalent),
|
||||
NamespaceSelector: &metav1.LabelSelector{},
|
||||
ObjectSelector: &metav1.LabelSelector{},
|
||||
},
|
||||
Mutations: []v1alpha1.Mutation{
|
||||
Mutations: []v1beta1.Mutation{
|
||||
{
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: "ignored, but required",
|
||||
},
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
&mutating.PolicyBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicyBindingSpec{
|
||||
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
|
||||
PolicyName: "policy",
|
||||
},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@ package apimachinery
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
admissionregistrationv1alpha1 "k8s.io/api/admissionregistration/v1alpha1"
|
||||
"k8s.io/apiserver/pkg/features"
|
||||
"k8s.io/kubernetes/test/e2e/feature"
|
||||
"k8s.io/utils/ptr"
|
||||
|
|
@ -28,7 +29,7 @@ import (
|
|||
"github.com/onsi/gomega"
|
||||
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
admissionregistrationv1alpha1 "k8s.io/api/admissionregistration/v1alpha1"
|
||||
admissionregistrationv1beta1 "k8s.io/api/admissionregistration/v1beta1"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
|
|
@ -71,17 +72,17 @@ var _ = SIGDescribe("MutatingAdmissionPolicy [Privileged:ClusterAdmin]", feature
|
|||
*/
|
||||
framework.It("should mutate a Deployment", func(ctx context.Context) {
|
||||
ginkgo.By("creating the policy", func() {
|
||||
policy := &admissionregistrationv1alpha1.MutatingAdmissionPolicy{
|
||||
policy := &admissionregistrationv1beta1.MutatingAdmissionPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: f.UniqueName + ".policy.example.com",
|
||||
},
|
||||
Spec: admissionregistrationv1alpha1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &admissionregistrationv1alpha1.MatchResources{
|
||||
ResourceRules: []admissionregistrationv1alpha1.NamedRuleWithOperations{
|
||||
Spec: admissionregistrationv1beta1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &admissionregistrationv1beta1.MatchResources{
|
||||
ResourceRules: []admissionregistrationv1beta1.NamedRuleWithOperations{
|
||||
{
|
||||
RuleWithOperations: admissionregistrationv1alpha1.RuleWithOperations{
|
||||
Operations: []admissionregistrationv1alpha1.OperationType{"CREATE", "UPDATE"},
|
||||
Rule: admissionregistrationv1alpha1.Rule{
|
||||
RuleWithOperations: admissionregistrationv1beta1.RuleWithOperations{
|
||||
Operations: []admissionregistrationv1beta1.OperationType{"CREATE", "UPDATE"},
|
||||
Rule: admissionregistrationv1beta1.Rule{
|
||||
APIGroups: []string{"apps"},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"deployments"},
|
||||
|
|
@ -95,10 +96,10 @@ var _ = SIGDescribe("MutatingAdmissionPolicy [Privileged:ClusterAdmin]", feature
|
|||
},
|
||||
},
|
||||
},
|
||||
Mutations: []admissionregistrationv1alpha1.Mutation{
|
||||
Mutations: []admissionregistrationv1beta1.Mutation{
|
||||
{
|
||||
PatchType: admissionregistrationv1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &admissionregistrationv1alpha1.ApplyConfiguration{
|
||||
PatchType: admissionregistrationv1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &admissionregistrationv1beta1.ApplyConfiguration{
|
||||
Expression: `
|
||||
Object{
|
||||
metadata: Object.metadata{
|
||||
|
|
@ -110,21 +111,21 @@ var _ = SIGDescribe("MutatingAdmissionPolicy [Privileged:ClusterAdmin]", feature
|
|||
},
|
||||
},
|
||||
},
|
||||
ReinvocationPolicy: admissionregistrationv1alpha1.NeverReinvocationPolicy,
|
||||
ReinvocationPolicy: admissionregistrationv1beta1.NeverReinvocationPolicy,
|
||||
},
|
||||
}
|
||||
|
||||
policy, err := client.AdmissionregistrationV1alpha1().MutatingAdmissionPolicies().Create(ctx, policy, metav1.CreateOptions{})
|
||||
policy, err := client.AdmissionregistrationV1beta1().MutatingAdmissionPolicies().Create(ctx, policy, metav1.CreateOptions{})
|
||||
framework.ExpectNoError(err, "create policy")
|
||||
ginkgo.DeferCleanup(func(ctx context.Context, name string) error {
|
||||
return client.AdmissionregistrationV1alpha1().MutatingAdmissionPolicies().Delete(ctx, name, metav1.DeleteOptions{})
|
||||
return client.AdmissionregistrationV1beta1().MutatingAdmissionPolicies().Delete(ctx, name, metav1.DeleteOptions{})
|
||||
}, policy.Name)
|
||||
|
||||
binding := createMAPBinding(f.UniqueName+".binding.example.com", f.UniqueName, policy.Name)
|
||||
binding, err = client.AdmissionregistrationV1alpha1().MutatingAdmissionPolicyBindings().Create(ctx, binding, metav1.CreateOptions{})
|
||||
binding, err = client.AdmissionregistrationV1beta1().MutatingAdmissionPolicyBindings().Create(ctx, binding, metav1.CreateOptions{})
|
||||
framework.ExpectNoError(err, "create binding")
|
||||
ginkgo.DeferCleanup(func(ctx context.Context, name string) error {
|
||||
return client.AdmissionregistrationV1alpha1().MutatingAdmissionPolicyBindings().Delete(ctx, name, metav1.DeleteOptions{})
|
||||
return client.AdmissionregistrationV1beta1().MutatingAdmissionPolicyBindings().Delete(ctx, name, metav1.DeleteOptions{})
|
||||
}, binding.Name)
|
||||
|
||||
// Test the mutation
|
||||
|
|
@ -537,7 +538,7 @@ var _ = SIGDescribe("MutatingAdmissionPolicy [Privileged:ClusterAdmin]", feature
|
|||
gomega.Expect(evt.Type).To(gomega.Equal(watch.Modified))
|
||||
vapbWatched, isFS := evt.Object.(*admissionregistrationv1alpha1.MutatingAdmissionPolicyBinding)
|
||||
if !isFS {
|
||||
framework.Failf("expected an object of type: %T, but got %T", &admissionregistrationv1alpha1.MutatingAdmissionPolicyBinding{}, evt.Object)
|
||||
framework.Failf("expected an object of type: %T, but got %T", &admissionregistrationv1beta1.MutatingAdmissionPolicyBinding{}, evt.Object)
|
||||
}
|
||||
if vapbWatched.Annotations["patched"] == "true" {
|
||||
sawAnnotation = true
|
||||
|
|
@ -588,14 +589,436 @@ var _ = SIGDescribe("MutatingAdmissionPolicy [Privileged:ClusterAdmin]", feature
|
|||
framework.ExpectNoError(err)
|
||||
gomega.Expect(itemsColWithoutFinalizer).To(gomega.BeEmpty(), "filtered list should have 0 items")
|
||||
})
|
||||
|
||||
/*
|
||||
Release: v1.34
|
||||
Testname: MutatingAdmissionPolicy API
|
||||
Description:
|
||||
The admissionregistration.k8s.io API group MUST exist in the
|
||||
/apis discovery document.
|
||||
The admissionregistration.k8s.io/v1beta11 API group/version MUST exist
|
||||
in the /apis/admissionregistration.k8s.io discovery document.
|
||||
The MutatingAdmissionPolicy MUST exist in the
|
||||
/apis/admissionregistration.k8s.io/v1beta1 discovery document.
|
||||
The mutatingadmisionpolicy resource must support create, get,
|
||||
list, watch, update, patch, delete, and deletecollection.
|
||||
*/
|
||||
framework.It("should support MutatingAdmissionPolicy API operations", func(ctx context.Context) {
|
||||
mapVersion := "v1beta1"
|
||||
ginkgo.By("getting /apis")
|
||||
{
|
||||
discoveryGroups, err := f.ClientSet.Discovery().ServerGroups()
|
||||
framework.ExpectNoError(err)
|
||||
found := false
|
||||
for _, group := range discoveryGroups.Groups {
|
||||
if group.Name == admissionregistrationv1.GroupName {
|
||||
for _, version := range group.Versions {
|
||||
if version.Version == mapVersion {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
framework.Failf("expected MutatingAdmissionPolicy API group/version, got %#v", discoveryGroups.Groups)
|
||||
}
|
||||
}
|
||||
|
||||
ginkgo.By("getting /apis/admissionregistration.k8s.io")
|
||||
{
|
||||
group := &metav1.APIGroup{}
|
||||
err := f.ClientSet.Discovery().RESTClient().Get().AbsPath("/apis/admissionregistration.k8s.io").Do(ctx).Into(group)
|
||||
framework.ExpectNoError(err)
|
||||
found := false
|
||||
for _, version := range group.Versions {
|
||||
if version.Version == mapVersion {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
framework.Failf("expected MutatingAdmissionPolicy API version, got %#v", group.Versions)
|
||||
}
|
||||
}
|
||||
|
||||
ginkgo.By("getting /apis/admissionregistration.k8s.io/" + mapVersion)
|
||||
{
|
||||
resources, err := f.ClientSet.Discovery().ServerResourcesForGroupVersion(admissionregistrationv1beta1.SchemeGroupVersion.String())
|
||||
framework.ExpectNoError(err)
|
||||
foundVAP := false
|
||||
for _, resource := range resources.APIResources {
|
||||
switch resource.Name {
|
||||
case "mutatingadmissionpolicies":
|
||||
foundVAP = true
|
||||
}
|
||||
}
|
||||
if !foundVAP {
|
||||
framework.Failf("expected mutatingadmissionpolicies, got %#v", resources.APIResources)
|
||||
}
|
||||
}
|
||||
|
||||
client := f.ClientSet.AdmissionregistrationV1beta1().MutatingAdmissionPolicies()
|
||||
labelKey, labelValue := "example-e2e-map-label", utilrand.String(8)
|
||||
label := fmt.Sprintf("%s=%s", labelKey, labelValue)
|
||||
|
||||
template := &admissionregistrationv1beta1.MutatingAdmissionPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "e2e-example-map-",
|
||||
Labels: map[string]string{
|
||||
labelKey: labelValue,
|
||||
},
|
||||
},
|
||||
Spec: admissionregistrationv1beta1.MutatingAdmissionPolicySpec{
|
||||
ReinvocationPolicy: admissionregistrationv1beta1.NeverReinvocationPolicy,
|
||||
Mutations: []admissionregistrationv1beta1.Mutation{
|
||||
{
|
||||
PatchType: admissionregistrationv1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &admissionregistrationv1beta1.ApplyConfiguration{
|
||||
Expression: `
|
||||
Object{
|
||||
metadata: Object.metadata{
|
||||
annotations: {
|
||||
"my-foo-annotation": "myAnnotationValue"
|
||||
}
|
||||
}
|
||||
}`,
|
||||
},
|
||||
},
|
||||
},
|
||||
MatchConstraints: &admissionregistrationv1beta1.MatchResources{
|
||||
ResourceRules: []admissionregistrationv1beta1.NamedRuleWithOperations{
|
||||
{
|
||||
RuleWithOperations: admissionregistrationv1beta1.RuleWithOperations{
|
||||
Operations: []admissionregistrationv1beta1.OperationType{"CREATE"},
|
||||
Rule: admissionregistrationv1beta1.Rule{
|
||||
APIGroups: []string{"apps"},
|
||||
APIVersions: []string{"v1"},
|
||||
Resources: []string{"deployments"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
ginkgo.DeferCleanup(func(ctx context.Context) {
|
||||
err := client.DeleteCollection(ctx, metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: label})
|
||||
framework.ExpectNoError(err)
|
||||
})
|
||||
|
||||
ginkgo.By("creating")
|
||||
_, err := client.Create(ctx, template, metav1.CreateOptions{})
|
||||
framework.ExpectNoError(err)
|
||||
_, err = client.Create(ctx, template, metav1.CreateOptions{})
|
||||
framework.ExpectNoError(err)
|
||||
mapCreated, err := client.Create(ctx, template, metav1.CreateOptions{})
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
ginkgo.By("getting")
|
||||
mapRead, err := client.Get(ctx, mapCreated.Name, metav1.GetOptions{})
|
||||
framework.ExpectNoError(err)
|
||||
gomega.Expect(mapRead.UID).To(gomega.Equal(mapCreated.UID))
|
||||
|
||||
ginkgo.By("listing")
|
||||
list, err := client.List(ctx, metav1.ListOptions{LabelSelector: label})
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
ginkgo.By("watching")
|
||||
framework.Logf("starting watch")
|
||||
mapWatch, err := client.Watch(ctx, metav1.ListOptions{ResourceVersion: list.ResourceVersion, LabelSelector: label})
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
ginkgo.By("patching")
|
||||
patchBytes := []byte(`{"metadata":{"annotations":{"patched":"true"}},"spec":{"failurePolicy":"Ignore"}}`)
|
||||
mapPatched, err := client.Patch(ctx, mapCreated.Name, types.MergePatchType, patchBytes, metav1.PatchOptions{})
|
||||
framework.ExpectNoError(err)
|
||||
gomega.Expect(mapPatched.Annotations).To(gomega.HaveKeyWithValue("patched", "true"), "patched object should have the applied annotation")
|
||||
gomega.Expect(mapPatched.Spec.FailurePolicy).To(gomega.HaveValue(gomega.Equal(admissionregistrationv1beta1.Ignore)), "patched object should have the applied spec")
|
||||
|
||||
ginkgo.By("updating")
|
||||
var mapUpdated *admissionregistrationv1beta1.MutatingAdmissionPolicy
|
||||
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||
mpolicy, err := client.Get(ctx, mapCreated.Name, metav1.GetOptions{})
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
mapToUpdate := mpolicy.DeepCopy()
|
||||
mapToUpdate.Annotations["updated"] = "true"
|
||||
fail := admissionregistrationv1beta1.Fail
|
||||
mapToUpdate.Spec.FailurePolicy = &fail
|
||||
|
||||
mapUpdated, err = client.Update(ctx, mapToUpdate, metav1.UpdateOptions{})
|
||||
return err
|
||||
})
|
||||
framework.ExpectNoError(err, "failed to update mutatingadmissionpolicy %q", mapCreated.Name)
|
||||
gomega.Expect(mapUpdated.Annotations).To(gomega.HaveKeyWithValue("updated", "true"), "updated object should have the applied annotation")
|
||||
gomega.Expect(mapUpdated.Spec.FailurePolicy).To(gomega.HaveValue(gomega.Equal(admissionregistrationv1beta1.Fail)), "updated object should have the applied spec")
|
||||
|
||||
framework.Logf("waiting for watch events with expected annotations")
|
||||
for sawAnnotation := false; !sawAnnotation; {
|
||||
select {
|
||||
case evt, ok := <-mapWatch.ResultChan():
|
||||
if !ok {
|
||||
framework.Fail("watch channel should not close")
|
||||
}
|
||||
gomega.Expect(evt.Type).To(gomega.Equal(watch.Modified))
|
||||
mapWatched, isFS := evt.Object.(*admissionregistrationv1beta1.MutatingAdmissionPolicy)
|
||||
if !isFS {
|
||||
framework.Failf("expected an object of type: %T, but got %T", &admissionregistrationv1beta1.MutatingAdmissionPolicy{}, evt.Object)
|
||||
}
|
||||
if mapWatched.Annotations["patched"] == "true" {
|
||||
sawAnnotation = true
|
||||
mapWatch.Stop()
|
||||
} else {
|
||||
framework.Logf("missing expected annotations, waiting: %#v", mapWatched.Annotations)
|
||||
}
|
||||
case <-time.After(wait.ForeverTestTimeout):
|
||||
framework.Fail("timed out waiting for watch event")
|
||||
}
|
||||
}
|
||||
|
||||
ginkgo.By("deleting")
|
||||
err = client.Delete(ctx, mapCreated.Name, metav1.DeleteOptions{})
|
||||
framework.ExpectNoError(err)
|
||||
vapTmp, err := client.Get(ctx, mapCreated.Name, metav1.GetOptions{})
|
||||
switch {
|
||||
case err == nil && vapTmp.GetDeletionTimestamp() != nil && len(vapTmp.GetFinalizers()) > 0:
|
||||
// deletion requested successfully, object is blocked by finalizers
|
||||
case err == nil:
|
||||
framework.Failf("expected deleted object, got %#v", vapTmp)
|
||||
case apierrors.IsNotFound(err):
|
||||
// deleted successfully
|
||||
default:
|
||||
framework.Failf("expected 404, got %#v", err)
|
||||
}
|
||||
|
||||
list, err = client.List(ctx, metav1.ListOptions{LabelSelector: label})
|
||||
var itemsWithoutFinalizer []admissionregistrationv1beta1.MutatingAdmissionPolicy
|
||||
for _, item := range list.Items {
|
||||
if len(item.GetFinalizers()) == 0 {
|
||||
itemsWithoutFinalizer = append(itemsWithoutFinalizer, item)
|
||||
}
|
||||
}
|
||||
framework.ExpectNoError(err)
|
||||
gomega.Expect(itemsWithoutFinalizer).To(gomega.HaveLen(2), "filtered list should have 2 items")
|
||||
|
||||
ginkgo.By("deleting a collection")
|
||||
err = client.DeleteCollection(ctx, metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: label})
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
list, err = client.List(ctx, metav1.ListOptions{LabelSelector: label})
|
||||
var itemsColWithoutFinalizer []admissionregistrationv1beta1.MutatingAdmissionPolicy
|
||||
for _, item := range list.Items {
|
||||
if item.GetDeletionTimestamp() == nil || len(item.GetFinalizers()) == 0 {
|
||||
itemsColWithoutFinalizer = append(itemsColWithoutFinalizer, item)
|
||||
}
|
||||
}
|
||||
framework.ExpectNoError(err)
|
||||
gomega.Expect(itemsColWithoutFinalizer).To(gomega.BeEmpty(), "filtered list should have 0 items")
|
||||
})
|
||||
|
||||
/*
|
||||
Release: v1.34
|
||||
Testname: MutatingadmissionPolicyBinding API
|
||||
Description:
|
||||
The admissionregistration.k8s.io API group MUST exist in the
|
||||
/apis discovery document.
|
||||
The admissionregistration.k8s.io/v1beta1 API group/version MUST exist
|
||||
in the /apis/admissionregistration.k8s.io discovery document.
|
||||
The MutatingadmissionPolicyBinding resources MUST exist in the
|
||||
/apis/admissionregistration.k8s.io/v1beta1 discovery document.
|
||||
The MutatingadmissionPolicyBinding resource must support create, get,
|
||||
list, watch, update, patch, delete, and deletecollection.
|
||||
*/
|
||||
framework.It("should support MutatingAdmissionPolicyBinding API operations", func(ctx context.Context) {
|
||||
mapbVersion := "v1beta1"
|
||||
ginkgo.By("getting /apis")
|
||||
{
|
||||
discoveryGroups, err := f.ClientSet.Discovery().ServerGroups()
|
||||
framework.ExpectNoError(err)
|
||||
found := false
|
||||
for _, group := range discoveryGroups.Groups {
|
||||
if group.Name == admissionregistrationv1.GroupName {
|
||||
for _, version := range group.Versions {
|
||||
if version.Version == mapbVersion {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
framework.Failf("expected MutatingAdmissionPolicyBinding API group/version, got %#v", discoveryGroups.Groups)
|
||||
}
|
||||
}
|
||||
|
||||
ginkgo.By("getting /apis/admissionregistration.k8s.io")
|
||||
{
|
||||
group := &metav1.APIGroup{}
|
||||
err := f.ClientSet.Discovery().RESTClient().Get().AbsPath("/apis/admissionregistration.k8s.io").Do(ctx).Into(group)
|
||||
framework.ExpectNoError(err)
|
||||
found := false
|
||||
for _, version := range group.Versions {
|
||||
if version.Version == mapbVersion {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
framework.Failf("expected MutatingAdmissionPolicyBinding API version, got %#v", group.Versions)
|
||||
}
|
||||
}
|
||||
|
||||
ginkgo.By("getting /apis/admissionregistration.k8s.io/" + mapbVersion)
|
||||
{
|
||||
resources, err := f.ClientSet.Discovery().ServerResourcesForGroupVersion(admissionregistrationv1beta1.SchemeGroupVersion.String())
|
||||
framework.ExpectNoError(err)
|
||||
foundVAPB := false
|
||||
for _, resource := range resources.APIResources {
|
||||
switch resource.Name {
|
||||
case "mutatingadmissionpolicybindings":
|
||||
foundVAPB = true
|
||||
}
|
||||
}
|
||||
if !foundVAPB {
|
||||
framework.Failf("expected mutatingadmissionpolicybindings, got %#v", resources.APIResources)
|
||||
}
|
||||
}
|
||||
|
||||
client := f.ClientSet.AdmissionregistrationV1beta1().MutatingAdmissionPolicyBindings()
|
||||
labelKey, labelValue := "example-e2e-mapb-label", utilrand.String(8)
|
||||
label := fmt.Sprintf("%s=%s", labelKey, labelValue)
|
||||
|
||||
template := &admissionregistrationv1beta1.MutatingAdmissionPolicyBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
GenerateName: "e2e-example-mapb-",
|
||||
Labels: map[string]string{
|
||||
labelKey: labelValue,
|
||||
},
|
||||
},
|
||||
Spec: admissionregistrationv1beta1.MutatingAdmissionPolicyBindingSpec{
|
||||
PolicyName: "replicalimit-policy.example.com",
|
||||
},
|
||||
}
|
||||
|
||||
ginkgo.DeferCleanup(func(ctx context.Context) {
|
||||
err := client.DeleteCollection(ctx, metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: label})
|
||||
framework.ExpectNoError(err)
|
||||
})
|
||||
|
||||
ginkgo.By("creating")
|
||||
_, err := client.Create(ctx, template, metav1.CreateOptions{})
|
||||
framework.ExpectNoError(err)
|
||||
_, err = client.Create(ctx, template, metav1.CreateOptions{})
|
||||
framework.ExpectNoError(err)
|
||||
mapbCreated, err := client.Create(ctx, template, metav1.CreateOptions{})
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
ginkgo.By("getting")
|
||||
mapbRead, err := client.Get(ctx, mapbCreated.Name, metav1.GetOptions{})
|
||||
framework.ExpectNoError(err)
|
||||
gomega.Expect(mapbRead.UID).To(gomega.Equal(mapbCreated.UID))
|
||||
|
||||
ginkgo.By("listing")
|
||||
list, err := client.List(ctx, metav1.ListOptions{LabelSelector: label})
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
ginkgo.By("watching")
|
||||
framework.Logf("starting watch")
|
||||
mapbWatch, err := client.Watch(ctx, metav1.ListOptions{ResourceVersion: list.ResourceVersion, LabelSelector: label})
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
ginkgo.By("patching")
|
||||
patchBytes := []byte(`{"metadata":{"annotations":{"patched":"true"}}}`)
|
||||
mapbPatched, err := client.Patch(ctx, mapbCreated.Name, types.MergePatchType, patchBytes, metav1.PatchOptions{})
|
||||
framework.ExpectNoError(err)
|
||||
gomega.Expect(mapbPatched.Annotations).To(gomega.HaveKeyWithValue("patched", "true"), "patched object should have the applied annotation")
|
||||
|
||||
ginkgo.By("updating")
|
||||
var mapbUpdated *admissionregistrationv1beta1.MutatingAdmissionPolicyBinding
|
||||
err = retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||
mapb, err := client.Get(ctx, mapbCreated.Name, metav1.GetOptions{})
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
mapbToUpdate := mapb.DeepCopy()
|
||||
mapbToUpdate.Annotations["updated"] = "true"
|
||||
|
||||
mapbUpdated, err = client.Update(ctx, mapbToUpdate, metav1.UpdateOptions{})
|
||||
return err
|
||||
})
|
||||
framework.ExpectNoError(err, "failed to update mutatingadmissionpolicybinding %q", mapbCreated.Name)
|
||||
gomega.Expect(mapbUpdated.Annotations).To(gomega.HaveKeyWithValue("updated", "true"), "updated object should have the applied annotation")
|
||||
|
||||
framework.Logf("waiting for watch events with expected annotations")
|
||||
for sawAnnotation := false; !sawAnnotation; {
|
||||
select {
|
||||
case evt, ok := <-mapbWatch.ResultChan():
|
||||
if !ok {
|
||||
framework.Fail("watch channel should not close")
|
||||
}
|
||||
gomega.Expect(evt.Type).To(gomega.Equal(watch.Modified))
|
||||
vapbWatched, isFS := evt.Object.(*admissionregistrationv1beta1.MutatingAdmissionPolicyBinding)
|
||||
if !isFS {
|
||||
framework.Failf("expected an object of type: %T, but got %T", &admissionregistrationv1beta1.MutatingAdmissionPolicyBinding{}, evt.Object)
|
||||
}
|
||||
if vapbWatched.Annotations["patched"] == "true" {
|
||||
sawAnnotation = true
|
||||
mapbWatch.Stop()
|
||||
} else {
|
||||
framework.Logf("missing expected annotations, waiting: %#v", vapbWatched.Annotations)
|
||||
}
|
||||
case <-time.After(wait.ForeverTestTimeout):
|
||||
framework.Fail("timed out waiting for watch event")
|
||||
}
|
||||
}
|
||||
ginkgo.By("deleting")
|
||||
err = client.Delete(ctx, mapbCreated.Name, metav1.DeleteOptions{})
|
||||
framework.ExpectNoError(err)
|
||||
mapbTmp, err := client.Get(ctx, mapbCreated.Name, metav1.GetOptions{})
|
||||
switch {
|
||||
case err == nil && mapbTmp.GetDeletionTimestamp() != nil && len(mapbTmp.GetFinalizers()) > 0:
|
||||
// deletion requested successfully, object is blocked by finalizers
|
||||
case err == nil:
|
||||
framework.Failf("expected deleted object, got %#v", mapbTmp)
|
||||
case apierrors.IsNotFound(err):
|
||||
// deleted successfully
|
||||
default:
|
||||
framework.Failf("expected 404, got %#v", err)
|
||||
}
|
||||
|
||||
list, err = client.List(ctx, metav1.ListOptions{LabelSelector: label})
|
||||
var itemsWithoutFinalizer []admissionregistrationv1beta1.MutatingAdmissionPolicyBinding
|
||||
for _, item := range list.Items {
|
||||
if len(item.GetFinalizers()) == 0 {
|
||||
itemsWithoutFinalizer = append(itemsWithoutFinalizer, item)
|
||||
}
|
||||
}
|
||||
framework.ExpectNoError(err)
|
||||
gomega.Expect(itemsWithoutFinalizer).To(gomega.HaveLen(2), "filtered list should have 2 items")
|
||||
|
||||
ginkgo.By("deleting a collection")
|
||||
err = client.DeleteCollection(ctx, metav1.DeleteOptions{}, metav1.ListOptions{LabelSelector: label})
|
||||
framework.ExpectNoError(err)
|
||||
|
||||
list, err = client.List(ctx, metav1.ListOptions{LabelSelector: label})
|
||||
var itemsColWithoutFinalizer []admissionregistrationv1beta1.MutatingAdmissionPolicyBinding
|
||||
for _, item := range list.Items {
|
||||
if item.GetDeletionTimestamp() == nil || len(item.GetFinalizers()) == 0 {
|
||||
itemsColWithoutFinalizer = append(itemsColWithoutFinalizer, item)
|
||||
}
|
||||
}
|
||||
framework.ExpectNoError(err)
|
||||
gomega.Expect(itemsColWithoutFinalizer).To(gomega.BeEmpty(), "filtered list should have 0 items")
|
||||
})
|
||||
})
|
||||
|
||||
func createMAPBinding(bindingName string, uniqueLabel string, policyName string) *admissionregistrationv1alpha1.MutatingAdmissionPolicyBinding {
|
||||
return &admissionregistrationv1alpha1.MutatingAdmissionPolicyBinding{
|
||||
func createMAPBinding(bindingName string, uniqueLabel string, policyName string) *admissionregistrationv1beta1.MutatingAdmissionPolicyBinding {
|
||||
return &admissionregistrationv1beta1.MutatingAdmissionPolicyBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{Name: bindingName},
|
||||
Spec: admissionregistrationv1alpha1.MutatingAdmissionPolicyBindingSpec{
|
||||
Spec: admissionregistrationv1beta1.MutatingAdmissionPolicyBindingSpec{
|
||||
PolicyName: policyName,
|
||||
MatchResources: &admissionregistrationv1alpha1.MatchResources{
|
||||
MatchResources: &admissionregistrationv1beta1.MatchResources{
|
||||
NamespaceSelector: &metav1.LabelSelector{
|
||||
MatchLabels: map[string]string{uniqueLabel: "true"},
|
||||
},
|
||||
|
|
|
|||
|
|
@ -155,6 +155,8 @@ var (
|
|||
gvr("admissionregistration.k8s.io", "v1", "validatingadmissionpolicybindings"): true,
|
||||
gvr("admissionregistration.k8s.io", "v1alpha1", "mutatingadmissionpolicies"): true,
|
||||
gvr("admissionregistration.k8s.io", "v1alpha1", "mutatingadmissionpolicybindings"): true,
|
||||
gvr("admissionregistration.k8s.io", "v1beta1", "mutatingadmissionpolicies"): true,
|
||||
gvr("admissionregistration.k8s.io", "v1beta1", "mutatingadmissionpolicybindings"): true,
|
||||
}
|
||||
|
||||
parentResources = map[schema.GroupVersionResource]schema.GroupVersionResource{
|
||||
|
|
|
|||
|
|
@ -155,6 +155,8 @@ var (
|
|||
gvr("admissionregistration.k8s.io", "v1", "validatingadmissionpolicybindings"): true,
|
||||
gvr("admissionregistration.k8s.io", "v1alpha1", "mutatingadmissionpolicies"): true,
|
||||
gvr("admissionregistration.k8s.io", "v1alpha1", "mutatingadmissionpolicybindings"): true,
|
||||
gvr("admissionregistration.k8s.io", "v1beta1", "mutatingadmissionpolicies"): true,
|
||||
gvr("admissionregistration.k8s.io", "v1beta1", "mutatingadmissionpolicybindings"): true,
|
||||
// transient resource exemption
|
||||
gvr("authentication.k8s.io", "v1", "selfsubjectreviews"): true,
|
||||
gvr("authentication.k8s.io", "v1beta1", "selfsubjectreviews"): true,
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
"k8s.io/api/admissionregistration/v1alpha1"
|
||||
"k8s.io/api/admissionregistration/v1beta1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apiextensions "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
|
|
@ -55,10 +55,11 @@ import (
|
|||
// and waiting for bindings to become ready by dry-running marker requests until the binding successfully
|
||||
// mutates a marker, and then verifies the policy exactly once.
|
||||
func TestMutatingAdmissionPolicy(t *testing.T) {
|
||||
matchEndpointResources := v1alpha1.MatchResources{
|
||||
ResourceRules: []v1alpha1.NamedRuleWithOperations{
|
||||
allow := v1beta1.AllowAction
|
||||
matchEndpointResources := v1beta1.MatchResources{
|
||||
ResourceRules: []v1beta1.NamedRuleWithOperations{
|
||||
{
|
||||
RuleWithOperations: v1alpha1.RuleWithOperations{
|
||||
RuleWithOperations: v1beta1.RuleWithOperations{
|
||||
Operations: []admissionregistrationv1.OperationType{"*"},
|
||||
Rule: admissionregistrationv1.Rule{
|
||||
APIGroups: []string{""},
|
||||
|
|
@ -72,8 +73,8 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
|
||||
cases := []struct {
|
||||
name string
|
||||
policies []*v1alpha1.MutatingAdmissionPolicy
|
||||
bindings []*v1alpha1.MutatingAdmissionPolicyBinding
|
||||
policies []*v1beta1.MutatingAdmissionPolicy
|
||||
bindings []*v1beta1.MutatingAdmissionPolicyBinding
|
||||
params []*corev1.ConfigMap
|
||||
|
||||
requestOperation admissionregistrationv1.OperationType
|
||||
|
|
@ -84,10 +85,10 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
name: "basic",
|
||||
policies: []*v1alpha1.MutatingAdmissionPolicy{
|
||||
mutatingPolicy("basic-policy", v1alpha1.NeverReinvocationPolicy, matchEndpointResources, nil, v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
policies: []*v1beta1.MutatingAdmissionPolicy{
|
||||
mutatingPolicy("basic-policy", v1beta1.NeverReinvocationPolicy, matchEndpointResources, nil, v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `
|
||||
Object{
|
||||
metadata: Object.metadata{
|
||||
|
|
@ -99,7 +100,7 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
},
|
||||
}),
|
||||
},
|
||||
bindings: []*v1alpha1.MutatingAdmissionPolicyBinding{
|
||||
bindings: []*v1beta1.MutatingAdmissionPolicyBinding{
|
||||
mutatingBinding("basic-policy", nil, nil),
|
||||
},
|
||||
requestOperation: admissionregistrationv1.Create,
|
||||
|
|
@ -122,10 +123,10 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "multiple policies",
|
||||
policies: []*v1alpha1.MutatingAdmissionPolicy{
|
||||
mutatingPolicy("multi-policy-1", v1alpha1.NeverReinvocationPolicy, matchEndpointResources, nil, v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
policies: []*v1beta1.MutatingAdmissionPolicy{
|
||||
mutatingPolicy("multi-policy-1", v1beta1.NeverReinvocationPolicy, matchEndpointResources, nil, v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `
|
||||
Object{
|
||||
metadata: Object.metadata{
|
||||
|
|
@ -136,9 +137,9 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
}`,
|
||||
},
|
||||
}),
|
||||
mutatingPolicy("multi-policy-2", v1alpha1.NeverReinvocationPolicy, matchEndpointResources, nil, v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
mutatingPolicy("multi-policy-2", v1beta1.NeverReinvocationPolicy, matchEndpointResources, nil, v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `
|
||||
Object{
|
||||
metadata: Object.metadata{
|
||||
|
|
@ -150,7 +151,7 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
},
|
||||
}),
|
||||
},
|
||||
bindings: []*v1alpha1.MutatingAdmissionPolicyBinding{
|
||||
bindings: []*v1beta1.MutatingAdmissionPolicyBinding{
|
||||
mutatingBinding("multi-policy-1", nil, nil),
|
||||
mutatingBinding("multi-policy-2", nil, nil),
|
||||
},
|
||||
|
|
@ -175,13 +176,13 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "policy with native param",
|
||||
policies: []*v1alpha1.MutatingAdmissionPolicy{
|
||||
mutatingPolicy("policy-with-native", v1alpha1.NeverReinvocationPolicy, matchEndpointResources, &v1alpha1.ParamKind{
|
||||
policies: []*v1beta1.MutatingAdmissionPolicy{
|
||||
mutatingPolicy("policy-with-native", v1beta1.NeverReinvocationPolicy, matchEndpointResources, &v1beta1.ParamKind{
|
||||
APIVersion: "v1",
|
||||
Kind: "ConfigMap",
|
||||
}, v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
}, v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `
|
||||
Object{
|
||||
metadata: Object.metadata{
|
||||
|
|
@ -193,9 +194,10 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
},
|
||||
}),
|
||||
},
|
||||
bindings: []*v1alpha1.MutatingAdmissionPolicyBinding{
|
||||
mutatingBinding("policy-with-native", &v1alpha1.ParamRef{
|
||||
Name: "policy-with-native-param",
|
||||
bindings: []*v1beta1.MutatingAdmissionPolicyBinding{
|
||||
mutatingBinding("policy-with-native", &v1beta1.ParamRef{
|
||||
Name: "policy-with-native-param",
|
||||
ParameterNotFoundAction: &allow,
|
||||
}, nil),
|
||||
},
|
||||
params: []*corev1.ConfigMap{
|
||||
|
|
@ -230,19 +232,19 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "policy with multiple params quantified by single binding",
|
||||
policies: []*v1alpha1.MutatingAdmissionPolicy{
|
||||
mutatingPolicy("multi-param-binding", v1alpha1.NeverReinvocationPolicy, matchEndpointResources, &v1alpha1.ParamKind{
|
||||
policies: []*v1beta1.MutatingAdmissionPolicy{
|
||||
mutatingPolicy("multi-param-binding", v1beta1.NeverReinvocationPolicy, matchEndpointResources, &v1beta1.ParamKind{
|
||||
APIVersion: "v1",
|
||||
Kind: "ConfigMap",
|
||||
}, v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
}, v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{metadata: Object.metadata{annotations: params.data}}`,
|
||||
},
|
||||
}),
|
||||
},
|
||||
bindings: []*v1alpha1.MutatingAdmissionPolicyBinding{
|
||||
mutatingBinding("multi-param-binding", &v1alpha1.ParamRef{
|
||||
bindings: []*v1beta1.MutatingAdmissionPolicyBinding{
|
||||
mutatingBinding("multi-param-binding", &v1beta1.ParamRef{
|
||||
// note empty namespace. all params matching request namespace
|
||||
// will be used
|
||||
Selector: &metav1.LabelSelector{
|
||||
|
|
@ -250,7 +252,8 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
"multi-param-binding-param": "true",
|
||||
},
|
||||
},
|
||||
Namespace: "default",
|
||||
Namespace: "default",
|
||||
ParameterNotFoundAction: &allow,
|
||||
}, nil),
|
||||
},
|
||||
params: []*corev1.ConfigMap{
|
||||
|
|
@ -302,15 +305,15 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "policy with variables",
|
||||
policies: []*v1alpha1.MutatingAdmissionPolicy{
|
||||
withMutatingVariables([]v1alpha1.Variable{
|
||||
policies: []*v1beta1.MutatingAdmissionPolicy{
|
||||
withMutatingVariables([]v1beta1.Variable{
|
||||
{Name: "foo1", Expression: `"foo1" + "Value"`},
|
||||
{Name: "foo2", Expression: `variables.foo1.replace("1", "2")`},
|
||||
},
|
||||
mutatingPolicy("policy-with-multiple-mutations", v1alpha1.NeverReinvocationPolicy, matchEndpointResources, nil,
|
||||
v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
mutatingPolicy("policy-with-multiple-mutations", v1beta1.NeverReinvocationPolicy, matchEndpointResources, nil,
|
||||
v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `
|
||||
Object{
|
||||
metadata: Object.metadata{
|
||||
|
|
@ -321,18 +324,18 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
}`,
|
||||
},
|
||||
},
|
||||
v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeJSONPatch,
|
||||
JSONPatch: &v1alpha1.JSONPatch{
|
||||
v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeJSONPatch,
|
||||
JSONPatch: &v1beta1.JSONPatch{
|
||||
Expression: `[
|
||||
JSONPatch{op: "test", path: "/metadata/annotations", value: {"foo1": variables.foo1}},
|
||||
JSONPatch{op: "add", path: "/metadata/annotations/foo2", value: variables.foo2},
|
||||
]`,
|
||||
},
|
||||
},
|
||||
v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `
|
||||
Object{
|
||||
metadata: Object.metadata{
|
||||
|
|
@ -345,7 +348,7 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
},
|
||||
)),
|
||||
},
|
||||
bindings: []*v1alpha1.MutatingAdmissionPolicyBinding{
|
||||
bindings: []*v1beta1.MutatingAdmissionPolicyBinding{
|
||||
mutatingBinding("policy-with-multiple-mutations", nil, nil),
|
||||
},
|
||||
requestOperation: admissionregistrationv1.Create,
|
||||
|
|
@ -370,16 +373,16 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "match condition matches",
|
||||
policies: []*v1alpha1.MutatingAdmissionPolicy{
|
||||
withMutatingMatchConditions([]v1alpha1.MatchCondition{{Name: "test-only", Expression: `object.metadata.?labels["environment"] == optional.of("test")`}},
|
||||
mutatingPolicy("policy-match-condition", v1alpha1.NeverReinvocationPolicy, matchEndpointResources, nil, v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
policies: []*v1beta1.MutatingAdmissionPolicy{
|
||||
withMutatingMatchConditions([]v1beta1.MatchCondition{{Name: "test-only", Expression: `object.metadata.?labels["environment"] == optional.of("test")`}},
|
||||
mutatingPolicy("policy-match-condition", v1beta1.NeverReinvocationPolicy, matchEndpointResources, nil, v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{metadata: Object.metadata{labels: {"applied": "updated"}}}`,
|
||||
},
|
||||
})),
|
||||
},
|
||||
bindings: []*v1alpha1.MutatingAdmissionPolicyBinding{
|
||||
bindings: []*v1beta1.MutatingAdmissionPolicyBinding{
|
||||
mutatingBinding("policy-match-condition", nil, nil),
|
||||
},
|
||||
requestOperation: admissionregistrationv1.Create,
|
||||
|
|
@ -403,11 +406,11 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
// same as the multiple mutations test, but the mutations are split
|
||||
// across multiple policies
|
||||
name: "multiple policies requiring reinvocation",
|
||||
policies: []*v1alpha1.MutatingAdmissionPolicy{
|
||||
mutatingPolicy("policy-1", v1alpha1.IfNeededReinvocationPolicy, matchEndpointResources, nil,
|
||||
v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
policies: []*v1beta1.MutatingAdmissionPolicy{
|
||||
mutatingPolicy("policy-1", v1beta1.IfNeededReinvocationPolicy, matchEndpointResources, nil,
|
||||
v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `
|
||||
Object{
|
||||
metadata: Object.metadata{
|
||||
|
|
@ -420,10 +423,10 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
},
|
||||
},
|
||||
),
|
||||
mutatingPolicy("policy-2", v1alpha1.IfNeededReinvocationPolicy, matchEndpointResources, nil,
|
||||
v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
mutatingPolicy("policy-2", v1beta1.IfNeededReinvocationPolicy, matchEndpointResources, nil,
|
||||
v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `
|
||||
Object{
|
||||
metadata: Object.metadata{
|
||||
|
|
@ -436,10 +439,10 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
},
|
||||
},
|
||||
),
|
||||
mutatingPolicy("policy-3", v1alpha1.NeverReinvocationPolicy, matchEndpointResources, nil,
|
||||
v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
mutatingPolicy("policy-3", v1beta1.NeverReinvocationPolicy, matchEndpointResources, nil,
|
||||
v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `
|
||||
Object{
|
||||
metadata: Object.metadata{
|
||||
|
|
@ -453,7 +456,7 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
},
|
||||
),
|
||||
},
|
||||
bindings: []*v1alpha1.MutatingAdmissionPolicyBinding{
|
||||
bindings: []*v1beta1.MutatingAdmissionPolicyBinding{
|
||||
mutatingBinding("policy-1", nil, nil),
|
||||
mutatingBinding("policy-2", nil, nil),
|
||||
mutatingBinding("policy-3", nil, nil),
|
||||
|
|
@ -493,7 +496,7 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
|
||||
// Run all tests in a shared apiserver
|
||||
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.MutatingAdmissionPolicy, true)
|
||||
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1alpha1.SchemeGroupVersion)}
|
||||
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1beta1.SchemeGroupVersion)}
|
||||
server, err := apiservertesting.StartTestServer(t, nil, flags, framework.SharedEtcd())
|
||||
require.NoError(t, err)
|
||||
defer server.TearDownFn()
|
||||
|
|
@ -519,7 +522,7 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
for _, p := range tc.policies {
|
||||
// Modify each policy to also mutate marker requests.
|
||||
p = withMutatingWaitReadyConstraintAndExpression(p, fmt.Sprintf("%d-%s", i, p.Name))
|
||||
_, err = client.AdmissionregistrationV1alpha1().MutatingAdmissionPolicies().Create(ctx, p, metav1.CreateOptions{FieldManager: "integration-test"})
|
||||
_, err = client.AdmissionregistrationV1beta1().MutatingAdmissionPolicies().Create(ctx, p, metav1.CreateOptions{FieldManager: "integration-test"})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
|
|
@ -572,10 +575,11 @@ func TestMutatingAdmissionPolicy(t *testing.T) {
|
|||
// a single apiserver and then uses marker requests to check that a binding is ready before testing it exactly once.
|
||||
// Only test cases that cannot be run in TestMutatingAdmissionPolicy should be added here.
|
||||
func TestMutatingAdmissionPolicy_Slow(t *testing.T) {
|
||||
matchEndpointResources := v1alpha1.MatchResources{
|
||||
ResourceRules: []v1alpha1.NamedRuleWithOperations{
|
||||
allow := v1beta1.AllowAction
|
||||
matchEndpointResources := v1beta1.MatchResources{
|
||||
ResourceRules: []v1beta1.NamedRuleWithOperations{
|
||||
{
|
||||
RuleWithOperations: v1alpha1.RuleWithOperations{
|
||||
RuleWithOperations: v1beta1.RuleWithOperations{
|
||||
Operations: []admissionregistrationv1.OperationType{"*"},
|
||||
Rule: admissionregistrationv1.Rule{
|
||||
APIGroups: []string{""},
|
||||
|
|
@ -589,8 +593,8 @@ func TestMutatingAdmissionPolicy_Slow(t *testing.T) {
|
|||
|
||||
cases := []struct {
|
||||
name string
|
||||
policies []*v1alpha1.MutatingAdmissionPolicy
|
||||
bindings []*v1alpha1.MutatingAdmissionPolicyBinding
|
||||
policies []*v1beta1.MutatingAdmissionPolicy
|
||||
bindings []*v1beta1.MutatingAdmissionPolicyBinding
|
||||
params []*corev1.ConfigMap
|
||||
|
||||
requestOperation admissionregistrationv1.OperationType
|
||||
|
|
@ -602,10 +606,10 @@ func TestMutatingAdmissionPolicy_Slow(t *testing.T) {
|
|||
}{
|
||||
{
|
||||
name: "unbound policy is no-op",
|
||||
policies: []*v1alpha1.MutatingAdmissionPolicy{
|
||||
mutatingPolicy("unbound-policy", v1alpha1.NeverReinvocationPolicy, matchEndpointResources, nil, v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
policies: []*v1beta1.MutatingAdmissionPolicy{
|
||||
mutatingPolicy("unbound-policy", v1beta1.NeverReinvocationPolicy, matchEndpointResources, nil, v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `
|
||||
Object{
|
||||
metadata: Object.metadata{
|
||||
|
|
@ -634,16 +638,16 @@ func TestMutatingAdmissionPolicy_Slow(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "failure policy ignore",
|
||||
policies: []*v1alpha1.MutatingAdmissionPolicy{
|
||||
withMutatingFailurePolicy(v1alpha1.Ignore,
|
||||
mutatingPolicy("policy", v1alpha1.NeverReinvocationPolicy, matchEndpointResources, nil, v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
policies: []*v1beta1.MutatingAdmissionPolicy{
|
||||
withMutatingFailurePolicy(v1beta1.Ignore,
|
||||
mutatingPolicy("policy", v1beta1.NeverReinvocationPolicy, matchEndpointResources, nil, v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{spec: Object.spec{invalidField: "invalid apply configuration"}}`,
|
||||
},
|
||||
})),
|
||||
},
|
||||
bindings: []*v1alpha1.MutatingAdmissionPolicyBinding{
|
||||
bindings: []*v1beta1.MutatingAdmissionPolicyBinding{
|
||||
mutatingBinding("policy", nil, nil),
|
||||
},
|
||||
requestOperation: admissionregistrationv1.Create,
|
||||
|
|
@ -663,16 +667,16 @@ func TestMutatingAdmissionPolicy_Slow(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "match condition does not match",
|
||||
policies: []*v1alpha1.MutatingAdmissionPolicy{
|
||||
withMutatingMatchConditions([]v1alpha1.MatchCondition{{Name: "test-only", Expression: `object.metadata.?labels["environment"] == optional.of("test")`}},
|
||||
mutatingPolicy("policy-no-match-condition", v1alpha1.NeverReinvocationPolicy, matchEndpointResources, nil, v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
policies: []*v1beta1.MutatingAdmissionPolicy{
|
||||
withMutatingMatchConditions([]v1beta1.MatchCondition{{Name: "test-only", Expression: `object.metadata.?labels["environment"] == optional.of("test")`}},
|
||||
mutatingPolicy("policy-no-match-condition", v1beta1.NeverReinvocationPolicy, matchEndpointResources, nil, v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{metadata: Object.metadata{labels: {"applied": "updated"}}}`,
|
||||
},
|
||||
})),
|
||||
},
|
||||
bindings: []*v1alpha1.MutatingAdmissionPolicyBinding{
|
||||
bindings: []*v1beta1.MutatingAdmissionPolicyBinding{
|
||||
mutatingBinding("policy-no-match-condition", nil, nil),
|
||||
},
|
||||
requestOperation: admissionregistrationv1.Create,
|
||||
|
|
@ -694,23 +698,23 @@ func TestMutatingAdmissionPolicy_Slow(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "some policy conditions match",
|
||||
policies: []*v1alpha1.MutatingAdmissionPolicy{
|
||||
withMutatingMatchConditions([]v1alpha1.MatchCondition{{Name: "test-only", Expression: `object.metadata.?labels["environment"] == optional.of("production")`}},
|
||||
mutatingPolicy("policy-1", v1alpha1.NeverReinvocationPolicy, matchEndpointResources, nil, v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
policies: []*v1beta1.MutatingAdmissionPolicy{
|
||||
withMutatingMatchConditions([]v1beta1.MatchCondition{{Name: "test-only", Expression: `object.metadata.?labels["environment"] == optional.of("production")`}},
|
||||
mutatingPolicy("policy-1", v1beta1.NeverReinvocationPolicy, matchEndpointResources, nil, v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{metadata: Object.metadata{labels: {"applied": "wrong"}}}`,
|
||||
},
|
||||
})),
|
||||
withMutatingMatchConditions([]v1alpha1.MatchCondition{{Name: "test-only", Expression: `object.metadata.?labels["environment"] == optional.of("test")`}},
|
||||
mutatingPolicy("policy-2", v1alpha1.NeverReinvocationPolicy, matchEndpointResources, nil, v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
withMutatingMatchConditions([]v1beta1.MatchCondition{{Name: "test-only", Expression: `object.metadata.?labels["environment"] == optional.of("test")`}},
|
||||
mutatingPolicy("policy-2", v1beta1.NeverReinvocationPolicy, matchEndpointResources, nil, v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{metadata: Object.metadata{labels: {"applied": "updated"}}}`,
|
||||
},
|
||||
})),
|
||||
},
|
||||
bindings: []*v1alpha1.MutatingAdmissionPolicyBinding{
|
||||
bindings: []*v1beta1.MutatingAdmissionPolicyBinding{
|
||||
mutatingBinding("policy-1", nil, nil),
|
||||
mutatingBinding("policy-2", nil, nil),
|
||||
},
|
||||
|
|
@ -733,11 +737,11 @@ func TestMutatingAdmissionPolicy_Slow(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "mutate status subresource",
|
||||
policies: []*v1alpha1.MutatingAdmissionPolicy{
|
||||
mutatingPolicy("subresource-status", v1alpha1.NeverReinvocationPolicy, v1alpha1.MatchResources{
|
||||
ResourceRules: []v1alpha1.NamedRuleWithOperations{
|
||||
policies: []*v1beta1.MutatingAdmissionPolicy{
|
||||
mutatingPolicy("subresource-status", v1beta1.NeverReinvocationPolicy, v1beta1.MatchResources{
|
||||
ResourceRules: []v1beta1.NamedRuleWithOperations{
|
||||
{
|
||||
RuleWithOperations: v1alpha1.RuleWithOperations{
|
||||
RuleWithOperations: v1beta1.RuleWithOperations{
|
||||
Operations: []admissionregistrationv1.OperationType{"*"},
|
||||
Rule: admissionregistrationv1.Rule{
|
||||
APIGroups: []string{""},
|
||||
|
|
@ -747,9 +751,9 @@ func TestMutatingAdmissionPolicy_Slow(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
}, nil, v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
}, nil, v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{
|
||||
status: Object.status{
|
||||
conditions: [Object.status.conditions{
|
||||
|
|
@ -761,7 +765,7 @@ func TestMutatingAdmissionPolicy_Slow(t *testing.T) {
|
|||
},
|
||||
}),
|
||||
},
|
||||
bindings: []*v1alpha1.MutatingAdmissionPolicyBinding{
|
||||
bindings: []*v1beta1.MutatingAdmissionPolicyBinding{
|
||||
mutatingBinding("subresource-status", nil, nil),
|
||||
},
|
||||
requestOperation: admissionregistrationv1.Update,
|
||||
|
|
@ -803,25 +807,27 @@ func TestMutatingAdmissionPolicy_Slow(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "multiple bindings with different params",
|
||||
policies: []*v1alpha1.MutatingAdmissionPolicy{
|
||||
mutatingPolicy("multi-binding", v1alpha1.NeverReinvocationPolicy, matchEndpointResources, &v1alpha1.ParamKind{
|
||||
policies: []*v1beta1.MutatingAdmissionPolicy{
|
||||
mutatingPolicy("multi-binding", v1beta1.NeverReinvocationPolicy, matchEndpointResources, &v1beta1.ParamKind{
|
||||
APIVersion: "v1",
|
||||
Kind: "ConfigMap",
|
||||
}, v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
}, v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{metadata: Object.metadata{annotations: params.data}}`,
|
||||
},
|
||||
}),
|
||||
},
|
||||
bindings: []*v1alpha1.MutatingAdmissionPolicyBinding{
|
||||
mutatingBinding("multi-binding", &v1alpha1.ParamRef{
|
||||
Name: "multi-binding-param-1",
|
||||
Namespace: "default",
|
||||
bindings: []*v1beta1.MutatingAdmissionPolicyBinding{
|
||||
mutatingBinding("multi-binding", &v1beta1.ParamRef{
|
||||
Name: "multi-binding-param-1",
|
||||
Namespace: "default",
|
||||
ParameterNotFoundAction: &allow,
|
||||
}, nil),
|
||||
mutatingBinding("multi-binding", &v1alpha1.ParamRef{
|
||||
Name: "multi-binding-param-2",
|
||||
Namespace: "default",
|
||||
mutatingBinding("multi-binding", &v1beta1.ParamRef{
|
||||
Name: "multi-binding-param-2",
|
||||
Namespace: "default",
|
||||
ParameterNotFoundAction: &allow,
|
||||
}, nil),
|
||||
},
|
||||
params: []*corev1.ConfigMap{
|
||||
|
|
@ -869,24 +875,24 @@ func TestMutatingAdmissionPolicy_Slow(t *testing.T) {
|
|||
// Same as the other cases, but the reinvocation is caused by
|
||||
// multiple params bound
|
||||
name: "multiple params causing reinvocation",
|
||||
policies: []*v1alpha1.MutatingAdmissionPolicy{
|
||||
policies: []*v1beta1.MutatingAdmissionPolicy{
|
||||
mutatingPolicy(
|
||||
"multi-param-reinvocation",
|
||||
v1alpha1.IfNeededReinvocationPolicy,
|
||||
v1beta1.IfNeededReinvocationPolicy,
|
||||
matchEndpointResources,
|
||||
&v1alpha1.ParamKind{
|
||||
&v1beta1.ParamKind{
|
||||
APIVersion: "v1",
|
||||
Kind: "ConfigMap",
|
||||
},
|
||||
v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{metadata: Object.metadata{annotations: params.data}}`,
|
||||
},
|
||||
},
|
||||
v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `
|
||||
Object{
|
||||
metadata: Object.metadata{
|
||||
|
|
@ -900,21 +906,21 @@ func TestMutatingAdmissionPolicy_Slow(t *testing.T) {
|
|||
),
|
||||
mutatingPolicy(
|
||||
"policy-with-param-no-reinvoke",
|
||||
v1alpha1.NeverReinvocationPolicy,
|
||||
v1beta1.NeverReinvocationPolicy,
|
||||
matchEndpointResources,
|
||||
&v1alpha1.ParamKind{
|
||||
&v1beta1.ParamKind{
|
||||
APIVersion: "v1",
|
||||
Kind: "ConfigMap",
|
||||
},
|
||||
v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{metadata: Object.metadata{annotations: params.data}}`,
|
||||
},
|
||||
},
|
||||
v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `
|
||||
Object{
|
||||
metadata: Object.metadata{
|
||||
|
|
@ -927,8 +933,8 @@ func TestMutatingAdmissionPolicy_Slow(t *testing.T) {
|
|||
},
|
||||
),
|
||||
},
|
||||
bindings: []*v1alpha1.MutatingAdmissionPolicyBinding{
|
||||
mutatingBinding("multi-param-reinvocation", &v1alpha1.ParamRef{
|
||||
bindings: []*v1beta1.MutatingAdmissionPolicyBinding{
|
||||
mutatingBinding("multi-param-reinvocation", &v1beta1.ParamRef{
|
||||
// note empty namespace. all params matching request namespace
|
||||
// will be used
|
||||
Selector: &metav1.LabelSelector{
|
||||
|
|
@ -936,11 +942,13 @@ func TestMutatingAdmissionPolicy_Slow(t *testing.T) {
|
|||
"multi-param-reinvocation": "true",
|
||||
},
|
||||
},
|
||||
ParameterNotFoundAction: &allow,
|
||||
}, nil),
|
||||
mutatingBinding("policy-with-param-no-reinvoke", &v1alpha1.ParamRef{
|
||||
mutatingBinding("policy-with-param-no-reinvoke", &v1beta1.ParamRef{
|
||||
// note empty namespace. all params matching request namespace
|
||||
// will be used
|
||||
Name: "multi-param-reinvocation-param-3",
|
||||
Name: "multi-param-reinvocation-param-3",
|
||||
ParameterNotFoundAction: &allow,
|
||||
}, nil),
|
||||
},
|
||||
params: []*corev1.ConfigMap{
|
||||
|
|
@ -1007,7 +1015,7 @@ func TestMutatingAdmissionPolicy_Slow(t *testing.T) {
|
|||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.MutatingAdmissionPolicy, true)
|
||||
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1alpha1.SchemeGroupVersion)}
|
||||
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1beta1.SchemeGroupVersion)}
|
||||
server, err := apiservertesting.StartTestServer(t, nil, flags, framework.SharedEtcd())
|
||||
require.NoError(t, err)
|
||||
defer server.TearDownFn()
|
||||
|
|
@ -1027,12 +1035,12 @@ func TestMutatingAdmissionPolicy_Slow(t *testing.T) {
|
|||
}
|
||||
|
||||
for _, p := range tc.policies {
|
||||
_, err = client.AdmissionregistrationV1alpha1().MutatingAdmissionPolicies().Create(ctx, p, metav1.CreateOptions{FieldManager: "integration-test"})
|
||||
_, err = client.AdmissionregistrationV1beta1().MutatingAdmissionPolicies().Create(ctx, p, metav1.CreateOptions{FieldManager: "integration-test"})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
for _, b := range tc.bindings {
|
||||
_, err = client.AdmissionregistrationV1alpha1().MutatingAdmissionPolicyBindings().Create(ctx, b, metav1.CreateOptions{FieldManager: "integration-test"})
|
||||
_, err = client.AdmissionregistrationV1beta1().MutatingAdmissionPolicyBindings().Create(ctx, b, metav1.CreateOptions{FieldManager: "integration-test"})
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
|
|
@ -1093,7 +1101,7 @@ func TestMutatingAdmissionPolicy_Slow(t *testing.T) {
|
|||
// tested.
|
||||
func Test_MutatingAdmissionPolicy_CustomResources(t *testing.T) {
|
||||
featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, genericfeatures.MutatingAdmissionPolicy, true)
|
||||
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1alpha1.SchemeGroupVersion)}
|
||||
flags := []string{fmt.Sprintf("--runtime-config=%s=true", v1beta1.SchemeGroupVersion)}
|
||||
server, err := apiservertesting.StartTestServer(t, nil, flags, framework.SharedEtcd())
|
||||
etcd.CreateTestCRDs(t, apiextensions.NewForConfigOrDie(server.ClientConfig), false, versionedCustomResourceDefinition())
|
||||
if err != nil {
|
||||
|
|
@ -1111,14 +1119,14 @@ func Test_MutatingAdmissionPolicy_CustomResources(t *testing.T) {
|
|||
ctx, cancel := context.WithCancel(context.Background())
|
||||
t.Cleanup(cancel)
|
||||
|
||||
policy := withMutatingFailurePolicy(v1alpha1.Fail, mutatingPolicy("match-by-match-policy-equivalent", v1alpha1.IfNeededReinvocationPolicy, v1alpha1.MatchResources{
|
||||
ResourceRules: []v1alpha1.NamedRuleWithOperations{
|
||||
policy := withMutatingFailurePolicy(v1beta1.Fail, mutatingPolicy("match-by-match-policy-equivalent", v1beta1.IfNeededReinvocationPolicy, v1beta1.MatchResources{
|
||||
ResourceRules: []v1beta1.NamedRuleWithOperations{
|
||||
{
|
||||
RuleWithOperations: v1alpha1.RuleWithOperations{
|
||||
Operations: []v1alpha1.OperationType{
|
||||
RuleWithOperations: v1beta1.RuleWithOperations{
|
||||
Operations: []v1beta1.OperationType{
|
||||
"*",
|
||||
},
|
||||
Rule: v1alpha1.Rule{
|
||||
Rule: v1beta1.Rule{
|
||||
APIGroups: []string{
|
||||
"awesome.bears.com",
|
||||
},
|
||||
|
|
@ -1133,16 +1141,16 @@ func Test_MutatingAdmissionPolicy_CustomResources(t *testing.T) {
|
|||
},
|
||||
}},
|
||||
nil,
|
||||
v1alpha1.Mutation{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
v1beta1.Mutation{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
Expression: `Object{ metadata: Object.metadata{ labels: {"mutated-panda": "true"} } }`,
|
||||
},
|
||||
},
|
||||
))
|
||||
testID := "policy-equivalent"
|
||||
policy = withMutatingWaitReadyConstraintAndExpression(policy, testID)
|
||||
if _, err := client.AdmissionregistrationV1alpha1().MutatingAdmissionPolicies().Create(ctx, policy, metav1.CreateOptions{}); err != nil {
|
||||
if _, err := client.AdmissionregistrationV1beta1().MutatingAdmissionPolicies().Create(ctx, policy, metav1.CreateOptions{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
|
|
@ -1213,12 +1221,12 @@ func Test_MutatingAdmissionPolicy_CustomResources(t *testing.T) {
|
|||
|
||||
}
|
||||
|
||||
func mutatingPolicy(name string, reinvocationPolicy v1alpha1.ReinvocationPolicyType, matchResources v1alpha1.MatchResources, paramKind *v1alpha1.ParamKind, mutations ...v1alpha1.Mutation) *v1alpha1.MutatingAdmissionPolicy {
|
||||
return &v1alpha1.MutatingAdmissionPolicy{
|
||||
func mutatingPolicy(name string, reinvocationPolicy v1beta1.ReinvocationPolicyType, matchResources v1beta1.MatchResources, paramKind *v1beta1.ParamKind, mutations ...v1beta1.Mutation) *v1beta1.MutatingAdmissionPolicy {
|
||||
return &v1beta1.MutatingAdmissionPolicy{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: name,
|
||||
},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicySpec{
|
||||
Spec: v1beta1.MutatingAdmissionPolicySpec{
|
||||
MatchConstraints: &matchResources,
|
||||
ParamKind: paramKind,
|
||||
Mutations: mutations,
|
||||
|
|
@ -1227,24 +1235,24 @@ func mutatingPolicy(name string, reinvocationPolicy v1alpha1.ReinvocationPolicyT
|
|||
}
|
||||
}
|
||||
|
||||
func withMutatingVariables(variables []v1alpha1.Variable, policy *v1alpha1.MutatingAdmissionPolicy) *v1alpha1.MutatingAdmissionPolicy {
|
||||
func withMutatingVariables(variables []v1beta1.Variable, policy *v1beta1.MutatingAdmissionPolicy) *v1beta1.MutatingAdmissionPolicy {
|
||||
policy.Spec.Variables = variables
|
||||
return policy
|
||||
}
|
||||
|
||||
func withMutatingFailurePolicy(failure v1alpha1.FailurePolicyType, policy *v1alpha1.MutatingAdmissionPolicy) *v1alpha1.MutatingAdmissionPolicy {
|
||||
func withMutatingFailurePolicy(failure v1beta1.FailurePolicyType, policy *v1beta1.MutatingAdmissionPolicy) *v1beta1.MutatingAdmissionPolicy {
|
||||
policy.Spec.FailurePolicy = &failure
|
||||
return policy
|
||||
}
|
||||
|
||||
func withMutatingMatchConditions(matchConditions []v1alpha1.MatchCondition, policy *v1alpha1.MutatingAdmissionPolicy) *v1alpha1.MutatingAdmissionPolicy {
|
||||
func withMutatingMatchConditions(matchConditions []v1beta1.MatchCondition, policy *v1beta1.MutatingAdmissionPolicy) *v1beta1.MutatingAdmissionPolicy {
|
||||
policy.Spec.MatchConditions = matchConditions
|
||||
return policy
|
||||
}
|
||||
|
||||
func withMutatingWaitReadyConstraintAndExpression(policy *v1alpha1.MutatingAdmissionPolicy, testID string) *v1alpha1.MutatingAdmissionPolicy {
|
||||
func withMutatingWaitReadyConstraintAndExpression(policy *v1beta1.MutatingAdmissionPolicy, testID string) *v1beta1.MutatingAdmissionPolicy {
|
||||
policy = policy.DeepCopy()
|
||||
policy.Spec.MatchConstraints.ResourceRules = append(policy.Spec.MatchConstraints.ResourceRules, v1alpha1.NamedRuleWithOperations{
|
||||
policy.Spec.MatchConstraints.ResourceRules = append(policy.Spec.MatchConstraints.ResourceRules, v1beta1.NamedRuleWithOperations{
|
||||
ResourceNames: []string{"test-marker"},
|
||||
RuleWithOperations: admissionregistrationv1.RuleWithOperations{
|
||||
Operations: []admissionregistrationv1.OperationType{
|
||||
|
|
@ -1273,9 +1281,9 @@ func withMutatingWaitReadyConstraintAndExpression(policy *v1alpha1.MutatingAdmis
|
|||
m.ApplyConfiguration.Expression = bypass + m.ApplyConfiguration.Expression
|
||||
}
|
||||
}
|
||||
policy.Spec.Mutations = append([]v1alpha1.Mutation{{
|
||||
PatchType: v1alpha1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1alpha1.ApplyConfiguration{
|
||||
policy.Spec.Mutations = append([]v1beta1.Mutation{{
|
||||
PatchType: v1beta1.PatchTypeApplyConfiguration,
|
||||
ApplyConfiguration: &v1beta1.ApplyConfiguration{
|
||||
// Only mutate mutation-markers.
|
||||
Expression: fmt.Sprintf(`object.metadata.?labels["mutation-marker"] == optional.of("%v") ? Object{ metadata: Object.metadata{ labels: {"mutated":"%v"}}}: Object{}`, testID, testID),
|
||||
},
|
||||
|
|
@ -1283,12 +1291,12 @@ func withMutatingWaitReadyConstraintAndExpression(policy *v1alpha1.MutatingAdmis
|
|||
return policy
|
||||
}
|
||||
|
||||
func mutatingBinding(policyName string, paramRef *v1alpha1.ParamRef, matchResources *v1alpha1.MatchResources) *v1alpha1.MutatingAdmissionPolicyBinding {
|
||||
return &v1alpha1.MutatingAdmissionPolicyBinding{
|
||||
func mutatingBinding(policyName string, paramRef *v1beta1.ParamRef, matchResources *v1beta1.MatchResources) *v1beta1.MutatingAdmissionPolicyBinding {
|
||||
return &v1beta1.MutatingAdmissionPolicyBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: policyName + "-binding-" + string(uuid.NewUUID()),
|
||||
},
|
||||
Spec: v1alpha1.MutatingAdmissionPolicyBindingSpec{
|
||||
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
|
||||
PolicyName: policyName,
|
||||
ParamRef: paramRef,
|
||||
MatchResources: matchResources,
|
||||
|
|
@ -1296,12 +1304,12 @@ func mutatingBinding(policyName string, paramRef *v1alpha1.ParamRef, matchResour
|
|||
}
|
||||
}
|
||||
|
||||
func createAndWaitReadyMutating(ctx context.Context, t *testing.T, client kubernetes.Interface, binding *v1alpha1.MutatingAdmissionPolicyBinding, testID string) error {
|
||||
func createAndWaitReadyMutating(ctx context.Context, t *testing.T, client kubernetes.Interface, binding *v1beta1.MutatingAdmissionPolicyBinding, testID string) error {
|
||||
return createAndWaitReadyNamespacedWithWarnHandlerMutating(ctx, t, client, binding, "default", testID)
|
||||
}
|
||||
|
||||
func createAndWaitReadyNamespacedWithWarnHandlerMutating(ctx context.Context, t *testing.T, client kubernetes.Interface, binding *v1alpha1.MutatingAdmissionPolicyBinding, ns string, testID string) error {
|
||||
_, err := client.AdmissionregistrationV1alpha1().MutatingAdmissionPolicyBindings().Create(ctx, binding, metav1.CreateOptions{})
|
||||
func createAndWaitReadyNamespacedWithWarnHandlerMutating(ctx context.Context, t *testing.T, client kubernetes.Interface, binding *v1beta1.MutatingAdmissionPolicyBinding, ns string, testID string) error {
|
||||
_, err := client.AdmissionregistrationV1beta1().MutatingAdmissionPolicyBindings().Create(ctx, binding, metav1.CreateOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -1326,14 +1334,14 @@ func createAndWaitReadyNamespacedWithWarnHandlerMutating(ctx context.Context, t
|
|||
return nil
|
||||
}
|
||||
|
||||
func cleanupMutatingPolicy(ctx context.Context, t *testing.T, client kubernetes.Interface, policies []*v1alpha1.MutatingAdmissionPolicy, bindings []*v1alpha1.MutatingAdmissionPolicyBinding, params []*corev1.ConfigMap) error {
|
||||
func cleanupMutatingPolicy(ctx context.Context, t *testing.T, client kubernetes.Interface, policies []*v1beta1.MutatingAdmissionPolicy, bindings []*v1beta1.MutatingAdmissionPolicyBinding, params []*corev1.ConfigMap) error {
|
||||
for _, policy := range policies {
|
||||
if err := client.AdmissionregistrationV1alpha1().MutatingAdmissionPolicies().Delete(ctx, policy.Name, metav1.DeleteOptions{}); err != nil {
|
||||
if err := client.AdmissionregistrationV1beta1().MutatingAdmissionPolicies().Delete(ctx, policy.Name, metav1.DeleteOptions{}); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if waitErr := wait.PollUntilContextTimeout(ctx, 100*time.Millisecond, time.Minute, true, func(ctx context.Context) (bool, error) {
|
||||
_, err := client.AdmissionregistrationV1alpha1().MutatingAdmissionPolicies().Get(ctx, policy.Name, metav1.GetOptions{})
|
||||
_, err := client.AdmissionregistrationV1beta1().MutatingAdmissionPolicies().Get(ctx, policy.Name, metav1.GetOptions{})
|
||||
if apierrors.IsNotFound(err) {
|
||||
return true, nil
|
||||
}
|
||||
|
|
@ -1344,13 +1352,13 @@ func cleanupMutatingPolicy(ctx context.Context, t *testing.T, client kubernetes.
|
|||
}
|
||||
|
||||
for _, binding := range bindings {
|
||||
err := client.AdmissionregistrationV1alpha1().MutatingAdmissionPolicyBindings().Delete(ctx, binding.Name, metav1.DeleteOptions{})
|
||||
err := client.AdmissionregistrationV1beta1().MutatingAdmissionPolicyBindings().Delete(ctx, binding.Name, metav1.DeleteOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if waitErr := wait.PollUntilContextTimeout(ctx, 100*time.Millisecond, time.Minute, true, func(ctx context.Context) (bool, error) {
|
||||
_, err := client.AdmissionregistrationV1alpha1().MutatingAdmissionPolicyBindings().Get(ctx, binding.Name, metav1.GetOptions{})
|
||||
_, err := client.AdmissionregistrationV1beta1().MutatingAdmissionPolicyBindings().Get(ctx, binding.Name, metav1.GetOptions{})
|
||||
if apierrors.IsNotFound(err) {
|
||||
return true, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -483,18 +483,32 @@ func GetEtcdStorageDataForNamespaceServedAt(namespace string, v string, isEmulat
|
|||
IntroducedVersion: "1.28",
|
||||
RemovedVersion: "1.34",
|
||||
},
|
||||
gvr("admissionregistration.k8s.io", "v1beta1", "mutatingadmissionpolicies"): {
|
||||
Stub: `{"metadata":{"name":"map1b1"},"spec":{"paramKind":{"apiVersion":"test.example.com/v1","kind":"Example"},"matchConstraints":{"resourceRules": [{"resourceNames": ["fakeName"], "apiGroups":["apps"],"apiVersions":["v1"],"operations":["CREATE", "UPDATE"], "resources":["deployments"]}]},"reinvocationPolicy": "IfNeeded","mutations":[{"applyConfiguration": {"expression":"Object{metadata: Object.metadata{labels: {'example':'true'}}}"}, "patchType":"ApplyConfiguration"}]}}`,
|
||||
ExpectedEtcdPath: "/registry/mutatingadmissionpolicies/map1b1",
|
||||
IntroducedVersion: "1.34",
|
||||
RemovedVersion: "1.40",
|
||||
},
|
||||
gvr("admissionregistration.k8s.io", "v1beta1", "mutatingadmissionpolicybindings"): {
|
||||
Stub: `{"metadata":{"name":"mpb1b1"},"spec":{"policyName":"replicalimit-policy.example.com","paramRef":{"name":"replica-limit-test.example.com", "parameterNotFoundAction": "Allow"}}}`,
|
||||
ExpectedEtcdPath: "/registry/mutatingadmissionpolicybindings/mpb1b1",
|
||||
IntroducedVersion: "1.34",
|
||||
RemovedVersion: "1.40",
|
||||
},
|
||||
// --
|
||||
|
||||
// k8s.io/kubernetes/pkg/apis/admissionregistration/v1alpha1
|
||||
gvr("admissionregistration.k8s.io", "v1alpha1", "mutatingadmissionpolicies"): {
|
||||
Stub: `{"metadata":{"name":"map1"},"spec":{"paramKind":{"apiVersion":"test.example.com/v1","kind":"Example"},"matchConstraints":{"resourceRules": [{"resourceNames": ["fakeName"], "apiGroups":["apps"],"apiVersions":["v1"],"operations":["CREATE", "UPDATE"], "resources":["deployments"]}]},"reinvocationPolicy": "IfNeeded","mutations":[{"applyConfiguration": {"expression":"Object{metadata: Object.metadata{labels: {'example':'true'}}}"}, "patchType":"ApplyConfiguration"}]}}`,
|
||||
ExpectedEtcdPath: "/registry/mutatingadmissionpolicies/map1",
|
||||
ExpectedGVK: gvkP("admissionregistration.k8s.io", "v1beta1", "MutatingAdmissionPolicy"),
|
||||
IntroducedVersion: "1.32",
|
||||
RemovedVersion: "1.38",
|
||||
},
|
||||
gvr("admissionregistration.k8s.io", "v1alpha1", "mutatingadmissionpolicybindings"): {
|
||||
Stub: `{"metadata":{"name":"mpb1"},"spec":{"policyName":"replicalimit-policy.example.com","paramRef":{"name":"replica-limit-test.example.com"}}}`,
|
||||
Stub: `{"metadata":{"name":"mpb1"},"spec":{"policyName":"replicalimit-policy.example.com","paramRef":{"name":"replica-limit-test.example.com", "parameterNotFoundAction": "Allow"}}}`,
|
||||
ExpectedEtcdPath: "/registry/mutatingadmissionpolicybindings/mpb1",
|
||||
ExpectedGVK: gvkP("admissionregistration.k8s.io", "v1beta1", "MutatingAdmissionPolicyBinding"),
|
||||
IntroducedVersion: "1.32",
|
||||
RemovedVersion: "1.38",
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in a new issue