Skip to content

Commit ed1f8db

Browse files
authored
feat: Add validatingAdmissionPolicy and validatingAdmissionPolicyBinding (#2635)
* feat: Add validatingAdmissionPolicy and validatingAdmissionPolicyBinding * fix: Update class-generator tests
1 parent 703cb59 commit ed1f8db

7 files changed

Lines changed: 16084 additions & 291894 deletions

File tree

class_generator/schema/_definitions.json

Lines changed: 15722 additions & 291411 deletions
Large diffs are not rendered by default.

class_generator/tests/manifests/Deployment/deployment.py

Lines changed: 9 additions & 221 deletions
Large diffs are not rendered by default.

class_generator/tests/manifests/Ingress/ingress_networking_k8s_io.py

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,29 @@ def __init__(
2323
) -> None:
2424
r"""
2525
Args:
26-
default_backend (dict[str, Any]): resource apiGroup kind name service name port name number.
27-
28-
ingress_class_name (str): No field description from API
29-
30-
rules (list[Any]): host http paths backend resource apiGroup kind name service name port
31-
name number path pathType enum: Exact, ImplementationSpecific,
32-
Prefix.
33-
34-
tls (list[Any]): hosts secretName.
26+
default_backend (dict[str, Any]): IngressBackend describes all endpoints for a given service and port.
27+
28+
ingress_class_name (str): ingressClassName is the name of an IngressClass cluster resource.
29+
Ingress controller implementations use this field to know whether
30+
they should be serving this Ingress resource, by a transitive
31+
connection (controller -> IngressClass -> Ingress resource).
32+
Although the `kubernetes.io/ingress.class` annotation (simple
33+
constant name) was never formally defined, it was widely supported
34+
by Ingress controllers to create a direct binding between Ingress
35+
controller and Ingress resources. Newly created Ingress resources
36+
should prefer using the field. However, even though the annotation
37+
is officially deprecated, for backwards compatibility reasons,
38+
ingress controllers should still honor that annotation if present.
39+
40+
rules (list[Any]): rules is a list of host rules used to configure the Ingress. If
41+
unspecified, or no rule matches, all traffic is sent to the
42+
default backend.
43+
44+
tls (list[Any]): tls represents the TLS configuration. Currently the Ingress only
45+
supports a single TLS port, 443. If multiple members of this list
46+
specify different hosts, they will be multiplexed on the same port
47+
according to the hostname specified through the SNI TLS extension,
48+
if the ingress controller fulfilling the ingress supports SNI.
3549
3650
"""
3751
super().__init__(**kwargs)

class_generator/tests/manifests/Pod/pod.py

Lines changed: 92 additions & 249 deletions
Large diffs are not rendered by default.

class_generator/tests/test_class_generator.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,13 +96,13 @@ def test_parse_explain(tmp_path: Path) -> None:
9696
"Deployment",
9797
"ImageContentSourcePolicy",
9898
"Machine",
99-
"NMState",
100-
"OAuth",
101-
"Pipeline",
10299
"Pod",
103100
"Secret",
101+
"NMState",
104102
"ServiceMeshMember",
105103
"ServingRuntime",
104+
"OAuth",
105+
"Pipeline",
106106
"Ingress",
107107
"RouteAdvertisements",
108108
]
@@ -146,7 +146,9 @@ def create_test_task(kind: str) -> tuple[str, str] | None:
146146

147147
# Create a concise failure message for pytest
148148
failed_kinds = [kind for kind, _ in failures]
149-
failure_summary = f"{len(failures)} resource(s) failed: {','.join(failed_kinds)}"
149+
failure_summary = f"{len(failures)} resource(s) failed: {', '.join(failed_kinds[:5])}"
150+
if len(failed_kinds) > 5:
151+
failure_summary += f" and {len(failed_kinds) - 5} more"
150152

151153
# Fail the test with summary - detailed output is already printed above
152154
raise AssertionError(failure_summary)
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
# Generated using https://github.com/RedHatQE/openshift-python-wrapper/blob/main/scripts/resource/README.md
2+
3+
4+
from typing import Any
5+
6+
from ocp_resources.resource import Resource
7+
8+
9+
class ValidatingAdmissionPolicy(Resource):
10+
"""
11+
ValidatingAdmissionPolicy describes the definition of an admission validation policy that accepts or rejects an object without changing it.
12+
"""
13+
14+
api_group: str = Resource.ApiGroup.ADMISSIONREGISTRATION_K8S_IO
15+
16+
def __init__(
17+
self,
18+
audit_annotations: list[Any] | None = None,
19+
failure_policy: str | None = None,
20+
match_conditions: list[Any] | None = None,
21+
match_constraints: dict[str, Any] | None = None,
22+
param_kind: dict[str, Any] | None = None,
23+
validations: list[Any] | None = None,
24+
variables: list[Any] | None = None,
25+
**kwargs: Any,
26+
) -> None:
27+
r"""
28+
Args:
29+
audit_annotations (list[Any]): auditAnnotations contains CEL expressions which are used to produce
30+
audit annotations for the audit event of the API request.
31+
validations and auditAnnotations may not both be empty; a least
32+
one of validations or auditAnnotations is required.
33+
34+
failure_policy (str): failurePolicy defines how to handle failures for the admission policy.
35+
Failures can occur from CEL expression parse errors, type check
36+
errors, runtime errors and invalid or mis-configured policy
37+
definitions or bindings. A policy is invalid if spec.paramKind
38+
refers to a non-existent Kind. A binding is invalid if
39+
spec.paramRef.name refers to a non-existent resource.
40+
failurePolicy does not define how validations that evaluate to
41+
false are handled. When failurePolicy is set to Fail,
42+
ValidatingAdmissionPolicyBinding validationActions define how
43+
failures are enforced. Allowed values are Ignore or Fail.
44+
Defaults to Fail. Possible enum values: - `"Fail"` means that an
45+
error calling the webhook causes the admission to fail. -
46+
`"Ignore"` means that an error calling the webhook is ignored.
47+
48+
match_conditions (list[Any]): MatchConditions is a list of conditions that must be met for a request
49+
to be validated. Match conditions filter requests that have
50+
already been matched by the rules, namespaceSelector, and
51+
objectSelector. An empty list of matchConditions matches all
52+
requests. There are a maximum of 64 match conditions allowed. If
53+
a parameter object is provided, it can be accessed via the
54+
`params` handle in the same manner as validation expressions. The
55+
exact matching logic is (in order): 1. If ANY matchCondition
56+
evaluates to FALSE, the policy is skipped. 2. If ALL
57+
matchConditions evaluate to TRUE, the policy is evaluated. 3. If
58+
any matchCondition evaluates to an error (but none are FALSE):
59+
- If failurePolicy=Fail, reject the request - If
60+
failurePolicy=Ignore, the policy is skipped
61+
62+
match_constraints (dict[str, Any]): MatchResources decides whether to run the admission control policy on
63+
an object based on whether it meets the match criteria. The
64+
exclude rules take precedence over include rules (if a resource
65+
matches both, it is excluded)
66+
67+
param_kind (dict[str, Any]): ParamKind is a tuple of Group Kind and Version.
68+
69+
validations (list[Any]): Validations contain CEL expressions which is used to apply the
70+
validation. Validations and AuditAnnotations may not both be
71+
empty; a minimum of one Validations or AuditAnnotations is
72+
required.
73+
74+
variables (list[Any]): Variables contain definitions of variables that can be used in
75+
composition of other expressions. Each variable is defined as a
76+
named CEL expression. The variables defined here will be available
77+
under `variables` in other expressions of the policy except
78+
MatchConditions because MatchConditions are evaluated before the
79+
rest of the policy. The expression of a variable can refer to
80+
other variables defined earlier in the list but not those after.
81+
Thus, Variables must be sorted by the order of first appearance
82+
and acyclic.
83+
84+
"""
85+
super().__init__(**kwargs)
86+
87+
self.audit_annotations = audit_annotations
88+
self.failure_policy = failure_policy
89+
self.match_conditions = match_conditions
90+
self.match_constraints = match_constraints
91+
self.param_kind = param_kind
92+
self.validations = validations
93+
self.variables = variables
94+
95+
def to_dict(self) -> None:
96+
97+
super().to_dict()
98+
99+
if not self.kind_dict and not self.yaml_file:
100+
self.res["spec"] = {}
101+
_spec = self.res["spec"]
102+
103+
if self.audit_annotations is not None:
104+
_spec["auditAnnotations"] = self.audit_annotations
105+
106+
if self.failure_policy is not None:
107+
_spec["failurePolicy"] = self.failure_policy
108+
109+
if self.match_conditions is not None:
110+
_spec["matchConditions"] = self.match_conditions
111+
112+
if self.match_constraints is not None:
113+
_spec["matchConstraints"] = self.match_constraints
114+
115+
if self.param_kind is not None:
116+
_spec["paramKind"] = self.param_kind
117+
118+
if self.validations is not None:
119+
_spec["validations"] = self.validations
120+
121+
if self.variables is not None:
122+
_spec["variables"] = self.variables
123+
124+
# End of generated code
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
# Generated using https://github.com/RedHatQE/openshift-python-wrapper/blob/main/scripts/resource/README.md
2+
3+
4+
from typing import Any
5+
6+
from ocp_resources.resource import Resource
7+
8+
9+
class ValidatingAdmissionPolicyBinding(Resource):
10+
"""
11+
ValidatingAdmissionPolicyBinding binds the ValidatingAdmissionPolicy with paramerized resources. ValidatingAdmissionPolicyBinding and parameter CRDs together define how cluster administrators configure policies for clusters.
12+
13+
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.
14+
15+
The CEL expressions of a policy must have a computed CEL cost below the maximum CEL budget. Each evaluation of the policy is given an independent CEL cost budget. Adding/removing policies, bindings, or params can not affect whether a given (policy, binding, param) combination is within its own CEL budget.
16+
"""
17+
18+
api_group: str = Resource.ApiGroup.ADMISSIONREGISTRATION_K8S_IO
19+
20+
def __init__(
21+
self,
22+
match_resources: dict[str, Any] | None = None,
23+
param_ref: dict[str, Any] | None = None,
24+
policy_name: str | None = None,
25+
validation_actions: list[Any] | None = None,
26+
**kwargs: Any,
27+
) -> None:
28+
r"""
29+
Args:
30+
match_resources (dict[str, Any]): MatchResources decides whether to run the admission control policy on
31+
an object based on whether it meets the match criteria. The
32+
exclude rules take precedence over include rules (if a resource
33+
matches both, it is excluded)
34+
35+
param_ref (dict[str, Any]): ParamRef describes how to locate the params to be used as input to
36+
expressions of rules applied by a policy binding.
37+
38+
policy_name (str): PolicyName references a ValidatingAdmissionPolicy name which the
39+
ValidatingAdmissionPolicyBinding binds to. If the referenced
40+
resource does not exist, this binding is considered invalid and
41+
will be ignored Required.
42+
43+
validation_actions (list[Any]): validationActions declares how Validations of the referenced
44+
ValidatingAdmissionPolicy are enforced. If a validation evaluates
45+
to false it is always enforced according to these actions.
46+
Failures defined by the ValidatingAdmissionPolicy's FailurePolicy
47+
are enforced according to these actions only if the FailurePolicy
48+
is set to Fail, otherwise the failures are ignored. This includes
49+
compilation errors, runtime errors and misconfigurations of the
50+
policy. validationActions is declared as a set of action values.
51+
Order does not matter. validationActions may not contain
52+
duplicates of the same action. The supported actions values are:
53+
"Deny" specifies that a validation failure results in a denied
54+
request. "Warn" specifies that a validation failure is reported
55+
to the request client in HTTP Warning headers, with a warning code
56+
of 299. Warnings can be sent both for allowed or denied admission
57+
responses. "Audit" specifies that a validation failure is
58+
included in the published audit event for the request. The audit
59+
event will contain a
60+
`validation.policy.admission.k8s.io/validation_failure` audit
61+
annotation with a value containing the details of the validation
62+
failures, formatted as a JSON list of objects, each with the
63+
following fields: - message: The validation failure message string
64+
- policy: The resource name of the ValidatingAdmissionPolicy -
65+
binding: The resource name of the ValidatingAdmissionPolicyBinding
66+
- expressionIndex: The index of the failed validations in the
67+
ValidatingAdmissionPolicy - validationActions: The enforcement
68+
actions enacted for the validation failure Example audit
69+
annotation:
70+
`"validation.policy.admission.k8s.io/validation_failure":
71+
"[{\"message\": \"Invalid value\", {\"policy\":
72+
\"policy.example.com\", {\"binding\":
73+
\"policybinding.example.com\", {\"expressionIndex\": \"1\",
74+
{\"validationActions\": [\"Audit\"]}]"` Clients should expect to
75+
handle additional values by ignoring any values not recognized.
76+
"Deny" and "Warn" may not be used together since this combination
77+
needlessly duplicates the validation failure both in the API
78+
response body and the HTTP warning headers. Required.
79+
80+
"""
81+
super().__init__(**kwargs)
82+
83+
self.match_resources = match_resources
84+
self.param_ref = param_ref
85+
self.policy_name = policy_name
86+
self.validation_actions = validation_actions
87+
88+
def to_dict(self) -> None:
89+
90+
super().to_dict()
91+
92+
if not self.kind_dict and not self.yaml_file:
93+
self.res["spec"] = {}
94+
_spec = self.res["spec"]
95+
96+
if self.match_resources is not None:
97+
_spec["matchResources"] = self.match_resources
98+
99+
if self.param_ref is not None:
100+
_spec["paramRef"] = self.param_ref
101+
102+
if self.policy_name is not None:
103+
_spec["policyName"] = self.policy_name
104+
105+
if self.validation_actions is not None:
106+
_spec["validationActions"] = self.validation_actions
107+
108+
# End of generated code

0 commit comments

Comments
 (0)