Merge pull request #132821 from cici37/mapBeta

[KEP-3962]Promote MutatingAdmissionPolicy to Beta

Kubernetes-commit: 3dd0e86190cc023a98f59d48d75efde08a27fd82
This commit is contained in:
Kubernetes Publisher 2025-07-17 14:18:24 -07:00
commit b8b19e9618
10 changed files with 175 additions and 174 deletions

4
go.mod
View File

@ -48,9 +48,9 @@ require (
gopkg.in/evanphx/json-patch.v4 v4.12.0
gopkg.in/go-jose/go-jose.v2 v2.6.3
gopkg.in/natefinch/lumberjack.v2 v2.2.1
k8s.io/api v0.0.0-20250717170527-b7a83e2941aa
k8s.io/api v0.0.0-20250718010530-b3927ff69476
k8s.io/apimachinery v0.0.0-20250717210244-b92abb2d8139
k8s.io/client-go v0.0.0-20250717170921-fa10fa2dea75
k8s.io/client-go v0.0.0-20250718010928-be36413bbca7
k8s.io/component-base v0.0.0-20250717172125-4e07767df717
k8s.io/klog/v2 v2.130.1
k8s.io/kms v0.0.0-20250716213631-bbefe5cb7a2e

8
go.sum
View File

@ -296,12 +296,12 @@ gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYs
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.0.0-20250717170527-b7a83e2941aa h1:9T75LAFccLxRh1V7SjtTxnpY9H4DoTlajvyLQQuViZg=
k8s.io/api v0.0.0-20250717170527-b7a83e2941aa/go.mod h1:KToU1jTzT+gkd8q+fEft6oTAtPXK9a4pXEqdI6xhoLE=
k8s.io/api v0.0.0-20250718010530-b3927ff69476 h1:Aujs/kJa+rquu3rzDmTZmy8qul/yc4fTK1LEAK5QGpg=
k8s.io/api v0.0.0-20250718010530-b3927ff69476/go.mod h1:K8dwhtttsRR0RHeSRF8XQ77gfMgyAj3q78/TkxEXhoc=
k8s.io/apimachinery v0.0.0-20250717210244-b92abb2d8139 h1:jWBClrBPuk+GEA9pJzMa9IvxncSBbw7fmvey15nVm0w=
k8s.io/apimachinery v0.0.0-20250717210244-b92abb2d8139/go.mod h1:v1p1Jsze3IHLy5gU17yVqR2qLO7jgYeX6mw3HZy2AEU=
k8s.io/client-go v0.0.0-20250717170921-fa10fa2dea75 h1:15PFFxsRBk7ceo2B1lA+FxkA33GCwNqNl+UzXS/oL5U=
k8s.io/client-go v0.0.0-20250717170921-fa10fa2dea75/go.mod h1:OVZIe2J7VRQKdzsLDwmqAQyKxd1CKuTEVR7jW9uca2g=
k8s.io/client-go v0.0.0-20250718010928-be36413bbca7 h1:LNOJkn+3JlAEzdZzYheQM97gq6kKQfkrBN0GikI5nbc=
k8s.io/client-go v0.0.0-20250718010928-be36413bbca7/go.mod h1:a14VvgYhux7oUSE9mWdzBuFKDZSGtperboMjQ1JtVgc=
k8s.io/component-base v0.0.0-20250717172125-4e07767df717 h1:07oqkM0FzuGUw/bJw2rJubzccG7ShpGcTJ7SBDGp5Fc=
k8s.io/component-base v0.0.0-20250717172125-4e07767df717/go.mod h1:/ehREU84M2OxVgU8WfxuUIi4/c5XsT6rIsEGQfhgxEQ=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=

View File

@ -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
}

View File

@ -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)

View File

@ -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
}

View File

@ -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)
}
}

View File

@ -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",
},
}},

View File

@ -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}

View File

@ -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",
},
},

View File

@ -367,6 +367,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},
},
OpenAPIEnums: {