Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
307,133 changes: 15,722 additions & 291,411 deletions class_generator/schema/_definitions.json

Large diffs are not rendered by default.

230 changes: 9 additions & 221 deletions class_generator/tests/manifests/Deployment/deployment.py

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,29 @@ def __init__(
) -> None:
r"""
Args:
default_backend (dict[str, Any]): resource apiGroup kind name service name port name number.

ingress_class_name (str): No field description from API

rules (list[Any]): host http paths backend resource apiGroup kind name service name port
name number path pathType enum: Exact, ImplementationSpecific,
Prefix.

tls (list[Any]): hosts secretName.
default_backend (dict[str, Any]): IngressBackend describes all endpoints for a given service and port.

ingress_class_name (str): ingressClassName is the name of an IngressClass cluster resource.
Ingress controller implementations use this field to know whether
they should be serving this Ingress resource, by a transitive
connection (controller -> IngressClass -> Ingress resource).
Although the `kubernetes.io/ingress.class` annotation (simple
constant name) was never formally defined, it was widely supported
by Ingress controllers to create a direct binding between Ingress
controller and Ingress resources. Newly created Ingress resources
should prefer using the field. However, even though the annotation
is officially deprecated, for backwards compatibility reasons,
ingress controllers should still honor that annotation if present.

rules (list[Any]): rules is a list of host rules used to configure the Ingress. If
unspecified, or no rule matches, all traffic is sent to the
default backend.

tls (list[Any]): tls represents the TLS configuration. Currently the Ingress only
supports a single TLS port, 443. If multiple members of this list
specify different hosts, they will be multiplexed on the same port
according to the hostname specified through the SNI TLS extension,
if the ingress controller fulfilling the ingress supports SNI.

"""
super().__init__(**kwargs)
Expand Down
341 changes: 92 additions & 249 deletions class_generator/tests/manifests/Pod/pod.py

Large diffs are not rendered by default.

10 changes: 6 additions & 4 deletions class_generator/tests/test_class_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,13 +96,13 @@ def test_parse_explain(tmp_path: Path) -> None:
"Deployment",
"ImageContentSourcePolicy",
"Machine",
"NMState",
"OAuth",
"Pipeline",
"Pod",
"Secret",
"NMState",
"ServiceMeshMember",
"ServingRuntime",
"OAuth",
"Pipeline",
"Ingress",
"RouteAdvertisements",
]
Expand Down Expand Up @@ -146,7 +146,9 @@ def create_test_task(kind: str) -> tuple[str, str] | None:

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

# Fail the test with summary - detailed output is already printed above
raise AssertionError(failure_summary)
Expand Down
124 changes: 124 additions & 0 deletions ocp_resources/validating_admission_policy.py
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
108 changes: 108 additions & 0 deletions ocp_resources/validating_admission_policy_binding.py
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
54 changes: 54 additions & 0 deletions tests/test_resources/test_validating_admission_policy.py
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

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
39 changes: 39 additions & 0 deletions tests/test_resources/test_validating_admission_policy_binding.py
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

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