-
Notifications
You must be signed in to change notification settings - Fork 68
feat: Add validatingAdmissionPolicy and validatingAdmissionPolicyBinding #2635
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
RoniKishner
wants to merge
2
commits into
RedHatQE:main
Choose a base branch
from
RoniKishner:validating-admission-policy
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
307,133 changes: 15,722 additions & 291,411 deletions
307,133
class_generator/schema/_definitions.json
Large diffs are not rendered by default.
Oops, something went wrong.
230 changes: 9 additions & 221 deletions
230
class_generator/tests/manifests/Deployment/deployment.py
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,124 @@ | ||
| # Generated using https://github.com/RedHatQE/openshift-python-wrapper/blob/main/scripts/resource/README.md | ||
|
|
||
|
|
||
| from typing import Any | ||
|
|
||
| from ocp_resources.resource import Resource | ||
|
|
||
|
|
||
| class ValidatingAdmissionPolicy(Resource): | ||
| """ | ||
| ValidatingAdmissionPolicy describes the definition of an admission validation policy that accepts or rejects an object without changing it. | ||
| """ | ||
|
|
||
| api_group: str = Resource.ApiGroup.ADMISSIONREGISTRATION_K8S_IO | ||
|
|
||
| def __init__( | ||
| self, | ||
| audit_annotations: list[Any] | None = None, | ||
| failure_policy: str | None = None, | ||
| match_conditions: list[Any] | None = None, | ||
| match_constraints: dict[str, Any] | None = None, | ||
| param_kind: dict[str, Any] | None = None, | ||
| validations: list[Any] | None = None, | ||
| variables: list[Any] | None = None, | ||
| **kwargs: Any, | ||
| ) -> None: | ||
| r""" | ||
| Args: | ||
| audit_annotations (list[Any]): auditAnnotations contains CEL expressions which are used to produce | ||
| audit annotations for the audit event of the API request. | ||
| validations and auditAnnotations may not both be empty; a least | ||
| one of validations or auditAnnotations is required. | ||
|
|
||
| failure_policy (str): failurePolicy defines how to handle failures for the admission policy. | ||
| Failures can occur from CEL expression parse errors, type check | ||
| errors, runtime errors and invalid or mis-configured policy | ||
| definitions or bindings. A policy is invalid if spec.paramKind | ||
| refers to a non-existent Kind. A binding is invalid if | ||
| spec.paramRef.name refers to a non-existent resource. | ||
| failurePolicy does not define how validations that evaluate to | ||
| false are handled. When failurePolicy is set to Fail, | ||
| ValidatingAdmissionPolicyBinding validationActions define how | ||
| failures are enforced. Allowed values are Ignore or Fail. | ||
| Defaults to Fail. Possible enum values: - `"Fail"` means that an | ||
| error calling the webhook causes the admission to fail. - | ||
| `"Ignore"` means that an error calling the webhook is ignored. | ||
|
|
||
| match_conditions (list[Any]): MatchConditions is a list of conditions that must be met for a request | ||
| to be validated. Match conditions filter requests that have | ||
| already been matched by the rules, namespaceSelector, and | ||
| objectSelector. An empty list of matchConditions matches all | ||
| requests. There are a maximum of 64 match conditions allowed. If | ||
| a parameter object is provided, it can be accessed via the | ||
| `params` handle in the same manner as validation expressions. The | ||
| exact matching logic is (in order): 1. If ANY matchCondition | ||
| evaluates to FALSE, the policy is skipped. 2. If ALL | ||
| matchConditions evaluate to TRUE, the policy is evaluated. 3. If | ||
| any matchCondition evaluates to an error (but none are FALSE): | ||
| - If failurePolicy=Fail, reject the request - If | ||
| failurePolicy=Ignore, the policy is skipped | ||
|
|
||
| match_constraints (dict[str, Any]): MatchResources decides whether to run the admission control policy on | ||
| an object based on whether it meets the match criteria. The | ||
| exclude rules take precedence over include rules (if a resource | ||
| matches both, it is excluded) | ||
|
|
||
| param_kind (dict[str, Any]): ParamKind is a tuple of Group Kind and Version. | ||
|
|
||
| validations (list[Any]): Validations contain CEL expressions which is used to apply the | ||
| validation. Validations and AuditAnnotations may not both be | ||
| empty; a minimum of one Validations or AuditAnnotations is | ||
| required. | ||
|
|
||
| variables (list[Any]): Variables contain definitions of variables that can be used in | ||
| composition of other expressions. Each variable is defined as a | ||
| named CEL expression. The variables defined here will be available | ||
| under `variables` in other expressions of the policy except | ||
| MatchConditions because MatchConditions are evaluated before the | ||
| rest of the policy. The expression of a variable can refer to | ||
| other variables defined earlier in the list but not those after. | ||
| Thus, Variables must be sorted by the order of first appearance | ||
| and acyclic. | ||
|
|
||
| """ | ||
| super().__init__(**kwargs) | ||
|
|
||
| self.audit_annotations = audit_annotations | ||
| self.failure_policy = failure_policy | ||
| self.match_conditions = match_conditions | ||
| self.match_constraints = match_constraints | ||
| self.param_kind = param_kind | ||
| self.validations = validations | ||
| self.variables = variables | ||
|
|
||
| def to_dict(self) -> None: | ||
|
|
||
| super().to_dict() | ||
|
|
||
| if not self.kind_dict and not self.yaml_file: | ||
| self.res["spec"] = {} | ||
| _spec = self.res["spec"] | ||
|
|
||
| if self.audit_annotations is not None: | ||
| _spec["auditAnnotations"] = self.audit_annotations | ||
|
|
||
| if self.failure_policy is not None: | ||
| _spec["failurePolicy"] = self.failure_policy | ||
|
|
||
| if self.match_conditions is not None: | ||
| _spec["matchConditions"] = self.match_conditions | ||
|
|
||
| if self.match_constraints is not None: | ||
| _spec["matchConstraints"] = self.match_constraints | ||
|
|
||
| if self.param_kind is not None: | ||
| _spec["paramKind"] = self.param_kind | ||
|
|
||
| if self.validations is not None: | ||
| _spec["validations"] = self.validations | ||
|
|
||
| if self.variables is not None: | ||
| _spec["variables"] = self.variables | ||
|
|
||
| # End of generated code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| # Generated using https://github.com/RedHatQE/openshift-python-wrapper/blob/main/scripts/resource/README.md | ||
|
|
||
|
|
||
| from typing import Any | ||
|
|
||
| from ocp_resources.resource import Resource | ||
|
|
||
|
|
||
| class ValidatingAdmissionPolicyBinding(Resource): | ||
| """ | ||
| ValidatingAdmissionPolicyBinding binds the ValidatingAdmissionPolicy with paramerized resources. ValidatingAdmissionPolicyBinding and parameter CRDs together define how cluster administrators configure policies for clusters. | ||
|
|
||
| For a given admission request, each binding will cause its policy to be evaluated N times, where N is 1 for policies/bindings that don't use params, otherwise N is the number of parameters selected by the binding. | ||
|
|
||
| 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. | ||
| """ | ||
|
|
||
| api_group: str = Resource.ApiGroup.ADMISSIONREGISTRATION_K8S_IO | ||
|
|
||
| def __init__( | ||
| self, | ||
| match_resources: dict[str, Any] | None = None, | ||
| param_ref: dict[str, Any] | None = None, | ||
| policy_name: str | None = None, | ||
| validation_actions: list[Any] | None = None, | ||
| **kwargs: Any, | ||
| ) -> None: | ||
| r""" | ||
| Args: | ||
| match_resources (dict[str, Any]): MatchResources decides whether to run the admission control policy on | ||
| an object based on whether it meets the match criteria. The | ||
| exclude rules take precedence over include rules (if a resource | ||
| matches both, it is excluded) | ||
|
|
||
| param_ref (dict[str, Any]): ParamRef describes how to locate the params to be used as input to | ||
| expressions of rules applied by a policy binding. | ||
|
|
||
| policy_name (str): PolicyName references a ValidatingAdmissionPolicy name which the | ||
| ValidatingAdmissionPolicyBinding binds to. If the referenced | ||
| resource does not exist, this binding is considered invalid and | ||
| will be ignored Required. | ||
|
|
||
| validation_actions (list[Any]): validationActions declares how Validations of the referenced | ||
| ValidatingAdmissionPolicy are enforced. If a validation evaluates | ||
| to false it is always enforced according to these actions. | ||
| Failures defined by the ValidatingAdmissionPolicy's FailurePolicy | ||
| are enforced according to these actions only if the FailurePolicy | ||
| is set to Fail, otherwise the failures are ignored. This includes | ||
| compilation errors, runtime errors and misconfigurations of the | ||
| policy. validationActions is declared as a set of action values. | ||
| Order does not matter. validationActions may not contain | ||
| duplicates of the same action. The supported actions values are: | ||
| "Deny" specifies that a validation failure results in a denied | ||
| request. "Warn" specifies that a validation failure is reported | ||
| to the request client in HTTP Warning headers, with a warning code | ||
| of 299. Warnings can be sent both for allowed or denied admission | ||
| responses. "Audit" specifies that a validation failure is | ||
| included in the published audit event for the request. The audit | ||
| event will contain a | ||
| `validation.policy.admission.k8s.io/validation_failure` audit | ||
| annotation with a value containing the details of the validation | ||
| failures, formatted as a JSON list of objects, each with the | ||
| following fields: - message: The validation failure message string | ||
| - policy: The resource name of the ValidatingAdmissionPolicy - | ||
| binding: The resource name of the ValidatingAdmissionPolicyBinding | ||
| - expressionIndex: The index of the failed validations in the | ||
| ValidatingAdmissionPolicy - validationActions: The enforcement | ||
| actions enacted for the validation failure Example audit | ||
| annotation: | ||
| `"validation.policy.admission.k8s.io/validation_failure": | ||
| "[{\"message\": \"Invalid value\", {\"policy\": | ||
| \"policy.example.com\", {\"binding\": | ||
| \"policybinding.example.com\", {\"expressionIndex\": \"1\", | ||
| {\"validationActions\": [\"Audit\"]}]"` Clients should expect to | ||
| handle additional values by ignoring any values not recognized. | ||
| "Deny" and "Warn" may not be used together since this combination | ||
| needlessly duplicates the validation failure both in the API | ||
| response body and the HTTP warning headers. Required. | ||
|
|
||
| """ | ||
| super().__init__(**kwargs) | ||
|
|
||
| self.match_resources = match_resources | ||
| self.param_ref = param_ref | ||
| self.policy_name = policy_name | ||
| self.validation_actions = validation_actions | ||
|
|
||
| def to_dict(self) -> None: | ||
|
|
||
| super().to_dict() | ||
|
|
||
| if not self.kind_dict and not self.yaml_file: | ||
| self.res["spec"] = {} | ||
| _spec = self.res["spec"] | ||
|
|
||
| if self.match_resources is not None: | ||
| _spec["matchResources"] = self.match_resources | ||
|
|
||
| if self.param_ref is not None: | ||
| _spec["paramRef"] = self.param_ref | ||
|
|
||
| if self.policy_name is not None: | ||
| _spec["policyName"] = self.policy_name | ||
|
|
||
| if self.validation_actions is not None: | ||
| _spec["validationActions"] = self.validation_actions | ||
|
|
||
| # End of generated code |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,54 @@ | ||
| import pytest | ||
|
|
||
| from ocp_resources.validating_admission_policy import ValidatingAdmissionPolicy | ||
|
|
||
|
|
||
| @pytest.mark.incremental | ||
| class TestValidatingAdmissionPolicy: | ||
| @pytest.fixture(scope="class") | ||
| def validatingadmissionpolicy(self, fake_client): | ||
| return ValidatingAdmissionPolicy( | ||
| client=fake_client, | ||
| name="test-validatingadmissionpolicy", | ||
| match_constraints={ | ||
| "resourceRules": [ | ||
| { | ||
| "apiGroups": [""], | ||
| "apiVersions": ["v1"], | ||
| "operations": ["CREATE", "UPDATE"], | ||
| "resources": ["pods"], | ||
| } | ||
| ], | ||
| }, | ||
| validations=[ | ||
| { | ||
| "expression": "object.metadata.name != 'forbidden'", | ||
| "message": "Resource name cannot be 'forbidden'", | ||
| } | ||
| ], | ||
| ) | ||
|
|
||
| def test_01_create_validatingadmissionpolicy(self, validatingadmissionpolicy): | ||
| """Test creating ValidatingAdmissionPolicy""" | ||
| deployed_resource = validatingadmissionpolicy.deploy() | ||
| assert deployed_resource | ||
| assert deployed_resource.name == "test-validatingadmissionpolicy" | ||
| assert validatingadmissionpolicy.exists | ||
RoniKishner marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| def test_02_get_validatingadmissionpolicy(self, validatingadmissionpolicy): | ||
| """Test getting ValidatingAdmissionPolicy""" | ||
| assert validatingadmissionpolicy.instance | ||
| assert validatingadmissionpolicy.kind == "ValidatingAdmissionPolicy" | ||
|
|
||
| def test_03_update_validatingadmissionpolicy(self, validatingadmissionpolicy): | ||
| """Test updating ValidatingAdmissionPolicy""" | ||
| resource_dict = validatingadmissionpolicy.instance.to_dict() | ||
| resource_dict["metadata"]["labels"] = {"updated": "true"} | ||
| validatingadmissionpolicy.update(resource_dict=resource_dict) | ||
| assert validatingadmissionpolicy.labels["updated"] == "true" | ||
|
|
||
| def test_04_delete_validatingadmissionpolicy(self, validatingadmissionpolicy): | ||
| """Test deleting ValidatingAdmissionPolicy""" | ||
| validatingadmissionpolicy.clean_up(wait=False) | ||
| # Verify resource no longer exists after deletion | ||
| assert not validatingadmissionpolicy.exists | ||
RoniKishner marked this conversation as resolved.
Show resolved
Hide resolved
|
||
39 changes: 39 additions & 0 deletions
39
tests/test_resources/test_validating_admission_policy_binding.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,39 @@ | ||
| import pytest | ||
|
|
||
| from ocp_resources.validating_admission_policy_binding import ValidatingAdmissionPolicyBinding | ||
|
|
||
|
|
||
| @pytest.mark.incremental | ||
| class TestValidatingAdmissionPolicyBinding: | ||
| @pytest.fixture(scope="class") | ||
| def validatingadmissionpolicybinding(self, fake_client): | ||
| return ValidatingAdmissionPolicyBinding( | ||
| client=fake_client, | ||
| name="test-validatingadmissionpolicybinding", | ||
| policy_name="test-validatingadmissionpolicy", | ||
| ) | ||
|
|
||
| def test_01_create_validatingadmissionpolicybinding(self, validatingadmissionpolicybinding): | ||
| """Test creating ValidatingAdmissionPolicyBinding""" | ||
| deployed_resource = validatingadmissionpolicybinding.deploy() | ||
| assert deployed_resource | ||
| assert deployed_resource.name == "test-validatingadmissionpolicybinding" | ||
| assert validatingadmissionpolicybinding.exists | ||
RoniKishner marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| def test_02_get_validatingadmissionpolicybinding(self, validatingadmissionpolicybinding): | ||
| """Test getting ValidatingAdmissionPolicyBinding""" | ||
| assert validatingadmissionpolicybinding.instance | ||
| assert validatingadmissionpolicybinding.kind == "ValidatingAdmissionPolicyBinding" | ||
|
|
||
| def test_03_update_validatingadmissionpolicybinding(self, validatingadmissionpolicybinding): | ||
| """Test updating ValidatingAdmissionPolicyBinding""" | ||
| resource_dict = validatingadmissionpolicybinding.instance.to_dict() | ||
| resource_dict["metadata"]["labels"] = {"updated": "true"} | ||
| validatingadmissionpolicybinding.update(resource_dict=resource_dict) | ||
| assert validatingadmissionpolicybinding.labels["updated"] == "true" | ||
|
|
||
| def test_04_delete_validatingadmissionpolicybinding(self, validatingadmissionpolicybinding): | ||
| """Test deleting ValidatingAdmissionPolicyBinding""" | ||
| validatingadmissionpolicybinding.clean_up(wait=False) | ||
| # Verify resource no longer exists after deletion | ||
| assert not validatingadmissionpolicybinding.exists | ||
RoniKishner marked this conversation as resolved.
Show resolved
Hide resolved
|
||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.