promote MutatingAdmissionPolicy to v1: update plugin implementation

- Update MutatingAdmissionPolicy plugin to use v1 types.
This commit is contained in:
Lalit Chauhan
2026-01-05 21:11:05 +00:00
committed by Your Name
parent b7c4f21d41
commit 0d5bdaedc9
13 changed files with 720 additions and 686 deletions

View File

@@ -2006,6 +2006,7 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate
genericfeatures.MutatingAdmissionPolicy: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.34"), Default: false, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.36"), Default: true, PreRelease: featuregate.GA},
},
genericfeatures.OpenAPIEnums: {

View File

@@ -18,7 +18,6 @@ package mutating
import (
v1 "k8s.io/api/admissionregistration/v1"
"k8s.io/api/admissionregistration/v1beta1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apiserver/pkg/admission/plugin/policy/generic"
)
@@ -59,19 +58,11 @@ func (v *mutatingAdmissionPolicyAccessor) GetParamKind() *v1.ParamKind {
}
func (v *mutatingAdmissionPolicyAccessor) GetMatchConstraints() *v1.MatchResources {
return convertV1alpha1ResourceRulesToV1(v.Spec.MatchConstraints)
return v.Spec.MatchConstraints
}
func (v *mutatingAdmissionPolicyAccessor) GetFailurePolicy() *v1.FailurePolicyType {
return toV1FailurePolicy(v.Spec.FailurePolicy)
}
func toV1FailurePolicy(failurePolicy *v1beta1.FailurePolicyType) *v1.FailurePolicyType {
if failurePolicy == nil {
return nil
}
fp := v1.FailurePolicyType(*failurePolicy)
return &fp
return v.Spec.FailurePolicy
}
type mutatingAdmissionPolicyBindingAccessor struct {
@@ -94,7 +85,7 @@ func (v *mutatingAdmissionPolicyBindingAccessor) GetPolicyName() types.Namespace
}
func (v *mutatingAdmissionPolicyBindingAccessor) GetMatchResources() *v1.MatchResources {
return convertV1alpha1ResourceRulesToV1(v.Spec.MatchResources)
return v.Spec.MatchResources
}
func (v *mutatingAdmissionPolicyBindingAccessor) GetParamRef() *v1.ParamRef {
@@ -115,30 +106,3 @@ func (v *mutatingAdmissionPolicyBindingAccessor) GetParamRef() *v1.ParamRef {
ParameterNotFoundAction: nfa,
}
}
func convertV1alpha1ResourceRulesToV1(mc *v1beta1.MatchResources) *v1.MatchResources {
if mc == nil {
return nil
}
var res v1.MatchResources
res.NamespaceSelector = mc.NamespaceSelector
res.ObjectSelector = mc.ObjectSelector
for _, ex := range mc.ExcludeResourceRules {
res.ExcludeResourceRules = append(res.ExcludeResourceRules, v1.NamedRuleWithOperations{
ResourceNames: ex.ResourceNames,
RuleWithOperations: ex.RuleWithOperations,
})
}
for _, ex := range mc.ResourceRules {
res.ResourceRules = append(res.ResourceRules, v1.NamedRuleWithOperations{
ResourceNames: ex.ResourceNames,
RuleWithOperations: ex.RuleWithOperations,
})
}
if mc.MatchPolicy != nil {
mp := v1.MatchPolicyType(*mc.MatchPolicy)
res.MatchPolicy = &mp
}
return &res
}

View File

@@ -19,9 +19,10 @@ package mutating
import (
"fmt"
"k8s.io/api/admissionregistration/v1beta1"
"k8s.io/api/admissionregistration/v1"
plugincel "k8s.io/apiserver/pkg/admission/plugin/cel"
"k8s.io/apiserver/pkg/admission/plugin/policy/mutating/patch"
"k8s.io/apiserver/pkg/admission/plugin/policy/validating"
"k8s.io/apiserver/pkg/admission/plugin/webhook/matchconditions"
apiservercel "k8s.io/apiserver/pkg/cel"
"k8s.io/apiserver/pkg/cel/environment"
@@ -32,7 +33,7 @@ import (
//
// Each individual mutation is compiled into MutationEvaluationFunc and
// returned is a PolicyEvaluator in the same order as the mutations appeared in the policy.
func compilePolicy(policy *Policy) PolicyEvaluator {
func compilePolicy(policy *v1.MutatingAdmissionPolicy) PolicyEvaluator {
opts := plugincel.OptionalVariableDeclarations{HasParams: policy.Spec.ParamKind != nil, HasAuthorizer: true}
compiler, err := plugincel.NewCompositedCompiler(environment.MustBaseEnvSet(environment.DefaultCompatibilityVersion()))
if err != nil {
@@ -43,7 +44,7 @@ func compilePolicy(policy *Policy) PolicyEvaluator {
}
// Compile and store variables
compiler.CompileAndStoreVariables(convertv1alpha1Variables(policy.Spec.Variables), opts, environment.StoredExpressions)
compiler.CompileAndStoreVariables(convertV1Variables(policy.Spec.Variables), opts, environment.StoredExpressions)
// Compile matchers
var matcher matchconditions.Matcher = nil
@@ -53,7 +54,7 @@ func compilePolicy(policy *Policy) PolicyEvaluator {
for i := range matchConditions {
matchExpressionAccessors[i] = (*matchconditions.MatchCondition)(&matchConditions[i])
}
matcher = matchconditions.NewMatcher(compiler.CompileCondition(matchExpressionAccessors, opts, environment.StoredExpressions), toV1FailurePolicy(policy.Spec.FailurePolicy), "policy", "validate", policy.Name)
matcher = matchconditions.NewMatcher(compiler.CompileCondition(matchExpressionAccessors, opts, environment.StoredExpressions), policy.Spec.FailurePolicy, "policy", "validate", policy.Name)
}
// Compiler patchers
@@ -62,13 +63,13 @@ func compilePolicy(policy *Policy) PolicyEvaluator {
patchOptions.HasPatchTypes = true
for _, m := range policy.Spec.Mutations {
switch m.PatchType {
case v1beta1.PatchTypeJSONPatch:
case v1.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 v1beta1.PatchTypeApplyConfiguration:
case v1.PatchTypeApplyConfiguration:
if m.ApplyConfiguration != nil {
accessor := &patch.ApplyConfigurationCondition{Expression: m.ApplyConfiguration.Expression}
compileResult := compiler.CompileMutatingEvaluator(accessor, patchOptions, environment.StoredExpressions)
@@ -79,3 +80,17 @@ func compilePolicy(policy *Policy) PolicyEvaluator {
return PolicyEvaluator{Matcher: matcher, Mutators: patchers, CompositedCompiler: compiler}
}
func convertV1Variables(variables []v1.Variable) []plugincel.NamedExpressionAccessor {
if variables == nil {
return nil
}
res := make([]plugincel.NamedExpressionAccessor, len(variables))
for i, v := range variables {
res[i] = &validating.Variable{
Name: v.Name,
Expression: v.Expression,
}
}
return res
}

View File

@@ -24,7 +24,7 @@ import (
"github.com/google/go-cmp/cmp"
"k8s.io/api/admissionregistration/v1beta1"
v1 "k8s.io/api/admissionregistration/v1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/equality"
@@ -50,7 +50,7 @@ func TestCompilation(t *testing.T) {
deploymentGVK := schema.GroupVersionKind{Group: "apps", Version: "v1", Kind: "Deployment"}
testCases := []struct {
name string
policy *Policy
policy *v1.MutatingAdmissionPolicy
gvr schema.GroupVersionResource
object runtime.Object
oldObject runtime.Object
@@ -61,9 +61,9 @@ func TestCompilation(t *testing.T) {
}{
{
name: "applyConfiguration then jsonPatch",
policy: mutations(policy("d1"), v1beta1.Mutation{
PatchType: v1beta1.PatchTypeApplyConfiguration,
ApplyConfiguration: &v1beta1.ApplyConfiguration{
policy: mutations(policy("d1"), v1.Mutation{
PatchType: v1.PatchTypeApplyConfiguration,
ApplyConfiguration: &v1.ApplyConfiguration{
Expression: `Object{
spec: Object.spec{
replicas: object.spec.replicas + 100
@@ -71,9 +71,9 @@ func TestCompilation(t *testing.T) {
}`,
},
},
v1beta1.Mutation{
PatchType: v1beta1.PatchTypeJSONPatch,
JSONPatch: &v1beta1.JSONPatch{
v1.Mutation{
PatchType: v1.PatchTypeJSONPatch,
JSONPatch: &v1.JSONPatch{
Expression: `[
JSONPatch{op: "replace", path: "/spec/replicas", value: object.spec.replicas + 10}
]`,
@@ -86,17 +86,17 @@ func TestCompilation(t *testing.T) {
{
name: "jsonPatch then applyConfiguration",
policy: mutations(policy("d1"),
v1beta1.Mutation{
PatchType: v1beta1.PatchTypeJSONPatch,
JSONPatch: &v1beta1.JSONPatch{
v1.Mutation{
PatchType: v1.PatchTypeJSONPatch,
JSONPatch: &v1.JSONPatch{
Expression: `[
JSONPatch{op: "replace", path: "/spec/replicas", value: object.spec.replicas + 10}
]`,
},
},
v1beta1.Mutation{
PatchType: v1beta1.PatchTypeApplyConfiguration,
ApplyConfiguration: &v1beta1.ApplyConfiguration{
v1.Mutation{
PatchType: v1.PatchTypeApplyConfiguration,
ApplyConfiguration: &v1.ApplyConfiguration{
Expression: `Object{
spec: Object.spec{
replicas: object.spec.replicas + 100
@@ -110,7 +110,7 @@ func TestCompilation(t *testing.T) {
},
{
name: "jsonPatch with variable",
policy: jsonPatches(variables(policy("d1"), v1beta1.Variable{Name: "desired", Expression: "10"}), v1beta1.JSONPatch{
policy: jsonPatches(variables(policy("d1"), v1.Variable{Name: "desired", Expression: "10"}), v1.JSONPatch{
Expression: `[
JSONPatch{op: "replace", path: "/spec/replicas", value: variables.desired + 1},
]`,
@@ -121,7 +121,7 @@ func TestCompilation(t *testing.T) {
},
{
name: "apply configuration with variable",
policy: applyConfigurations(variables(policy("d1"), v1beta1.Variable{Name: "desired", Expression: "10"}),
policy: applyConfigurations(variables(policy("d1"), v1.Variable{Name: "desired", Expression: "10"}),
`Object{
spec: Object.spec{
replicas: variables.desired + 1
@@ -138,7 +138,7 @@ func TestCompilation(t *testing.T) {
spec: Object.spec{
replicas: int(params.data['k1'])
}
}`), &v1beta1.ParamKind{Kind: "ConfigMap", APIVersion: "v1"}),
}`), &v1.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)}},
@@ -146,7 +146,7 @@ func TestCompilation(t *testing.T) {
},
{
name: "jsonPatch with excessive cost",
policy: jsonPatches(variables(policy("d1"), v1beta1.Variable{Name: "list", Expression: "[0,1,2,3,4,5,6,7,8,9]"}), v1beta1.JSONPatch{
policy: jsonPatches(variables(policy("d1"), v1.Variable{Name: "list", Expression: "[0,1,2,3,4,5,6,7,8,9]"}), v1.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
@@ -164,14 +164,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
}
}`), v1beta1.Variable{Name: "list", Expression: "[0,1,2,3,4,5,6,7,8,9]"}),
}`), v1.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"), v1beta1.JSONPatch{
policy: jsonPatches(policy("d1"), v1.JSONPatch{
Expression: `[
JSONPatch{op: "replace", path: "/spec/replicas",
value: request.kind.group == 'apps' && request.kind.version == 'v1' && request.kind.kind == 'Deployment' ? 10 : 0
@@ -183,7 +183,7 @@ func TestCompilation(t *testing.T) {
},
{
name: "namespace request variable",
policy: jsonPatches(policy("d1"), v1beta1.JSONPatch{
policy: jsonPatches(policy("d1"), v1.JSONPatch{
Expression: `[
JSONPatch{op: "replace", path: "/spec/replicas",
value: namespaceObject.metadata.name == 'ns1' ? 10 : 0
@@ -196,7 +196,7 @@ func TestCompilation(t *testing.T) {
},
{
name: "authorizer check",
policy: jsonPatches(policy("d1"), v1beta1.JSONPatch{
policy: jsonPatches(policy("d1"), v1.JSONPatch{
Expression: `[
JSONPatch{op: "replace", path: "/spec/replicas",
value: authorizer.group('').resource('endpoints').check('create').allowed() ? 10 : 0
@@ -209,7 +209,7 @@ func TestCompilation(t *testing.T) {
},
{
name: "object type has field access",
policy: jsonPatches(policy("d1"), v1beta1.JSONPatch{
policy: jsonPatches(policy("d1"), v1.JSONPatch{
Expression: `[
JSONPatch{
op: "add", path: "/metadata/labels",
@@ -227,7 +227,7 @@ func TestCompilation(t *testing.T) {
},
{
name: "object type has field testing",
policy: jsonPatches(policy("d1"), v1beta1.JSONPatch{
policy: jsonPatches(policy("d1"), v1.JSONPatch{
Expression: `[
JSONPatch{
op: "add", path: "/metadata/labels",
@@ -247,7 +247,7 @@ func TestCompilation(t *testing.T) {
},
{
name: "object type equality",
policy: jsonPatches(policy("d1"), v1beta1.JSONPatch{
policy: jsonPatches(policy("d1"), v1.JSONPatch{
Expression: `[
JSONPatch{
op: "add", path: "/metadata/labels",
@@ -275,7 +275,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"), v1beta1.JSONPatch{
policy: jsonPatches(policy("d1"), v1.JSONPatch{
Expression: `[
JSONPatch{
op: "add", path: "/spec",
@@ -401,52 +401,52 @@ func TestCompilation(t *testing.T) {
}
}
func policy(name string) *v1beta1.MutatingAdmissionPolicy {
return &v1beta1.MutatingAdmissionPolicy{
func policy(name string) *v1.MutatingAdmissionPolicy {
return &v1.MutatingAdmissionPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: name,
},
Spec: v1beta1.MutatingAdmissionPolicySpec{},
Spec: v1.MutatingAdmissionPolicySpec{},
}
}
func variables(policy *v1beta1.MutatingAdmissionPolicy, variables ...v1beta1.Variable) *v1beta1.MutatingAdmissionPolicy {
func variables(policy *v1.MutatingAdmissionPolicy, variables ...v1.Variable) *v1.MutatingAdmissionPolicy {
policy.Spec.Variables = append(policy.Spec.Variables, variables...)
return policy
}
func jsonPatches(policy *v1beta1.MutatingAdmissionPolicy, jsonPatches ...v1beta1.JSONPatch) *v1beta1.MutatingAdmissionPolicy {
func jsonPatches(policy *v1.MutatingAdmissionPolicy, jsonPatches ...v1.JSONPatch) *v1.MutatingAdmissionPolicy {
for _, jsonPatch := range jsonPatches {
policy.Spec.Mutations = append(policy.Spec.Mutations, v1beta1.Mutation{
policy.Spec.Mutations = append(policy.Spec.Mutations, v1.Mutation{
JSONPatch: &jsonPatch,
PatchType: v1beta1.PatchTypeJSONPatch,
PatchType: v1.PatchTypeJSONPatch,
})
}
return policy
}
func applyConfigurations(policy *v1beta1.MutatingAdmissionPolicy, expressions ...string) *v1beta1.MutatingAdmissionPolicy {
func applyConfigurations(policy *v1.MutatingAdmissionPolicy, expressions ...string) *v1.MutatingAdmissionPolicy {
for _, expression := range expressions {
policy.Spec.Mutations = append(policy.Spec.Mutations, v1beta1.Mutation{
ApplyConfiguration: &v1beta1.ApplyConfiguration{Expression: expression},
PatchType: v1beta1.PatchTypeApplyConfiguration,
policy.Spec.Mutations = append(policy.Spec.Mutations, v1.Mutation{
ApplyConfiguration: &v1.ApplyConfiguration{Expression: expression},
PatchType: v1.PatchTypeApplyConfiguration,
})
}
return policy
}
func paramKind(policy *v1beta1.MutatingAdmissionPolicy, paramKind *v1beta1.ParamKind) *v1beta1.MutatingAdmissionPolicy {
func paramKind(policy *v1.MutatingAdmissionPolicy, paramKind *v1.ParamKind) *v1.MutatingAdmissionPolicy {
policy.Spec.ParamKind = paramKind
return policy
}
func mutations(policy *v1beta1.MutatingAdmissionPolicy, mutations ...v1beta1.Mutation) *v1beta1.MutatingAdmissionPolicy {
func mutations(policy *v1.MutatingAdmissionPolicy, mutations ...v1.Mutation) *v1.MutatingAdmissionPolicy {
policy.Spec.Mutations = append(policy.Spec.Mutations, mutations...)
return policy
}
func matchConstraints(policy *v1beta1.MutatingAdmissionPolicy, matchConstraints *v1beta1.MatchResources) *v1beta1.MutatingAdmissionPolicy {
func matchConstraints(policy *v1.MutatingAdmissionPolicy, matchConstraints *v1.MatchResources) *v1.MutatingAdmissionPolicy {
policy.Spec.MatchConstraints = matchConstraints
return policy
}

View File

@@ -22,7 +22,7 @@ import (
"fmt"
"time"
"k8s.io/api/admissionregistration/v1beta1"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
v1 "k8s.io/api/core/v1"
apiequality "k8s.io/apimachinery/pkg/api/equality"
k8serrors "k8s.io/apimachinery/pkg/api/errors"
@@ -49,7 +49,7 @@ func NewDispatcher(a authorizer.Authorizer, m *matching.Matcher, tcm patch.TypeC
authz: a,
typeConverterManager: tcm,
}
res.Dispatcher = generic.NewPolicyDispatcher(
res.Dispatcher = generic.NewPolicyDispatcher[*Policy, *PolicyBinding, PolicyEvaluator](
NewMutatingAdmissionPolicyAccessor,
NewMutatingAdmissionPolicyBindingAccessor,
m,
@@ -210,7 +210,7 @@ func (d *dispatcher) dispatchInvocations(
policyReinvokeCtx.RequireReinvokingPreviouslyInvokedPlugins()
reinvokeCtx.SetShouldReinvoke()
}
if invocation.Policy.Spec.ReinvocationPolicy == v1beta1.IfNeededReinvocationPolicy {
if invocation.Policy.Spec.ReinvocationPolicy == admissionregistrationv1.IfNeededReinvocationPolicy {
policyReinvokeCtx.AddReinvocablePolicyToPreviouslyInvoked(invocationKey)
}
}

View File

@@ -23,7 +23,6 @@ import (
"time"
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
"k8s.io/api/admissionregistration/v1beta1"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/equality"
@@ -33,7 +32,6 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/admission"
"k8s.io/apiserver/pkg/admission/plugin/policy/generic"
"k8s.io/apiserver/pkg/admission/plugin/policy/matching"
"k8s.io/apiserver/pkg/admission/plugin/policy/mutating/patch"
"k8s.io/client-go/informers"
@@ -75,16 +73,16 @@ func TestDispatcher(t *testing.T) {
},
},
}},
policyHooks: []generic.PolicyHook[*Policy, *PolicyBinding, PolicyEvaluator]{
policyHooks: []PolicyHook{
{
Policy: mutations(matchConstraints(policy("policy1"), &v1beta1.MatchResources{
MatchPolicy: ptr.To(v1beta1.Equivalent),
Policy: mutations(matchConstraints(policy("policy1"), &admissionregistrationv1.MatchResources{
MatchPolicy: ptr.To(admissionregistrationv1.Equivalent),
NamespaceSelector: &metav1.LabelSelector{},
ObjectSelector: &metav1.LabelSelector{},
ResourceRules: []v1beta1.NamedRuleWithOperations{
ResourceRules: []admissionregistrationv1.NamedRuleWithOperations{
{
RuleWithOperations: v1beta1.RuleWithOperations{
Rule: v1beta1.Rule{
RuleWithOperations: admissionregistrationv1.RuleWithOperations{
Rule: admissionregistrationv1.Rule{
APIGroups: []string{"apps"},
APIVersions: []string{"v1"},
Resources: []string{"deployments"},
@@ -93,18 +91,18 @@ func TestDispatcher(t *testing.T) {
},
},
},
}), v1beta1.Mutation{
PatchType: v1beta1.PatchTypeApplyConfiguration,
ApplyConfiguration: &v1beta1.ApplyConfiguration{
}), admissionregistrationv1.Mutation{
PatchType: admissionregistrationv1.PatchTypeApplyConfiguration,
ApplyConfiguration: &admissionregistrationv1.ApplyConfiguration{
Expression: `Object{
spec: Object.spec{
replicas: object.spec.replicas + 100
}
}`,
}}),
Bindings: []*PolicyBinding{{
Bindings: []*admissionregistrationv1.MutatingAdmissionPolicyBinding{{
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
Spec: admissionregistrationv1.MutatingAdmissionPolicyBindingSpec{
PolicyName: "policy1",
},
}},
@@ -166,16 +164,16 @@ func TestDispatcher(t *testing.T) {
},
},
},
policyHooks: []generic.PolicyHook[*Policy, *PolicyBinding, PolicyEvaluator]{
policyHooks: []PolicyHook{
{
Policy: paramKind(mutations(matchConstraints(policy("policy1"), &v1beta1.MatchResources{
MatchPolicy: ptr.To(v1beta1.Equivalent),
Policy: paramKind(mutations(matchConstraints(policy("policy1"), &admissionregistrationv1.MatchResources{
MatchPolicy: ptr.To(admissionregistrationv1.Equivalent),
NamespaceSelector: &metav1.LabelSelector{},
ObjectSelector: &metav1.LabelSelector{},
ResourceRules: []v1beta1.NamedRuleWithOperations{
ResourceRules: []admissionregistrationv1.NamedRuleWithOperations{
{
RuleWithOperations: v1beta1.RuleWithOperations{
Rule: v1beta1.Rule{
RuleWithOperations: admissionregistrationv1.RuleWithOperations{
Rule: admissionregistrationv1.Rule{
APIGroups: []string{"apps"},
APIVersions: []string{"v1"},
Resources: []string{"deployments"},
@@ -184,24 +182,24 @@ func TestDispatcher(t *testing.T) {
},
},
}}),
v1beta1.Mutation{
PatchType: v1beta1.PatchTypeApplyConfiguration,
ApplyConfiguration: &v1beta1.ApplyConfiguration{
admissionregistrationv1.Mutation{
PatchType: admissionregistrationv1.PatchTypeApplyConfiguration,
ApplyConfiguration: &admissionregistrationv1.ApplyConfiguration{
Expression: `Object{
spec: Object.spec{
replicas: object.spec.replicas + int(params.data['key'])
}
}`,
}}),
&v1beta1.ParamKind{
&admissionregistrationv1.ParamKind{
APIVersion: "v1",
Kind: "ConfigMap",
}),
Bindings: []*PolicyBinding{{
Bindings: []*admissionregistrationv1.MutatingAdmissionPolicyBinding{{
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
Spec: admissionregistrationv1.MutatingAdmissionPolicyBindingSpec{
PolicyName: "policy1",
ParamRef: &v1beta1.ParamRef{Name: "cm1", Namespace: "default"},
ParamRef: &admissionregistrationv1.ParamRef{Name: "cm1", Namespace: "default"},
},
}},
},
@@ -246,16 +244,16 @@ func TestDispatcher(t *testing.T) {
Type: appsv1.RollingUpdateDeploymentStrategyType,
},
}},
policyHooks: []generic.PolicyHook[*Policy, *PolicyBinding, PolicyEvaluator]{
policyHooks: []PolicyHook{
{
Policy: mutations(matchConstraints(policy("policy1"), &v1beta1.MatchResources{
MatchPolicy: ptr.To(v1beta1.Equivalent),
Policy: mutations(matchConstraints(policy("policy1"), &admissionregistrationv1.MatchResources{
MatchPolicy: ptr.To(admissionregistrationv1.Equivalent),
NamespaceSelector: &metav1.LabelSelector{},
ObjectSelector: &metav1.LabelSelector{},
ResourceRules: []v1beta1.NamedRuleWithOperations{
ResourceRules: []admissionregistrationv1.NamedRuleWithOperations{
{
RuleWithOperations: v1beta1.RuleWithOperations{
Rule: v1beta1.Rule{
RuleWithOperations: admissionregistrationv1.RuleWithOperations{
Rule: admissionregistrationv1.Rule{
APIGroups: []string{"apps"},
APIVersions: []string{"v1"},
Resources: []string{"deployments"},
@@ -264,31 +262,31 @@ func TestDispatcher(t *testing.T) {
},
},
},
}), v1beta1.Mutation{
PatchType: v1beta1.PatchTypeApplyConfiguration,
ApplyConfiguration: &v1beta1.ApplyConfiguration{
}), admissionregistrationv1.Mutation{
PatchType: admissionregistrationv1.PatchTypeApplyConfiguration,
ApplyConfiguration: &admissionregistrationv1.ApplyConfiguration{
Expression: `Object{
metadata: Object.metadata{
labels: {"policy1": string(int(object.?metadata.labels["count"].orValue("1")) + 1)}
}
}`,
}}),
Bindings: []*PolicyBinding{{
Bindings: []*admissionregistrationv1.MutatingAdmissionPolicyBinding{{
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
Spec: admissionregistrationv1.MutatingAdmissionPolicyBindingSpec{
PolicyName: "policy1",
},
}},
},
{
Policy: mutations(matchConstraints(policy("policy2"), &v1beta1.MatchResources{
MatchPolicy: ptr.To(v1beta1.Equivalent),
Policy: mutations(matchConstraints(policy("policy2"), &admissionregistrationv1.MatchResources{
MatchPolicy: ptr.To(admissionregistrationv1.Equivalent),
NamespaceSelector: &metav1.LabelSelector{},
ObjectSelector: &metav1.LabelSelector{},
ResourceRules: []v1beta1.NamedRuleWithOperations{
ResourceRules: []admissionregistrationv1.NamedRuleWithOperations{
{
RuleWithOperations: v1beta1.RuleWithOperations{
Rule: v1beta1.Rule{
RuleWithOperations: admissionregistrationv1.RuleWithOperations{
Rule: admissionregistrationv1.Rule{
APIGroups: []string{"apps"},
APIVersions: []string{"v1"},
Resources: []string{"deployments"},
@@ -297,18 +295,18 @@ func TestDispatcher(t *testing.T) {
},
},
},
}), v1beta1.Mutation{
PatchType: v1beta1.PatchTypeApplyConfiguration,
ApplyConfiguration: &v1beta1.ApplyConfiguration{
}), admissionregistrationv1.Mutation{
PatchType: admissionregistrationv1.PatchTypeApplyConfiguration,
ApplyConfiguration: &admissionregistrationv1.ApplyConfiguration{
Expression: `Object{
metadata: Object.metadata{
labels: {"policy2": string(int(object.?metadata.labels["count"].orValue("1")) + 1)}
}
}`,
}}),
Bindings: []*PolicyBinding{{
Bindings: []*admissionregistrationv1.MutatingAdmissionPolicyBinding{{
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
Spec: admissionregistrationv1.MutatingAdmissionPolicyBindingSpec{
PolicyName: "policy2",
},
}},
@@ -357,21 +355,21 @@ func TestDispatcher(t *testing.T) {
Type: appsv1.RollingUpdateDeploymentStrategyType,
},
}},
policyHooks: []generic.PolicyHook[*Policy, *PolicyBinding, PolicyEvaluator]{
policyHooks: []PolicyHook{
{
Policy: &v1beta1.MutatingAdmissionPolicy{
Policy: &admissionregistrationv1.MutatingAdmissionPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "policy1",
},
Spec: v1beta1.MutatingAdmissionPolicySpec{
MatchConstraints: &v1beta1.MatchResources{
MatchPolicy: ptr.To(v1beta1.Equivalent),
Spec: admissionregistrationv1.MutatingAdmissionPolicySpec{
MatchConstraints: &admissionregistrationv1.MatchResources{
MatchPolicy: ptr.To(admissionregistrationv1.Equivalent),
NamespaceSelector: &metav1.LabelSelector{},
ObjectSelector: &metav1.LabelSelector{},
ResourceRules: []v1beta1.NamedRuleWithOperations{
ResourceRules: []admissionregistrationv1.NamedRuleWithOperations{
{
RuleWithOperations: v1beta1.RuleWithOperations{
Rule: v1beta1.Rule{
RuleWithOperations: admissionregistrationv1.RuleWithOperations{
Rule: admissionregistrationv1.Rule{
APIGroups: []string{"apps"},
APIVersions: []string{"v1"},
Resources: []string{"deployments"},
@@ -381,9 +379,9 @@ func TestDispatcher(t *testing.T) {
},
},
},
Mutations: []v1beta1.Mutation{{
PatchType: v1beta1.PatchTypeApplyConfiguration,
ApplyConfiguration: &v1beta1.ApplyConfiguration{
Mutations: []admissionregistrationv1.Mutation{{
PatchType: admissionregistrationv1.PatchTypeApplyConfiguration,
ApplyConfiguration: &admissionregistrationv1.ApplyConfiguration{
Expression: `Object{
metadata: Object.metadata{
labels: {"environment": "production"}
@@ -392,27 +390,27 @@ func TestDispatcher(t *testing.T) {
},
},
},
Bindings: []*PolicyBinding{{
Bindings: []*admissionregistrationv1.MutatingAdmissionPolicyBinding{{
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
Spec: admissionregistrationv1.MutatingAdmissionPolicyBindingSpec{
PolicyName: "policy1",
},
}},
},
{
Policy: &v1beta1.MutatingAdmissionPolicy{
Policy: &admissionregistrationv1.MutatingAdmissionPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "policy2",
},
Spec: v1beta1.MutatingAdmissionPolicySpec{
MatchConstraints: &v1beta1.MatchResources{
MatchPolicy: ptr.To(v1beta1.Equivalent),
Spec: admissionregistrationv1.MutatingAdmissionPolicySpec{
MatchConstraints: &admissionregistrationv1.MatchResources{
MatchPolicy: ptr.To(admissionregistrationv1.Equivalent),
NamespaceSelector: &metav1.LabelSelector{},
ObjectSelector: &metav1.LabelSelector{},
ResourceRules: []v1beta1.NamedRuleWithOperations{
ResourceRules: []admissionregistrationv1.NamedRuleWithOperations{
{
RuleWithOperations: v1beta1.RuleWithOperations{
Rule: v1beta1.Rule{
RuleWithOperations: admissionregistrationv1.RuleWithOperations{
Rule: admissionregistrationv1.Rule{
APIGroups: []string{"apps"},
APIVersions: []string{"v1"},
Resources: []string{"deployments"},
@@ -422,15 +420,15 @@ func TestDispatcher(t *testing.T) {
},
},
},
MatchConditions: []v1beta1.MatchCondition{
MatchConditions: []admissionregistrationv1.MatchCondition{
{
Name: "prodonly",
Expression: `object.?metadata.labels["environment"].orValue("") == "production"`,
},
},
Mutations: []v1beta1.Mutation{{
PatchType: v1beta1.PatchTypeApplyConfiguration,
ApplyConfiguration: &v1beta1.ApplyConfiguration{
Mutations: []admissionregistrationv1.Mutation{{
PatchType: admissionregistrationv1.PatchTypeApplyConfiguration,
ApplyConfiguration: &admissionregistrationv1.ApplyConfiguration{
Expression: `Object{
metadata: Object.metadata{
labels: {"policy1invoked": "true"}
@@ -439,9 +437,9 @@ func TestDispatcher(t *testing.T) {
},
},
},
Bindings: []*PolicyBinding{{
Bindings: []*admissionregistrationv1.MutatingAdmissionPolicyBinding{{
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
Spec: admissionregistrationv1.MutatingAdmissionPolicyBindingSpec{
PolicyName: "policy2",
},
}},
@@ -491,21 +489,21 @@ func TestDispatcher(t *testing.T) {
Type: appsv1.RollingUpdateDeploymentStrategyType,
},
}},
policyHooks: []generic.PolicyHook[*Policy, *PolicyBinding, PolicyEvaluator]{
policyHooks: []PolicyHook{
{
Policy: &v1beta1.MutatingAdmissionPolicy{
Policy: &admissionregistrationv1.MutatingAdmissionPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "policy1",
},
Spec: v1beta1.MutatingAdmissionPolicySpec{
MatchConstraints: &v1beta1.MatchResources{
MatchPolicy: ptr.To(v1beta1.Equivalent),
Spec: admissionregistrationv1.MutatingAdmissionPolicySpec{
MatchConstraints: &admissionregistrationv1.MatchResources{
MatchPolicy: ptr.To(admissionregistrationv1.Equivalent),
NamespaceSelector: &metav1.LabelSelector{},
ObjectSelector: &metav1.LabelSelector{},
ResourceRules: []v1beta1.NamedRuleWithOperations{
ResourceRules: []admissionregistrationv1.NamedRuleWithOperations{
{
RuleWithOperations: v1beta1.RuleWithOperations{
Rule: v1beta1.Rule{
RuleWithOperations: admissionregistrationv1.RuleWithOperations{
Rule: admissionregistrationv1.Rule{
APIGroups: []string{"apps"},
APIVersions: []string{"v1"},
Resources: []string{"deployments"},
@@ -515,15 +513,15 @@ func TestDispatcher(t *testing.T) {
},
},
},
MatchConditions: []v1beta1.MatchCondition{
MatchConditions: []admissionregistrationv1.MatchCondition{
{
Name: "prodonly",
Expression: `object.?metadata.labels["environment"].orValue("") == "production"`,
},
},
Mutations: []v1beta1.Mutation{{
PatchType: v1beta1.PatchTypeApplyConfiguration,
ApplyConfiguration: &v1beta1.ApplyConfiguration{
Mutations: []admissionregistrationv1.Mutation{{
PatchType: admissionregistrationv1.PatchTypeApplyConfiguration,
ApplyConfiguration: &admissionregistrationv1.ApplyConfiguration{
Expression: `Object{
metadata: Object.metadata{
labels: {"policy1invoked": "true"}
@@ -532,27 +530,27 @@ func TestDispatcher(t *testing.T) {
},
},
},
Bindings: []*PolicyBinding{{
Bindings: []*admissionregistrationv1.MutatingAdmissionPolicyBinding{{
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
Spec: admissionregistrationv1.MutatingAdmissionPolicyBindingSpec{
PolicyName: "policy1",
},
}},
},
{
Policy: &v1beta1.MutatingAdmissionPolicy{
Policy: &admissionregistrationv1.MutatingAdmissionPolicy{
ObjectMeta: metav1.ObjectMeta{
Name: "policy2",
},
Spec: v1beta1.MutatingAdmissionPolicySpec{
MatchConstraints: &v1beta1.MatchResources{
MatchPolicy: ptr.To(v1beta1.Equivalent),
Spec: admissionregistrationv1.MutatingAdmissionPolicySpec{
MatchConstraints: &admissionregistrationv1.MatchResources{
MatchPolicy: ptr.To(admissionregistrationv1.Equivalent),
NamespaceSelector: &metav1.LabelSelector{},
ObjectSelector: &metav1.LabelSelector{},
ResourceRules: []v1beta1.NamedRuleWithOperations{
ResourceRules: []admissionregistrationv1.NamedRuleWithOperations{
{
RuleWithOperations: v1beta1.RuleWithOperations{
Rule: v1beta1.Rule{
RuleWithOperations: admissionregistrationv1.RuleWithOperations{
Rule: admissionregistrationv1.Rule{
APIGroups: []string{"apps"},
APIVersions: []string{"v1"},
Resources: []string{"deployments"},
@@ -562,9 +560,9 @@ func TestDispatcher(t *testing.T) {
},
},
},
Mutations: []v1beta1.Mutation{{
PatchType: v1beta1.PatchTypeApplyConfiguration,
ApplyConfiguration: &v1beta1.ApplyConfiguration{
Mutations: []admissionregistrationv1.Mutation{{
PatchType: admissionregistrationv1.PatchTypeApplyConfiguration,
ApplyConfiguration: &admissionregistrationv1.ApplyConfiguration{
Expression: `Object{
metadata: Object.metadata{
labels: {"environment": "production"}
@@ -573,9 +571,9 @@ func TestDispatcher(t *testing.T) {
},
},
},
Bindings: []*PolicyBinding{{
Bindings: []*admissionregistrationv1.MutatingAdmissionPolicyBinding{{
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
Spec: admissionregistrationv1.MutatingAdmissionPolicyBindingSpec{
PolicyName: "policy2",
},
}},

View File

@@ -22,7 +22,7 @@ import (
celgo "github.com/google/cel-go/cel"
"k8s.io/api/admissionregistration/v1beta1"
v1 "k8s.io/api/admissionregistration/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/runtime"
@@ -54,9 +54,9 @@ func Register(plugins *admission.Plugins) {
})
}
type Policy = v1beta1.MutatingAdmissionPolicy
type PolicyBinding = v1beta1.MutatingAdmissionPolicyBinding
type PolicyMutation = v1beta1.Mutation
type Policy = v1.MutatingAdmissionPolicy
type PolicyBinding = v1.MutatingAdmissionPolicyBinding
type PolicyHook = generic.PolicyHook[*Policy, *PolicyBinding, PolicyEvaluator]
type Mutator struct {
@@ -97,8 +97,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().V1beta1().MutatingAdmissionPolicies().Informer(),
f.Admissionregistration().V1beta1().MutatingAdmissionPolicyBindings().Informer(),
f.Admissionregistration().V1().MutatingAdmissionPolicies().Informer(),
f.Admissionregistration().V1().MutatingAdmissionPolicyBindings().Informer(),
NewMutatingAdmissionPolicyAccessor,
NewMutatingAdmissionPolicyBindingAccessor,
compilePolicy,
@@ -142,11 +142,3 @@ func (v *Variable) ReturnTypes() []*celgo.Type {
func (v *Variable) GetName() string {
return v.Name
}
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}
}
return namedExpressions
}

View File

@@ -22,7 +22,7 @@ import (
"github.com/stretchr/testify/require"
"k8s.io/api/admissionregistration/v1beta1"
v1 "k8s.io/api/admissionregistration/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -42,10 +42,10 @@ import (
func setupTest(
t *testing.T,
compiler func(*mutating.Policy) mutating.PolicyEvaluator,
) *generic.PolicyTestContext[*mutating.Policy, *mutating.PolicyBinding, mutating.PolicyEvaluator] {
compiler func(*v1.MutatingAdmissionPolicy) mutating.PolicyEvaluator,
) *generic.PolicyTestContext[*v1.MutatingAdmissionPolicy, *v1.MutatingAdmissionPolicyBinding, mutating.PolicyEvaluator] {
testContext, testCancel, err := generic.NewPolicyTestContext[*mutating.Policy, *mutating.PolicyBinding, mutating.PolicyEvaluator](
testContext, testCancel, err := generic.NewPolicyTestContext[*v1.MutatingAdmissionPolicy, *v1.MutatingAdmissionPolicyBinding, mutating.PolicyEvaluator](
t,
mutating.NewMutatingAdmissionPolicyAccessor,
mutating.NewMutatingAdmissionPolicyBindingAccessor,
@@ -81,33 +81,33 @@ func TestBasicPatch(t *testing.T) {
expectedAnnotations := map[string]string{"foo": "bar"}
// Treat all policies as setting foo annotation to bar
testContext := setupTest(t, func(p *mutating.Policy) mutating.PolicyEvaluator {
testContext := setupTest(t, func(p *v1.MutatingAdmissionPolicy) mutating.PolicyEvaluator {
return mutating.PolicyEvaluator{Mutators: []patch.Patcher{annotationPatcher{expectedAnnotations}}}
})
// Set up a policy and binding that match, no params
require.NoError(t, testContext.UpdateAndWait(
&mutating.Policy{
&v1.MutatingAdmissionPolicy{
ObjectMeta: metav1.ObjectMeta{Name: "policy"},
Spec: v1beta1.MutatingAdmissionPolicySpec{
MatchConstraints: &v1beta1.MatchResources{
MatchPolicy: ptr.To(v1beta1.Equivalent),
Spec: v1.MutatingAdmissionPolicySpec{
MatchConstraints: &v1.MatchResources{
MatchPolicy: ptr.To(v1.Equivalent),
NamespaceSelector: &metav1.LabelSelector{},
ObjectSelector: &metav1.LabelSelector{},
},
Mutations: []v1beta1.Mutation{
Mutations: []v1.Mutation{
{
ApplyConfiguration: &v1beta1.ApplyConfiguration{
ApplyConfiguration: &v1.ApplyConfiguration{
Expression: "ignored, but required",
},
PatchType: v1beta1.PatchTypeApplyConfiguration,
PatchType: v1.PatchTypeApplyConfiguration,
},
},
},
},
&mutating.PolicyBinding{
&v1.MutatingAdmissionPolicyBinding{
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
Spec: v1.MutatingAdmissionPolicyBindingSpec{
PolicyName: "policy",
},
},
@@ -136,7 +136,7 @@ func TestJSONPatch(t *testing.T) {
},
}
testContext := setupTest(t, func(p *mutating.Policy) mutating.PolicyEvaluator {
testContext := setupTest(t, func(p *v1.MutatingAdmissionPolicy) mutating.PolicyEvaluator {
return mutating.PolicyEvaluator{
Mutators: []patch.Patcher{smdPatcher{patch: patchObj}},
}
@@ -144,27 +144,27 @@ func TestJSONPatch(t *testing.T) {
// Set up a policy and binding that match, no params
require.NoError(t, testContext.UpdateAndWait(
&mutating.Policy{
&v1.MutatingAdmissionPolicy{
ObjectMeta: metav1.ObjectMeta{Name: "policy"},
Spec: v1beta1.MutatingAdmissionPolicySpec{
MatchConstraints: &v1beta1.MatchResources{
MatchPolicy: ptr.To(v1beta1.Equivalent),
Spec: v1.MutatingAdmissionPolicySpec{
MatchConstraints: &v1.MatchResources{
MatchPolicy: ptr.To(v1.Equivalent),
NamespaceSelector: &metav1.LabelSelector{},
ObjectSelector: &metav1.LabelSelector{},
},
Mutations: []v1beta1.Mutation{
Mutations: []v1.Mutation{
{
JSONPatch: &v1beta1.JSONPatch{
JSONPatch: &v1.JSONPatch{
Expression: "ignored, but required",
},
PatchType: v1beta1.PatchTypeApplyConfiguration,
PatchType: v1.PatchTypeApplyConfiguration,
},
},
},
},
&mutating.PolicyBinding{
&v1.MutatingAdmissionPolicyBinding{
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
Spec: v1.MutatingAdmissionPolicyBindingSpec{
PolicyName: "policy",
},
},
@@ -198,7 +198,7 @@ func TestSSAPatch(t *testing.T) {
},
}
testContext := setupTest(t, func(p *mutating.Policy) mutating.PolicyEvaluator {
testContext := setupTest(t, func(p *v1.MutatingAdmissionPolicy) mutating.PolicyEvaluator {
return mutating.PolicyEvaluator{
Mutators: []patch.Patcher{smdPatcher{patch: patchObj}},
}
@@ -206,27 +206,27 @@ func TestSSAPatch(t *testing.T) {
// Set up a policy and binding that match, no params
require.NoError(t, testContext.UpdateAndWait(
&mutating.Policy{
&v1.MutatingAdmissionPolicy{
ObjectMeta: metav1.ObjectMeta{Name: "policy"},
Spec: v1beta1.MutatingAdmissionPolicySpec{
MatchConstraints: &v1beta1.MatchResources{
MatchPolicy: ptr.To(v1beta1.Equivalent),
Spec: v1.MutatingAdmissionPolicySpec{
MatchConstraints: &v1.MatchResources{
MatchPolicy: ptr.To(v1.Equivalent),
NamespaceSelector: &metav1.LabelSelector{},
ObjectSelector: &metav1.LabelSelector{},
},
Mutations: []v1beta1.Mutation{
Mutations: []v1.Mutation{
{
ApplyConfiguration: &v1beta1.ApplyConfiguration{
ApplyConfiguration: &v1.ApplyConfiguration{
Expression: "ignored, but required",
},
PatchType: v1beta1.PatchTypeApplyConfiguration,
PatchType: v1.PatchTypeApplyConfiguration,
},
},
},
},
&mutating.PolicyBinding{
&v1.MutatingAdmissionPolicyBinding{
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
Spec: v1.MutatingAdmissionPolicyBindingSpec{
PolicyName: "policy",
},
},
@@ -265,7 +265,7 @@ func TestSSAMapList(t *testing.T) {
},
}
testContext := setupTest(t, func(p *mutating.Policy) mutating.PolicyEvaluator {
testContext := setupTest(t, func(p *v1.MutatingAdmissionPolicy) mutating.PolicyEvaluator {
return mutating.PolicyEvaluator{
Mutators: []patch.Patcher{smdPatcher{patch: patchObj}},
}
@@ -273,27 +273,27 @@ func TestSSAMapList(t *testing.T) {
// Set up a policy and binding that match, no params
require.NoError(t, testContext.UpdateAndWait(
&mutating.Policy{
&v1.MutatingAdmissionPolicy{
ObjectMeta: metav1.ObjectMeta{Name: "policy"},
Spec: v1beta1.MutatingAdmissionPolicySpec{
MatchConstraints: &v1beta1.MatchResources{
MatchPolicy: ptr.To(v1beta1.Equivalent),
Spec: v1.MutatingAdmissionPolicySpec{
MatchConstraints: &v1.MatchResources{
MatchPolicy: ptr.To(v1.Equivalent),
NamespaceSelector: &metav1.LabelSelector{},
ObjectSelector: &metav1.LabelSelector{},
},
Mutations: []v1beta1.Mutation{
Mutations: []v1.Mutation{
{
ApplyConfiguration: &v1beta1.ApplyConfiguration{
ApplyConfiguration: &v1.ApplyConfiguration{
Expression: "ignored, but required",
},
PatchType: v1beta1.PatchTypeApplyConfiguration,
PatchType: v1.PatchTypeApplyConfiguration,
},
},
},
},
&mutating.PolicyBinding{
&v1.MutatingAdmissionPolicyBinding{
ObjectMeta: metav1.ObjectMeta{Name: "binding"},
Spec: v1beta1.MutatingAdmissionPolicyBindingSpec{
Spec: v1.MutatingAdmissionPolicyBindingSpec{
PolicyName: "policy",
},
},

View File

@@ -421,6 +421,7 @@ var defaultVersionedKubernetesFeatureGates = map[featuregate.Feature]featuregate
MutatingAdmissionPolicy: {
{Version: version.MustParse("1.32"), Default: false, PreRelease: featuregate.Alpha},
{Version: version.MustParse("1.34"), Default: false, PreRelease: featuregate.Beta},
{Version: version.MustParse("1.36"), Default: true, PreRelease: featuregate.GA},
},
OpenAPIEnums: {

View File

@@ -123,7 +123,7 @@
| MutablePVNodeAffinity | | | 1.35 | | | | | [code](https://cs.k8s.io/?q=%5CbMutablePVNodeAffinity%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbMutablePVNodeAffinity%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| MutablePodResourcesForSuspendedJobs | :ballot_box_with_check: 1.36+ | | 1.35 | 1.36 | | | | [code](https://cs.k8s.io/?q=%5CbMutablePodResourcesForSuspendedJobs%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbMutablePodResourcesForSuspendedJobs%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| MutableSchedulingDirectivesForSuspendedJobs | :ballot_box_with_check: 1.36+ | | 1.35 | 1.36 | | | | [code](https://cs.k8s.io/?q=%5CbMutableSchedulingDirectivesForSuspendedJobs%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbMutableSchedulingDirectivesForSuspendedJobs%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| MutatingAdmissionPolicy | | | 1.321.33 | 1.34 | | | | [code](https://cs.k8s.io/?q=%5CbMutatingAdmissionPolicy%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbMutatingAdmissionPolicy%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| MutatingAdmissionPolicy | :ballot_box_with_check: 1.36+ | | 1.321.33 | 1.341.35 | 1.36 | | | [code](https://cs.k8s.io/?q=%5CbMutatingAdmissionPolicy%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbMutatingAdmissionPolicy%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| NFTablesProxyMode | :ballot_box_with_check: 1.31+ | :closed_lock_with_key: 1.33+ | 1.291.30 | 1.311.32 | 1.33 | | | [code](https://cs.k8s.io/?q=%5CbNFTablesProxyMode%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbNFTablesProxyMode%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| NodeDeclaredFeatures | | | 1.35 | | | | | [code](https://cs.k8s.io/?q=%5CbNodeDeclaredFeatures%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbNodeDeclaredFeatures%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |
| NodeInclusionPolicyInPodTopologySpread | :ballot_box_with_check: 1.26+ | :closed_lock_with_key: 1.33+ | 1.25 | 1.261.32 | 1.33 | | | [code](https://cs.k8s.io/?q=%5CbNodeInclusionPolicyInPodTopologySpread%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/kubernetes) [KEPs](https://cs.k8s.io/?q=%5CbNodeInclusionPolicyInPodTopologySpread%5Cb&i=nope&files=&excludeFiles=CHANGELOG&repos=kubernetes/enhancements) |

View File

@@ -1141,6 +1141,10 @@
lockToDefault: false
preRelease: Beta
version: "1.34"
- default: true
lockToDefault: false
preRelease: GA
version: "1.36"
- name: NFTablesProxyMode
versionedSpecs:
- default: false

View File

@@ -157,6 +157,8 @@ var (
gvr("admissionregistration.k8s.io", "v1alpha1", "mutatingadmissionpolicybindings"): true,
gvr("admissionregistration.k8s.io", "v1beta1", "mutatingadmissionpolicies"): true,
gvr("admissionregistration.k8s.io", "v1beta1", "mutatingadmissionpolicybindings"): true,
gvr("admissionregistration.k8s.io", "v1", "mutatingadmissionpolicies"): true,
gvr("admissionregistration.k8s.io", "v1", "mutatingadmissionpolicybindings"): true,
}
parentResources = map[schema.GroupVersionResource]schema.GroupVersionResource{