diff --git a/class_generator/schema/__resources-mappings.json.gz b/class_generator/schema/__resources-mappings.json.gz index 54e80ac191..40323f55ba 100644 Binary files a/class_generator/schema/__resources-mappings.json.gz and b/class_generator/schema/__resources-mappings.json.gz differ diff --git a/class_generator/tests/manifests/HTTPRoute/http_route.py b/class_generator/tests/manifests/HTTPRoute/http_route.py new file mode 100644 index 0000000000..7408a2e909 --- /dev/null +++ b/class_generator/tests/manifests/HTTPRoute/http_route.py @@ -0,0 +1,137 @@ +# Generated using https://github.com/RedHatQE/openshift-python-wrapper/blob/main/class_generator/README.md + + +from typing import Any + +from ocp_resources.resource import NamespacedResource + + +class HTTPRoute(NamespacedResource): + """ + HTTPRoute provides a way to route HTTP requests. This includes the capability + to match requests by hostname, path, header, or query param. Filters can be + used to specify additional processing steps. Backends specify where matching + requests should be routed. + """ + + api_group: str = NamespacedResource.ApiGroup.GATEWAY_NETWORKING_K8S_IO + + def __init__( + self, + hostnames: list[Any] | None = None, + parent_refs: list[Any] | None = None, + rules: list[Any] | None = None, + **kwargs: Any, + ) -> None: + r""" + Args: + hostnames (list[Any]): Hostnames defines a set of hostnames that should match against the + HTTP Host header to select a HTTPRoute used to process the + request. Implementations MUST ignore any port value specified in + the HTTP Host header while performing a match and (absent of any + applicable header modification configuration) MUST forward this + header unmodified to the backend. Valid values for Hostnames are + determined by RFC 1123 definition of a hostname with 2 notable + exceptions: 1. IPs are not allowed. 2. A hostname may be prefixed + with a wildcard label (`*.`). The wildcard label must appear by + itself as the first label. If a hostname is specified by both the + Listener and HTTPRoute, there must be at least one intersecting + hostname for the HTTPRoute to be attached to the Listener. For + example: * A Listener with `test.example.com` as the hostname + matches HTTPRoutes that have either not specified any hostnames, + or have specified at least one of `test.example.com` or + `*.example.com`. * A Listener with `*.example.com` as the hostname + matches HTTPRoutes that have either not specified any hostnames + or have specified at least one hostname that matches the + Listener hostname. For example, `*.example.com`, + `test.example.com`, and `foo.test.example.com` would all match. + On the other hand, `example.com` and `test.example.net` would + not match. Hostnames that are prefixed with a wildcard label + (`*.`) are interpreted as a suffix match. That means that a match + for `*.example.com` would match both `test.example.com`, and + `foo.test.example.com`, but not `example.com`. If both the + Listener and HTTPRoute have specified hostnames, any HTTPRoute + hostnames that do not match the Listener hostname MUST be ignored. + For example, if a Listener specified `*.example.com`, and the + HTTPRoute specified `test.example.com` and `test.example.net`, + `test.example.net` must not be considered for a match. If both + the Listener and HTTPRoute have specified hostnames, and none + match with the criteria above, then the HTTPRoute is not accepted. + The implementation must raise an 'Accepted' Condition with a + status of `False` in the corresponding RouteParentStatus. In the + event that multiple HTTPRoutes specify intersecting hostnames + (e.g. overlapping wildcard matching and exact matching hostnames), + precedence must be given to rules from the HTTPRoute with the + largest number of: * Characters in a matching non-wildcard + hostname. * Characters in a matching hostname. If ties exist + across multiple Routes, the matching precedence rules for + HTTPRouteMatches takes over. Support: Core + + parent_refs (list[Any]): ParentRefs references the resources (usually Gateways) that a Route + wants to be attached to. Note that the referenced parent resource + needs to allow this for the attachment to be complete. For + Gateways, that means the Gateway needs to allow attachment from + Routes of this kind and namespace. For Services, that means the + Service must either be in the same namespace for a "producer" + route, or the mesh implementation must support and allow + "consumer" routes for the referenced Service. ReferenceGrant is + not applicable for governing ParentRefs to Services - it is not + possible to create a "producer" route for a Service in a different + namespace from the Route. There are two kinds of parent resources + with "Core" support: * Gateway (Gateway conformance profile) * + Service (Mesh conformance profile, ClusterIP Services only) This + API may be extended in the future to support additional kinds of + parent resources. ParentRefs must be _distinct_. This means + either that: * They select different objects. If this is the + case, then parentRef entries are distinct. In terms of fields, + this means that the multi-part key defined by `group`, `kind`, + `namespace`, and `name` must be unique across all parentRef + entries in the Route. * They do not select different objects, but + for each optional field used, each ParentRef that selects the + same object must set the same set of optional fields to + different values. If one ParentRef sets a combination of + optional fields, all must set the same combination. Some + examples: * If one ParentRef sets `sectionName`, all ParentRefs + referencing the same object must also set `sectionName`. * If + one ParentRef sets `port`, all ParentRefs referencing the same + object must also set `port`. * If one ParentRef sets `sectionName` + and `port`, all ParentRefs referencing the same object must also + set `sectionName` and `port`. It is possible to separately + reference multiple distinct objects that may be collapsed by an + implementation. For example, some implementations may choose to + merge compatible Gateway Listeners together. If that is the case, + the list of routes attached to those resources should also be + merged. Note that for ParentRefs that cross namespace boundaries, + there are specific rules. Cross-namespace references are only + valid if they are explicitly allowed by something in the namespace + they are referring to. For example, Gateway has the AllowedRoutes + field, and ReferenceGrant provides a generic way to enable other + kinds of cross-namespace reference. + + rules (list[Any]): Rules are a list of HTTP matchers, filters and actions. + + """ + super().__init__(**kwargs) + + self.hostnames = hostnames + self.parent_refs = parent_refs + self.rules = rules + + 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.hostnames is not None: + _spec["hostnames"] = self.hostnames + + if self.parent_refs is not None: + _spec["parentRefs"] = self.parent_refs + + if self.rules is not None: + _spec["rules"] = self.rules + + # End of generated code diff --git a/class_generator/tests/manifests/InferencePool/inference_pool_inference_networking_k8s_io.py b/class_generator/tests/manifests/InferencePool/inference_pool_inference_networking_k8s_io.py new file mode 100644 index 0000000000..b3b8e37d50 --- /dev/null +++ b/class_generator/tests/manifests/InferencePool/inference_pool_inference_networking_k8s_io.py @@ -0,0 +1,79 @@ +# Generated using https://github.com/RedHatQE/openshift-python-wrapper/blob/main/class_generator/README.md + + +from typing import Any + +from ocp_resources.exceptions import MissingRequiredArgumentError +from ocp_resources.resource import NamespacedResource + + +class InferencePool(NamespacedResource): + """ + InferencePool is the Schema for the InferencePools API. + + """ + + api_group: str = NamespacedResource.ApiGroup.INFERENCE_NETWORKING_K8S_IO + + def __init__( + self, + app_protocol: str | None = None, + endpoint_picker_ref: dict[str, Any] | None = None, + selector: dict[str, Any] | None = None, + target_ports: list[Any] | None = None, + **kwargs: Any, + ) -> None: + r""" + Args: + app_protocol (str): AppProtocol describes the application protocol for all the target + ports. If unspecified, the protocol defaults to HTTP/1.1. + Supported values include: * "http": HTTP/1.1. This is the default. + * "kubernetes.io/h2c": HTTP/2 over cleartext. + + endpoint_picker_ref (dict[str, Any]): EndpointPickerRef is a reference to the Endpoint Picker extension and + its associated configuration. + + selector (dict[str, Any]): Selector determines which Pods are members of this inference pool. It + matches Pods by their labels only within the same namespace; + cross-namespace selection is not supported. The structure of this + LabelSelector is intentionally simple to be compatible with + Kubernetes Service selectors, as some implementations may + translate this configuration into a Service resource. + + target_ports (list[Any]): TargetPorts defines a list of ports that are exposed by this + InferencePool. Every port will be treated as a distinctive + endpoint by EPP, addressable as a 'podIP:portNumber' combination. + + """ + super().__init__(**kwargs) + + self.app_protocol = app_protocol + self.endpoint_picker_ref = endpoint_picker_ref + self.selector = selector + self.target_ports = target_ports + + def to_dict(self) -> None: + + super().to_dict() + + if not self.kind_dict and not self.yaml_file: + if self.endpoint_picker_ref is None: + raise MissingRequiredArgumentError(argument="self.endpoint_picker_ref") + + if self.selector is None: + raise MissingRequiredArgumentError(argument="self.selector") + + if self.target_ports is None: + raise MissingRequiredArgumentError(argument="self.target_ports") + + self.res["spec"] = {} + _spec = self.res["spec"] + + _spec["endpointPickerRef"] = self.endpoint_picker_ref + _spec["selector"] = self.selector + _spec["targetPorts"] = self.target_ports + + if self.app_protocol is not None: + _spec["appProtocol"] = self.app_protocol + + # End of generated code diff --git a/class_generator/tests/manifests/InferencePool/inference_pool_inference_networking_x_k8s_io.py b/class_generator/tests/manifests/InferencePool/inference_pool_inference_networking_x_k8s_io.py new file mode 100644 index 0000000000..3fc9662840 --- /dev/null +++ b/class_generator/tests/manifests/InferencePool/inference_pool_inference_networking_x_k8s_io.py @@ -0,0 +1,67 @@ +# Generated using https://github.com/RedHatQE/openshift-python-wrapper/blob/main/class_generator/README.md + + +from typing import Any + +from ocp_resources.exceptions import MissingRequiredArgumentError +from ocp_resources.resource import NamespacedResource + + +class InferencePool(NamespacedResource): + """ + InferencePool is the Schema for the InferencePools API. + """ + + api_group: str = NamespacedResource.ApiGroup.INFERENCE_NETWORKING_X_K8S_IO + + def __init__( + self, + extension_ref: dict[str, Any] | None = None, + selector: dict[str, Any] | None = None, + target_port_number: int | None = None, + **kwargs: Any, + ) -> None: + r""" + Args: + extension_ref (dict[str, Any]): Extension configures an endpoint picker as an extension service. + + selector (dict[str, Any]): Selector defines a map of labels to watch model server Pods that + should be included in the InferencePool. In some cases, + implementations may translate this field to a Service selector, so + this matches the simple map used for Service selectors instead of + the full Kubernetes LabelSelector type. If specified, it will be + applied to match the model server pods in the same namespace as + the InferencePool. Cross namesoace selector is not supported. + + target_port_number (int): TargetPortNumber defines the port number to access the selected model + server Pods. The number must be in the range 1 to 65535. + + """ + super().__init__(**kwargs) + + self.extension_ref = extension_ref + self.selector = selector + self.target_port_number = target_port_number + + def to_dict(self) -> None: + + super().to_dict() + + if not self.kind_dict and not self.yaml_file: + if self.extension_ref is None: + raise MissingRequiredArgumentError(argument="self.extension_ref") + + if self.selector is None: + raise MissingRequiredArgumentError(argument="self.selector") + + if self.target_port_number is None: + raise MissingRequiredArgumentError(argument="self.target_port_number") + + self.res["spec"] = {} + _spec = self.res["spec"] + + _spec["extensionRef"] = self.extension_ref + _spec["selector"] = self.selector + _spec["targetPortNumber"] = self.target_port_number + + # End of generated code diff --git a/class_generator/tests/manifests/Kuadrant/kuadrant.py b/class_generator/tests/manifests/Kuadrant/kuadrant.py new file mode 100644 index 0000000000..aa1377632c --- /dev/null +++ b/class_generator/tests/manifests/Kuadrant/kuadrant.py @@ -0,0 +1,60 @@ +# Generated using https://github.com/RedHatQE/openshift-python-wrapper/blob/main/class_generator/README.md + + +from typing import Any + +from ocp_resources.resource import NamespacedResource + + +class Kuadrant(NamespacedResource): + """ + Kuadrant configures installations of Kuadrant Service Protection components + """ + + api_group: str = NamespacedResource.ApiGroup.KUADRANT_IO + + def __init__( + self, + components: dict[str, Any] | None = None, + mtls: dict[str, Any] | None = None, + observability: dict[str, Any] | None = None, + **kwargs: Any, + ) -> None: + r""" + Args: + components (dict[str, Any]): Components configures optional Kuadrant components + + mtls (dict[str, Any]): MTLS is an optional entry which when enabled is set to true, kuadrant- + operator will add the configuration required to enable mTLS + between an Istio provided gateway and the Kuadrant components. + + observability (dict[str, Any]): Observability configures telemetry and monitoring settings for + Kuadrant components. When enabled, it configures logging, tracing, + and other observability features for both the control plane and + data plane components. + + """ + super().__init__(**kwargs) + + self.components = components + self.mtls = mtls + self.observability = observability + + 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.components is not None: + _spec["components"] = self.components + + if self.mtls is not None: + _spec["mtls"] = self.mtls + + if self.observability is not None: + _spec["observability"] = self.observability + + # End of generated code diff --git a/class_generator/tests/manifests/LLMInferenceService/llm_inference_service.py b/class_generator/tests/manifests/LLMInferenceService/llm_inference_service.py new file mode 100644 index 0000000000..612a4dec83 --- /dev/null +++ b/class_generator/tests/manifests/LLMInferenceService/llm_inference_service.py @@ -0,0 +1,132 @@ +# Generated using https://github.com/RedHatQE/openshift-python-wrapper/blob/main/class_generator/README.md + + +from typing import Any + +from ocp_resources.resource import NamespacedResource + + +class LLMInferenceService(NamespacedResource): + """ + No field description from API + """ + + api_group: str = NamespacedResource.ApiGroup.SERVING_KSERVE_IO + + def __init__( + self, + spec_annotations: dict[str, Any] | None = None, + base_refs: list[Any] | None = None, + kv_cache_offloading: dict[str, Any] | None = None, + spec_labels: dict[str, Any] | None = None, + model: dict[str, Any] | None = None, + parallelism: dict[str, Any] | None = None, + prefill: dict[str, Any] | None = None, + replicas: int | None = None, + router: dict[str, Any] | None = None, + scaling: dict[str, Any] | None = None, + storage_initializer: dict[str, Any] | None = None, + template: dict[str, Any] | None = None, + tracing: dict[str, Any] | None = None, + worker: dict[str, Any] | None = None, + **kwargs: Any, + ) -> None: + r""" + Args: + spec_annotations (dict[str, Any]): No field description from API + + base_refs (list[Any]): No field description from API + + kv_cache_offloading (dict[str, Any]): No field description from API + + spec_labels (dict[str, Any]): No field description from API + + model (dict[str, Any]): No field description from API + + parallelism (dict[str, Any]): No field description from API + + prefill (dict[str, Any]): No field description from API + + replicas (int): No field description from API + + router (dict[str, Any]): No field description from API + + scaling (dict[str, Any]): No field description from API + + storage_initializer (dict[str, Any]): No field description from API + + template (dict[str, Any]): No field description from API + + tracing (dict[str, Any]): No field description from API + + worker (dict[str, Any]): No field description from API + + """ + super().__init__(**kwargs) + + self.spec_annotations = spec_annotations + self.base_refs = base_refs + self.kv_cache_offloading = kv_cache_offloading + self.spec_labels = spec_labels + self.model = model + self.parallelism = parallelism + self.prefill = prefill + self.replicas = replicas + self.router = router + self.scaling = scaling + self.storage_initializer = storage_initializer + self.template = template + self.tracing = tracing + self.worker = worker + + 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.spec_annotations is not None: + _spec["annotations"] = self.spec_annotations + + if self.base_refs is not None: + _spec["baseRefs"] = self.base_refs + + if self.kv_cache_offloading is not None: + _spec["kvCacheOffloading"] = self.kv_cache_offloading + + if self.spec_labels is not None: + _spec["labels"] = self.spec_labels + + if self.model is not None: + _spec["model"] = self.model + + if self.parallelism is not None: + _spec["parallelism"] = self.parallelism + + if self.prefill is not None: + _spec["prefill"] = self.prefill + + if self.replicas is not None: + _spec["replicas"] = self.replicas + + if self.router is not None: + _spec["router"] = self.router + + if self.scaling is not None: + _spec["scaling"] = self.scaling + + if self.storage_initializer is not None: + _spec["storageInitializer"] = self.storage_initializer + + if self.template is not None: + _spec["template"] = self.template + + if self.tracing is not None: + _spec["tracing"] = self.tracing + + if self.worker is not None: + _spec["worker"] = self.worker + + # End of generated code diff --git a/class_generator/tests/manifests/LLMInferenceServiceConfig/llm_inference_service_config.py b/class_generator/tests/manifests/LLMInferenceServiceConfig/llm_inference_service_config.py new file mode 100644 index 0000000000..f58bf74e86 --- /dev/null +++ b/class_generator/tests/manifests/LLMInferenceServiceConfig/llm_inference_service_config.py @@ -0,0 +1,132 @@ +# Generated using https://github.com/RedHatQE/openshift-python-wrapper/blob/main/class_generator/README.md + + +from typing import Any + +from ocp_resources.resource import NamespacedResource + + +class LLMInferenceServiceConfig(NamespacedResource): + """ + No field description from API + """ + + api_group: str = NamespacedResource.ApiGroup.SERVING_KSERVE_IO + + def __init__( + self, + spec_annotations: dict[str, Any] | None = None, + base_refs: list[Any] | None = None, + kv_cache_offloading: dict[str, Any] | None = None, + spec_labels: dict[str, Any] | None = None, + model: dict[str, Any] | None = None, + parallelism: dict[str, Any] | None = None, + prefill: dict[str, Any] | None = None, + replicas: int | None = None, + router: dict[str, Any] | None = None, + scaling: dict[str, Any] | None = None, + storage_initializer: dict[str, Any] | None = None, + template: dict[str, Any] | None = None, + tracing: dict[str, Any] | None = None, + worker: dict[str, Any] | None = None, + **kwargs: Any, + ) -> None: + r""" + Args: + spec_annotations (dict[str, Any]): No field description from API + + base_refs (list[Any]): No field description from API + + kv_cache_offloading (dict[str, Any]): No field description from API + + spec_labels (dict[str, Any]): No field description from API + + model (dict[str, Any]): No field description from API + + parallelism (dict[str, Any]): No field description from API + + prefill (dict[str, Any]): No field description from API + + replicas (int): No field description from API + + router (dict[str, Any]): No field description from API + + scaling (dict[str, Any]): No field description from API + + storage_initializer (dict[str, Any]): No field description from API + + template (dict[str, Any]): No field description from API + + tracing (dict[str, Any]): No field description from API + + worker (dict[str, Any]): No field description from API + + """ + super().__init__(**kwargs) + + self.spec_annotations = spec_annotations + self.base_refs = base_refs + self.kv_cache_offloading = kv_cache_offloading + self.spec_labels = spec_labels + self.model = model + self.parallelism = parallelism + self.prefill = prefill + self.replicas = replicas + self.router = router + self.scaling = scaling + self.storage_initializer = storage_initializer + self.template = template + self.tracing = tracing + self.worker = worker + + 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.spec_annotations is not None: + _spec["annotations"] = self.spec_annotations + + if self.base_refs is not None: + _spec["baseRefs"] = self.base_refs + + if self.kv_cache_offloading is not None: + _spec["kvCacheOffloading"] = self.kv_cache_offloading + + if self.spec_labels is not None: + _spec["labels"] = self.spec_labels + + if self.model is not None: + _spec["model"] = self.model + + if self.parallelism is not None: + _spec["parallelism"] = self.parallelism + + if self.prefill is not None: + _spec["prefill"] = self.prefill + + if self.replicas is not None: + _spec["replicas"] = self.replicas + + if self.router is not None: + _spec["router"] = self.router + + if self.scaling is not None: + _spec["scaling"] = self.scaling + + if self.storage_initializer is not None: + _spec["storageInitializer"] = self.storage_initializer + + if self.template is not None: + _spec["template"] = self.template + + if self.tracing is not None: + _spec["tracing"] = self.tracing + + if self.worker is not None: + _spec["worker"] = self.worker + + # End of generated code diff --git a/class_generator/tests/manifests/LocalModelNamespaceCache/local_model_namespace_cache.py b/class_generator/tests/manifests/LocalModelNamespaceCache/local_model_namespace_cache.py new file mode 100644 index 0000000000..e4d17eb3d3 --- /dev/null +++ b/class_generator/tests/manifests/LocalModelNamespaceCache/local_model_namespace_cache.py @@ -0,0 +1,74 @@ +# Generated using https://github.com/RedHatQE/openshift-python-wrapper/blob/main/class_generator/README.md + + +from typing import Any + +from ocp_resources.exceptions import MissingRequiredArgumentError +from ocp_resources.resource import NamespacedResource + + +class LocalModelNamespaceCache(NamespacedResource): + """ + No field description from API + """ + + api_group: str = NamespacedResource.ApiGroup.SERVING_KSERVE_IO + + def __init__( + self, + model_size: Any | None = None, + node_groups: list[Any] | None = None, + service_account_name: str | None = None, + source_model_uri: str | None = None, + storage: dict[str, Any] | None = None, + **kwargs: Any, + ) -> None: + r""" + Args: + model_size (Any): No field description from API + + node_groups (list[Any]): No field description from API + + service_account_name (str): No field description from API + + source_model_uri (str): No field description from API + + storage (dict[str, Any]): No field description from API + + """ + super().__init__(**kwargs) + + self.model_size = model_size + self.node_groups = node_groups + self.service_account_name = service_account_name + self.source_model_uri = source_model_uri + self.storage = storage + + def to_dict(self) -> None: + + super().to_dict() + + if not self.kind_dict and not self.yaml_file: + if self.model_size is None: + raise MissingRequiredArgumentError(argument="self.model_size") + + if self.node_groups is None: + raise MissingRequiredArgumentError(argument="self.node_groups") + + if self.source_model_uri is None: + raise MissingRequiredArgumentError(argument="self.source_model_uri") + + self.res["spec"] = {} + _spec = self.res["spec"] + + _spec["modelSize"] = self.model_size + _spec["nodeGroups"] = self.node_groups + _spec["sourceModelUri"] = self.source_model_uri + + if self.service_account_name is not None: + _spec["serviceAccountName"] = self.service_account_name + + if self.storage is not None: + _spec["storage"] = self.storage + + # End of generated code diff --git a/class_generator/tests/test_class_generator.py b/class_generator/tests/test_class_generator.py index d74efbf3be..46709f21c0 100644 --- a/class_generator/tests/test_class_generator.py +++ b/class_generator/tests/test_class_generator.py @@ -95,16 +95,22 @@ def test_parse_explain(tmp_path: Path) -> None: "DNS", "Deployment", "ImageContentSourcePolicy", + "Ingress", "Machine", "NMState", - "Pod", - "Secret", - "ServiceMeshMember", - "Ingress", "OAuth", "Pipeline", + "Pod", "RouteAdvertisements", + "Secret", + "ServiceMeshMember", "ServingRuntime", + "LLMInferenceServiceConfig", + "LLMInferenceService", + "Kuadrant", + "HTTPRoute", + "InferencePool", + "LocalModelNamespaceCache", ] failures: list[tuple[str, str]] = [] diff --git a/ocp_resources/http_route.py b/ocp_resources/http_route.py new file mode 100644 index 0000000000..7408a2e909 --- /dev/null +++ b/ocp_resources/http_route.py @@ -0,0 +1,137 @@ +# Generated using https://github.com/RedHatQE/openshift-python-wrapper/blob/main/class_generator/README.md + + +from typing import Any + +from ocp_resources.resource import NamespacedResource + + +class HTTPRoute(NamespacedResource): + """ + HTTPRoute provides a way to route HTTP requests. This includes the capability + to match requests by hostname, path, header, or query param. Filters can be + used to specify additional processing steps. Backends specify where matching + requests should be routed. + """ + + api_group: str = NamespacedResource.ApiGroup.GATEWAY_NETWORKING_K8S_IO + + def __init__( + self, + hostnames: list[Any] | None = None, + parent_refs: list[Any] | None = None, + rules: list[Any] | None = None, + **kwargs: Any, + ) -> None: + r""" + Args: + hostnames (list[Any]): Hostnames defines a set of hostnames that should match against the + HTTP Host header to select a HTTPRoute used to process the + request. Implementations MUST ignore any port value specified in + the HTTP Host header while performing a match and (absent of any + applicable header modification configuration) MUST forward this + header unmodified to the backend. Valid values for Hostnames are + determined by RFC 1123 definition of a hostname with 2 notable + exceptions: 1. IPs are not allowed. 2. A hostname may be prefixed + with a wildcard label (`*.`). The wildcard label must appear by + itself as the first label. If a hostname is specified by both the + Listener and HTTPRoute, there must be at least one intersecting + hostname for the HTTPRoute to be attached to the Listener. For + example: * A Listener with `test.example.com` as the hostname + matches HTTPRoutes that have either not specified any hostnames, + or have specified at least one of `test.example.com` or + `*.example.com`. * A Listener with `*.example.com` as the hostname + matches HTTPRoutes that have either not specified any hostnames + or have specified at least one hostname that matches the + Listener hostname. For example, `*.example.com`, + `test.example.com`, and `foo.test.example.com` would all match. + On the other hand, `example.com` and `test.example.net` would + not match. Hostnames that are prefixed with a wildcard label + (`*.`) are interpreted as a suffix match. That means that a match + for `*.example.com` would match both `test.example.com`, and + `foo.test.example.com`, but not `example.com`. If both the + Listener and HTTPRoute have specified hostnames, any HTTPRoute + hostnames that do not match the Listener hostname MUST be ignored. + For example, if a Listener specified `*.example.com`, and the + HTTPRoute specified `test.example.com` and `test.example.net`, + `test.example.net` must not be considered for a match. If both + the Listener and HTTPRoute have specified hostnames, and none + match with the criteria above, then the HTTPRoute is not accepted. + The implementation must raise an 'Accepted' Condition with a + status of `False` in the corresponding RouteParentStatus. In the + event that multiple HTTPRoutes specify intersecting hostnames + (e.g. overlapping wildcard matching and exact matching hostnames), + precedence must be given to rules from the HTTPRoute with the + largest number of: * Characters in a matching non-wildcard + hostname. * Characters in a matching hostname. If ties exist + across multiple Routes, the matching precedence rules for + HTTPRouteMatches takes over. Support: Core + + parent_refs (list[Any]): ParentRefs references the resources (usually Gateways) that a Route + wants to be attached to. Note that the referenced parent resource + needs to allow this for the attachment to be complete. For + Gateways, that means the Gateway needs to allow attachment from + Routes of this kind and namespace. For Services, that means the + Service must either be in the same namespace for a "producer" + route, or the mesh implementation must support and allow + "consumer" routes for the referenced Service. ReferenceGrant is + not applicable for governing ParentRefs to Services - it is not + possible to create a "producer" route for a Service in a different + namespace from the Route. There are two kinds of parent resources + with "Core" support: * Gateway (Gateway conformance profile) * + Service (Mesh conformance profile, ClusterIP Services only) This + API may be extended in the future to support additional kinds of + parent resources. ParentRefs must be _distinct_. This means + either that: * They select different objects. If this is the + case, then parentRef entries are distinct. In terms of fields, + this means that the multi-part key defined by `group`, `kind`, + `namespace`, and `name` must be unique across all parentRef + entries in the Route. * They do not select different objects, but + for each optional field used, each ParentRef that selects the + same object must set the same set of optional fields to + different values. If one ParentRef sets a combination of + optional fields, all must set the same combination. Some + examples: * If one ParentRef sets `sectionName`, all ParentRefs + referencing the same object must also set `sectionName`. * If + one ParentRef sets `port`, all ParentRefs referencing the same + object must also set `port`. * If one ParentRef sets `sectionName` + and `port`, all ParentRefs referencing the same object must also + set `sectionName` and `port`. It is possible to separately + reference multiple distinct objects that may be collapsed by an + implementation. For example, some implementations may choose to + merge compatible Gateway Listeners together. If that is the case, + the list of routes attached to those resources should also be + merged. Note that for ParentRefs that cross namespace boundaries, + there are specific rules. Cross-namespace references are only + valid if they are explicitly allowed by something in the namespace + they are referring to. For example, Gateway has the AllowedRoutes + field, and ReferenceGrant provides a generic way to enable other + kinds of cross-namespace reference. + + rules (list[Any]): Rules are a list of HTTP matchers, filters and actions. + + """ + super().__init__(**kwargs) + + self.hostnames = hostnames + self.parent_refs = parent_refs + self.rules = rules + + 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.hostnames is not None: + _spec["hostnames"] = self.hostnames + + if self.parent_refs is not None: + _spec["parentRefs"] = self.parent_refs + + if self.rules is not None: + _spec["rules"] = self.rules + + # End of generated code diff --git a/ocp_resources/inference_pool_inference_networking_k8s_io.py b/ocp_resources/inference_pool_inference_networking_k8s_io.py new file mode 100644 index 0000000000..b3b8e37d50 --- /dev/null +++ b/ocp_resources/inference_pool_inference_networking_k8s_io.py @@ -0,0 +1,79 @@ +# Generated using https://github.com/RedHatQE/openshift-python-wrapper/blob/main/class_generator/README.md + + +from typing import Any + +from ocp_resources.exceptions import MissingRequiredArgumentError +from ocp_resources.resource import NamespacedResource + + +class InferencePool(NamespacedResource): + """ + InferencePool is the Schema for the InferencePools API. + + """ + + api_group: str = NamespacedResource.ApiGroup.INFERENCE_NETWORKING_K8S_IO + + def __init__( + self, + app_protocol: str | None = None, + endpoint_picker_ref: dict[str, Any] | None = None, + selector: dict[str, Any] | None = None, + target_ports: list[Any] | None = None, + **kwargs: Any, + ) -> None: + r""" + Args: + app_protocol (str): AppProtocol describes the application protocol for all the target + ports. If unspecified, the protocol defaults to HTTP/1.1. + Supported values include: * "http": HTTP/1.1. This is the default. + * "kubernetes.io/h2c": HTTP/2 over cleartext. + + endpoint_picker_ref (dict[str, Any]): EndpointPickerRef is a reference to the Endpoint Picker extension and + its associated configuration. + + selector (dict[str, Any]): Selector determines which Pods are members of this inference pool. It + matches Pods by their labels only within the same namespace; + cross-namespace selection is not supported. The structure of this + LabelSelector is intentionally simple to be compatible with + Kubernetes Service selectors, as some implementations may + translate this configuration into a Service resource. + + target_ports (list[Any]): TargetPorts defines a list of ports that are exposed by this + InferencePool. Every port will be treated as a distinctive + endpoint by EPP, addressable as a 'podIP:portNumber' combination. + + """ + super().__init__(**kwargs) + + self.app_protocol = app_protocol + self.endpoint_picker_ref = endpoint_picker_ref + self.selector = selector + self.target_ports = target_ports + + def to_dict(self) -> None: + + super().to_dict() + + if not self.kind_dict and not self.yaml_file: + if self.endpoint_picker_ref is None: + raise MissingRequiredArgumentError(argument="self.endpoint_picker_ref") + + if self.selector is None: + raise MissingRequiredArgumentError(argument="self.selector") + + if self.target_ports is None: + raise MissingRequiredArgumentError(argument="self.target_ports") + + self.res["spec"] = {} + _spec = self.res["spec"] + + _spec["endpointPickerRef"] = self.endpoint_picker_ref + _spec["selector"] = self.selector + _spec["targetPorts"] = self.target_ports + + if self.app_protocol is not None: + _spec["appProtocol"] = self.app_protocol + + # End of generated code diff --git a/ocp_resources/inference_pool_inference_networking_x_k8s_io.py b/ocp_resources/inference_pool_inference_networking_x_k8s_io.py new file mode 100644 index 0000000000..3fc9662840 --- /dev/null +++ b/ocp_resources/inference_pool_inference_networking_x_k8s_io.py @@ -0,0 +1,67 @@ +# Generated using https://github.com/RedHatQE/openshift-python-wrapper/blob/main/class_generator/README.md + + +from typing import Any + +from ocp_resources.exceptions import MissingRequiredArgumentError +from ocp_resources.resource import NamespacedResource + + +class InferencePool(NamespacedResource): + """ + InferencePool is the Schema for the InferencePools API. + """ + + api_group: str = NamespacedResource.ApiGroup.INFERENCE_NETWORKING_X_K8S_IO + + def __init__( + self, + extension_ref: dict[str, Any] | None = None, + selector: dict[str, Any] | None = None, + target_port_number: int | None = None, + **kwargs: Any, + ) -> None: + r""" + Args: + extension_ref (dict[str, Any]): Extension configures an endpoint picker as an extension service. + + selector (dict[str, Any]): Selector defines a map of labels to watch model server Pods that + should be included in the InferencePool. In some cases, + implementations may translate this field to a Service selector, so + this matches the simple map used for Service selectors instead of + the full Kubernetes LabelSelector type. If specified, it will be + applied to match the model server pods in the same namespace as + the InferencePool. Cross namesoace selector is not supported. + + target_port_number (int): TargetPortNumber defines the port number to access the selected model + server Pods. The number must be in the range 1 to 65535. + + """ + super().__init__(**kwargs) + + self.extension_ref = extension_ref + self.selector = selector + self.target_port_number = target_port_number + + def to_dict(self) -> None: + + super().to_dict() + + if not self.kind_dict and not self.yaml_file: + if self.extension_ref is None: + raise MissingRequiredArgumentError(argument="self.extension_ref") + + if self.selector is None: + raise MissingRequiredArgumentError(argument="self.selector") + + if self.target_port_number is None: + raise MissingRequiredArgumentError(argument="self.target_port_number") + + self.res["spec"] = {} + _spec = self.res["spec"] + + _spec["extensionRef"] = self.extension_ref + _spec["selector"] = self.selector + _spec["targetPortNumber"] = self.target_port_number + + # End of generated code diff --git a/ocp_resources/kuadrant.py b/ocp_resources/kuadrant.py new file mode 100644 index 0000000000..aa1377632c --- /dev/null +++ b/ocp_resources/kuadrant.py @@ -0,0 +1,60 @@ +# Generated using https://github.com/RedHatQE/openshift-python-wrapper/blob/main/class_generator/README.md + + +from typing import Any + +from ocp_resources.resource import NamespacedResource + + +class Kuadrant(NamespacedResource): + """ + Kuadrant configures installations of Kuadrant Service Protection components + """ + + api_group: str = NamespacedResource.ApiGroup.KUADRANT_IO + + def __init__( + self, + components: dict[str, Any] | None = None, + mtls: dict[str, Any] | None = None, + observability: dict[str, Any] | None = None, + **kwargs: Any, + ) -> None: + r""" + Args: + components (dict[str, Any]): Components configures optional Kuadrant components + + mtls (dict[str, Any]): MTLS is an optional entry which when enabled is set to true, kuadrant- + operator will add the configuration required to enable mTLS + between an Istio provided gateway and the Kuadrant components. + + observability (dict[str, Any]): Observability configures telemetry and monitoring settings for + Kuadrant components. When enabled, it configures logging, tracing, + and other observability features for both the control plane and + data plane components. + + """ + super().__init__(**kwargs) + + self.components = components + self.mtls = mtls + self.observability = observability + + 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.components is not None: + _spec["components"] = self.components + + if self.mtls is not None: + _spec["mtls"] = self.mtls + + if self.observability is not None: + _spec["observability"] = self.observability + + # End of generated code diff --git a/ocp_resources/llm_inference_service.py b/ocp_resources/llm_inference_service.py index 48eb2a784f..612a4dec83 100644 --- a/ocp_resources/llm_inference_service.py +++ b/ocp_resources/llm_inference_service.py @@ -7,26 +7,40 @@ class LLMInferenceService(NamespacedResource): - """ """ + """ + No field description from API + """ api_group: str = NamespacedResource.ApiGroup.SERVING_KSERVE_IO def __init__( self, + spec_annotations: dict[str, Any] | None = None, base_refs: list[Any] | None = None, + kv_cache_offloading: dict[str, Any] | None = None, + spec_labels: dict[str, Any] | None = None, model: dict[str, Any] | None = None, parallelism: dict[str, Any] | None = None, prefill: dict[str, Any] | None = None, replicas: int | None = None, router: dict[str, Any] | None = None, + scaling: dict[str, Any] | None = None, + storage_initializer: dict[str, Any] | None = None, template: dict[str, Any] | None = None, + tracing: dict[str, Any] | None = None, worker: dict[str, Any] | None = None, **kwargs: Any, ) -> None: r""" Args: + spec_annotations (dict[str, Any]): No field description from API + base_refs (list[Any]): No field description from API + kv_cache_offloading (dict[str, Any]): No field description from API + + spec_labels (dict[str, Any]): No field description from API + model (dict[str, Any]): No field description from API parallelism (dict[str, Any]): No field description from API @@ -37,32 +51,54 @@ def __init__( router (dict[str, Any]): No field description from API + scaling (dict[str, Any]): No field description from API + + storage_initializer (dict[str, Any]): No field description from API + template (dict[str, Any]): No field description from API + tracing (dict[str, Any]): No field description from API + worker (dict[str, Any]): No field description from API """ super().__init__(**kwargs) + self.spec_annotations = spec_annotations self.base_refs = base_refs + self.kv_cache_offloading = kv_cache_offloading + self.spec_labels = spec_labels self.model = model self.parallelism = parallelism self.prefill = prefill self.replicas = replicas self.router = router + self.scaling = scaling + self.storage_initializer = storage_initializer self.template = template + self.tracing = tracing self.worker = worker 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.spec_annotations is not None: + _spec["annotations"] = self.spec_annotations + if self.base_refs is not None: _spec["baseRefs"] = self.base_refs + if self.kv_cache_offloading is not None: + _spec["kvCacheOffloading"] = self.kv_cache_offloading + + if self.spec_labels is not None: + _spec["labels"] = self.spec_labels + if self.model is not None: _spec["model"] = self.model @@ -78,9 +114,18 @@ def to_dict(self) -> None: if self.router is not None: _spec["router"] = self.router + if self.scaling is not None: + _spec["scaling"] = self.scaling + + if self.storage_initializer is not None: + _spec["storageInitializer"] = self.storage_initializer + if self.template is not None: _spec["template"] = self.template + if self.tracing is not None: + _spec["tracing"] = self.tracing + if self.worker is not None: _spec["worker"] = self.worker diff --git a/ocp_resources/llm_inference_service_config.py b/ocp_resources/llm_inference_service_config.py new file mode 100644 index 0000000000..f58bf74e86 --- /dev/null +++ b/ocp_resources/llm_inference_service_config.py @@ -0,0 +1,132 @@ +# Generated using https://github.com/RedHatQE/openshift-python-wrapper/blob/main/class_generator/README.md + + +from typing import Any + +from ocp_resources.resource import NamespacedResource + + +class LLMInferenceServiceConfig(NamespacedResource): + """ + No field description from API + """ + + api_group: str = NamespacedResource.ApiGroup.SERVING_KSERVE_IO + + def __init__( + self, + spec_annotations: dict[str, Any] | None = None, + base_refs: list[Any] | None = None, + kv_cache_offloading: dict[str, Any] | None = None, + spec_labels: dict[str, Any] | None = None, + model: dict[str, Any] | None = None, + parallelism: dict[str, Any] | None = None, + prefill: dict[str, Any] | None = None, + replicas: int | None = None, + router: dict[str, Any] | None = None, + scaling: dict[str, Any] | None = None, + storage_initializer: dict[str, Any] | None = None, + template: dict[str, Any] | None = None, + tracing: dict[str, Any] | None = None, + worker: dict[str, Any] | None = None, + **kwargs: Any, + ) -> None: + r""" + Args: + spec_annotations (dict[str, Any]): No field description from API + + base_refs (list[Any]): No field description from API + + kv_cache_offloading (dict[str, Any]): No field description from API + + spec_labels (dict[str, Any]): No field description from API + + model (dict[str, Any]): No field description from API + + parallelism (dict[str, Any]): No field description from API + + prefill (dict[str, Any]): No field description from API + + replicas (int): No field description from API + + router (dict[str, Any]): No field description from API + + scaling (dict[str, Any]): No field description from API + + storage_initializer (dict[str, Any]): No field description from API + + template (dict[str, Any]): No field description from API + + tracing (dict[str, Any]): No field description from API + + worker (dict[str, Any]): No field description from API + + """ + super().__init__(**kwargs) + + self.spec_annotations = spec_annotations + self.base_refs = base_refs + self.kv_cache_offloading = kv_cache_offloading + self.spec_labels = spec_labels + self.model = model + self.parallelism = parallelism + self.prefill = prefill + self.replicas = replicas + self.router = router + self.scaling = scaling + self.storage_initializer = storage_initializer + self.template = template + self.tracing = tracing + self.worker = worker + + 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.spec_annotations is not None: + _spec["annotations"] = self.spec_annotations + + if self.base_refs is not None: + _spec["baseRefs"] = self.base_refs + + if self.kv_cache_offloading is not None: + _spec["kvCacheOffloading"] = self.kv_cache_offloading + + if self.spec_labels is not None: + _spec["labels"] = self.spec_labels + + if self.model is not None: + _spec["model"] = self.model + + if self.parallelism is not None: + _spec["parallelism"] = self.parallelism + + if self.prefill is not None: + _spec["prefill"] = self.prefill + + if self.replicas is not None: + _spec["replicas"] = self.replicas + + if self.router is not None: + _spec["router"] = self.router + + if self.scaling is not None: + _spec["scaling"] = self.scaling + + if self.storage_initializer is not None: + _spec["storageInitializer"] = self.storage_initializer + + if self.template is not None: + _spec["template"] = self.template + + if self.tracing is not None: + _spec["tracing"] = self.tracing + + if self.worker is not None: + _spec["worker"] = self.worker + + # End of generated code diff --git a/ocp_resources/local_model_namespace_cache.py b/ocp_resources/local_model_namespace_cache.py new file mode 100644 index 0000000000..e4d17eb3d3 --- /dev/null +++ b/ocp_resources/local_model_namespace_cache.py @@ -0,0 +1,74 @@ +# Generated using https://github.com/RedHatQE/openshift-python-wrapper/blob/main/class_generator/README.md + + +from typing import Any + +from ocp_resources.exceptions import MissingRequiredArgumentError +from ocp_resources.resource import NamespacedResource + + +class LocalModelNamespaceCache(NamespacedResource): + """ + No field description from API + """ + + api_group: str = NamespacedResource.ApiGroup.SERVING_KSERVE_IO + + def __init__( + self, + model_size: Any | None = None, + node_groups: list[Any] | None = None, + service_account_name: str | None = None, + source_model_uri: str | None = None, + storage: dict[str, Any] | None = None, + **kwargs: Any, + ) -> None: + r""" + Args: + model_size (Any): No field description from API + + node_groups (list[Any]): No field description from API + + service_account_name (str): No field description from API + + source_model_uri (str): No field description from API + + storage (dict[str, Any]): No field description from API + + """ + super().__init__(**kwargs) + + self.model_size = model_size + self.node_groups = node_groups + self.service_account_name = service_account_name + self.source_model_uri = source_model_uri + self.storage = storage + + def to_dict(self) -> None: + + super().to_dict() + + if not self.kind_dict and not self.yaml_file: + if self.model_size is None: + raise MissingRequiredArgumentError(argument="self.model_size") + + if self.node_groups is None: + raise MissingRequiredArgumentError(argument="self.node_groups") + + if self.source_model_uri is None: + raise MissingRequiredArgumentError(argument="self.source_model_uri") + + self.res["spec"] = {} + _spec = self.res["spec"] + + _spec["modelSize"] = self.model_size + _spec["nodeGroups"] = self.node_groups + _spec["sourceModelUri"] = self.source_model_uri + + if self.service_account_name is not None: + _spec["serviceAccountName"] = self.service_account_name + + if self.storage is not None: + _spec["storage"] = self.storage + + # End of generated code diff --git a/ocp_resources/resource.py b/ocp_resources/resource.py index 279b52cc94..f53d86e51f 100644 --- a/ocp_resources/resource.py +++ b/ocp_resources/resource.py @@ -524,6 +524,8 @@ class ApiGroup: IMAGE_OPENSHIFT_IO: str = "image.openshift.io" IMAGE_REGISTRY: str = "registry.redhat.io" IMAGEREGISTRY_OPERATOR_OPENSHIFT_IO: str = "imageregistry.operator.openshift.io" + INFERENCE_NETWORKING_K8S_IO: str = "inference.networking.k8s.io" + INFERENCE_NETWORKING_X_K8S_IO: str = "inference.networking.x-k8s.io" INSTANCETYPE_KUBEVIRT_IO: str = "instancetype.kubevirt.io" INTEGREATLY_ORG: str = "integreatly.org" JAEGERTRACING_IO = "jaegertracing.io"