From 62d35b20023951a7671cfa0180a9ab5ab6f63540 Mon Sep 17 00:00:00 2001 From: Dineth Date: Sun, 19 Jul 2026 00:56:36 +0530 Subject: [PATCH 01/12] feat: Add SubscriptionPlan and Subscription CRDs with webhook support - Introduced CustomResourceDefinitions for SubscriptionPlan and Subscription, enabling management of subscription plans and subscriptions within the WSO2 API Gateway. - Implemented a conversion webhook for the CRDs, allowing for seamless versioning and updates. - Enhanced the operator deployment to support webhook functionality, including dynamic port configuration and certificate management. - Added a service for the webhook to facilitate communication between the operator and the Kubernetes API. - Updated Helm chart values to include configuration options for enabling/disabling the webhook and setting certificate validity. --- kubernetes/gateway-operator/PROJECT | 20 + .../api/v1/apigateway_types.go | 285 ++ .../gateway-operator/api/v1/apikey_types.go | 125 + .../api/v1/certificate_types.go | 67 + .../gateway-operator/api/v1/common_types.go | 93 + .../gateway-operator/api/v1/conversion.go | 36 + .../api/v1/groupversion_info.go | 36 + .../api/v1/llmprovider_types.go | 202 ++ .../api/v1/llmprovidertemplate_types.go | 112 + .../gateway-operator/api/v1/llmproxy_types.go | 152 + .../gateway-operator/api/v1/mcp_types.go | 236 ++ .../api/v1/operation_match.go | 61 + .../gateway-operator/api/v1/policy_types.go | 96 + .../gateway-operator/api/v1/restapi_types.go | 402 +++ .../gateway-operator/api/v1/secret_types.go | 69 + .../api/v1/subscription_types.go | 88 + .../api/v1/subscriptionplan_types.go | 89 + .../api/v1/zz_generated.deepcopy.go | 2332 ++++++++++++++ .../api/v1alpha1/conversion.go | 289 ++ .../api/v1alpha1/conversion_test.go | 138 + kubernetes/gateway-operator/cmd/main.go | 39 +- ...way.api-platform.wso2.com_apigateways.yaml | 1373 +++++++- ...gateway.api-platform.wso2.com_apikeys.yaml | 231 +- ...way.api-platform.wso2.com_apipolicies.yaml | 173 +- ...ay.api-platform.wso2.com_certificates.yaml | 169 +- ...ay.api-platform.wso2.com_llmproviders.yaml | 394 ++- ...latform.wso2.com_llmprovidertemplates.yaml | 388 ++- ...eway.api-platform.wso2.com_llmproxies.yaml | 386 ++- ....api-platform.wso2.com_managedsecrets.yaml | 170 +- .../gateway.api-platform.wso2.com_mcps.yaml | 418 ++- ...ateway.api-platform.wso2.com_restapis.yaml | 437 ++- ...i-platform.wso2.com_subscriptionplans.yaml | 163 +- ...y.api-platform.wso2.com_subscriptions.yaml | 194 +- .../internal/auth/auth_helper.go | 2 +- .../controller/apigateway_controller.go | 2 +- .../internal/controller/apikey_controller.go | 2 +- .../controller/apikey_external_deps_test.go | 2 +- .../controller/certificate_controller.go | 2 +- .../internal/controller/gateway_infra.go | 2 +- .../internal/controller/generic_reconciler.go | 2 +- .../internal/controller/httproute_compile.go | 2 +- .../httproute_confighash_stability_test.go | 2 +- .../controller/httproute_controller.go | 2 +- .../httproute_direct_response_policy.go | 2 +- .../httproute_direct_response_policy_test.go | 2 +- .../internal/controller/httproute_enqueue.go | 2 +- .../controller/httproute_enqueue_test.go | 2 +- .../internal/controller/httproute_filters.go | 2 +- .../internal/controller/httproute_mapper.go | 2 +- .../controller/httproute_mapper_test.go | 2 +- .../controller/httproute_match_emit_test.go | 2 +- .../internal/controller/httproute_policies.go | 2 +- .../httproute_policy_params_resolve.go | 2 +- .../httproute_policy_params_resolve_test.go | 2 +- .../controller/httproute_redirect_policy.go | 2 +- .../httproute_redirect_policy_test.go | 2 +- .../controller/k8s_gateway_controller.go | 2 +- .../controller/llmprovider_controller.go | 2 +- .../llmprovidertemplate_controller.go | 2 +- .../controller/llmproxy_controller.go | 2 +- .../controller/llmproxy_controller_test.go | 2 +- .../controller/managedsecret_controller.go | 2 +- .../controller/management_llm_enqueue.go | 2 +- .../management_resources_helpers.go | 2 +- .../management_upstream_auth_payload_test.go | 2 +- .../management_valuefrom_enqueue.go | 2 +- .../management_valuefrom_fingerprint.go | 2 +- .../management_valuefrom_fingerprint_test.go | 2 +- .../internal/controller/mcp_controller.go | 2 +- .../controller/payload_metadata_test.go | 2 +- .../internal/controller/restapi_controller.go | 2 +- .../internal/controller/restapi_enqueue.go | 2 +- .../controller/restapi_enqueue_test.go | 2 +- .../controller/restapi_policy_valuefrom.go | 2 +- .../restapi_policy_valuefrom_test.go | 2 +- .../internal/controller/serialization_test.go | 2 +- .../controller/subscription_controller.go | 2 +- .../subscription_external_deps_test.go | 2 +- .../controller/subscriptionplan_controller.go | 2 +- .../gatewayclient/envelope_payload_test.go | 2 +- .../internal/gatewayclient/rest_api.go | 2 +- .../internal/gatewayclient/yaml_payload.go | 2 +- .../gatewayclient/yaml_payload_test.go | 2 +- .../k8sutil/examples/template_usage.go | 2 +- .../internal/registry/gateway_registry.go | 2 +- .../internal/secretsource/resolver.go | 2 +- .../internal/secretsource/resolver_test.go | 2 +- .../internal/selector/api_selector.go | 2 +- ...way.api-platform.wso2.com_apigateways.yaml | 1386 --------- ...ay.api-platform.wso2.com_llmproviders.yaml | 410 --- .../gateway.api-platform.wso2.com_mcps.yaml | 434 --- ...ateway.api-platform.wso2.com_restapis.yaml | 360 --- ...way.api-platform.wso2.com_apigateways.yaml | 2758 +++++++++++++++++ ...gateway.api-platform.wso2.com_apikeys.yaml | 231 +- ...way.api-platform.wso2.com_apipolicies.yaml | 173 +- ...ay.api-platform.wso2.com_certificates.yaml | 169 +- ...ay.api-platform.wso2.com_llmproviders.yaml | 802 +++++ ...latform.wso2.com_llmprovidertemplates.yaml | 388 ++- ...eway.api-platform.wso2.com_llmproxies.yaml | 386 ++- ....api-platform.wso2.com_managedsecrets.yaml | 170 +- .../gateway.api-platform.wso2.com_mcps.yaml | 850 +++++ ...ateway.api-platform.wso2.com_restapis.yaml | 886 ++++++ ...i-platform.wso2.com_subscriptionplans.yaml | 163 +- ...y.api-platform.wso2.com_subscriptions.yaml | 194 +- .../templates/deployment.yaml | 22 +- .../templates/operator-crds.yaml | 75 + .../templates/webhook-service.yaml | 22 + .../helm/operator-helm-chart/values.yaml | 12 + 108 files changed, 16797 insertions(+), 2667 deletions(-) create mode 100644 kubernetes/gateway-operator/api/v1/apigateway_types.go create mode 100644 kubernetes/gateway-operator/api/v1/apikey_types.go create mode 100644 kubernetes/gateway-operator/api/v1/certificate_types.go create mode 100644 kubernetes/gateway-operator/api/v1/common_types.go create mode 100644 kubernetes/gateway-operator/api/v1/conversion.go create mode 100644 kubernetes/gateway-operator/api/v1/groupversion_info.go create mode 100644 kubernetes/gateway-operator/api/v1/llmprovider_types.go create mode 100644 kubernetes/gateway-operator/api/v1/llmprovidertemplate_types.go create mode 100644 kubernetes/gateway-operator/api/v1/llmproxy_types.go create mode 100644 kubernetes/gateway-operator/api/v1/mcp_types.go create mode 100644 kubernetes/gateway-operator/api/v1/operation_match.go create mode 100644 kubernetes/gateway-operator/api/v1/policy_types.go create mode 100644 kubernetes/gateway-operator/api/v1/restapi_types.go create mode 100644 kubernetes/gateway-operator/api/v1/secret_types.go create mode 100644 kubernetes/gateway-operator/api/v1/subscription_types.go create mode 100644 kubernetes/gateway-operator/api/v1/subscriptionplan_types.go create mode 100644 kubernetes/gateway-operator/api/v1/zz_generated.deepcopy.go create mode 100644 kubernetes/gateway-operator/api/v1alpha1/conversion.go create mode 100644 kubernetes/gateway-operator/api/v1alpha1/conversion_test.go delete mode 100644 kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_apigateways.yaml delete mode 100644 kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmproviders.yaml delete mode 100644 kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_mcps.yaml delete mode 100644 kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_restapis.yaml create mode 100644 kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_apigateways.yaml rename kubernetes/helm/operator-helm-chart/{crds => files/operator-crds}/gateway.api-platform.wso2.com_apikeys.yaml (50%) rename kubernetes/helm/operator-helm-chart/{crds => files/operator-crds}/gateway.api-platform.wso2.com_apipolicies.yaml (51%) rename kubernetes/helm/operator-helm-chart/{crds => files/operator-crds}/gateway.api-platform.wso2.com_certificates.yaml (51%) create mode 100644 kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_llmproviders.yaml rename kubernetes/helm/operator-helm-chart/{crds => files/operator-crds}/gateway.api-platform.wso2.com_llmprovidertemplates.yaml (50%) rename kubernetes/helm/operator-helm-chart/{crds => files/operator-crds}/gateway.api-platform.wso2.com_llmproxies.yaml (50%) rename kubernetes/helm/operator-helm-chart/{crds => files/operator-crds}/gateway.api-platform.wso2.com_managedsecrets.yaml (51%) create mode 100644 kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_mcps.yaml create mode 100644 kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_restapis.yaml rename kubernetes/helm/operator-helm-chart/{crds => files/operator-crds}/gateway.api-platform.wso2.com_subscriptionplans.yaml (51%) rename kubernetes/helm/operator-helm-chart/{crds => files/operator-crds}/gateway.api-platform.wso2.com_subscriptions.yaml (51%) create mode 100644 kubernetes/helm/operator-helm-chart/templates/operator-crds.yaml create mode 100644 kubernetes/helm/operator-helm-chart/templates/webhook-service.yaml diff --git a/kubernetes/gateway-operator/PROJECT b/kubernetes/gateway-operator/PROJECT index 5380ec5106..5e369fe476 100644 --- a/kubernetes/gateway-operator/PROJECT +++ b/kubernetes/gateway-operator/PROJECT @@ -14,6 +14,16 @@ resources: controller: true domain: gateway.api-platform.wso2.com kind: RestApi + path: github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1 + version: v1 + webhooks: + conversion: true + webhookVersion: v1 +- api: + crdVersion: v1 + namespaced: true + domain: gateway.api-platform.wso2.com + kind: RestApi path: github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1 version: v1alpha1 - api: @@ -22,6 +32,16 @@ resources: controller: true domain: gateway.api-platform.wso2.com kind: APIGateway + path: github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1 + version: v1 + webhooks: + conversion: true + webhookVersion: v1 +- api: + crdVersion: v1 + namespaced: true + domain: gateway.api-platform.wso2.com + kind: APIGateway path: github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1 version: v1alpha1 version: "3" diff --git a/kubernetes/gateway-operator/api/v1/apigateway_types.go b/kubernetes/gateway-operator/api/v1/apigateway_types.go new file mode 100644 index 0000000000..fe8a06bcf4 --- /dev/null +++ b/kubernetes/gateway-operator/api/v1/apigateway_types.go @@ -0,0 +1,285 @@ +/* +Copyright 2025. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN! +// NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. + +// APISelectorScope defines the scope of API selection for a gateway +// +kubebuilder:validation:Enum=Cluster;Namespaced;LabelSelector +type APISelectorScope string + +const ( + // ClusterScope means the gateway accepts APIs from any namespace + ClusterScope APISelectorScope = "Cluster" + + // NamespacedScope means the gateway only accepts APIs from specific namespaces + NamespacedScope APISelectorScope = "Namespaced" + + // LabelSelectorScope means the gateway accepts APIs matching specific labels + LabelSelectorScope APISelectorScope = "LabelSelector" +) + +// APISelector defines how a gateway selects which APIs to route +type APISelector struct { + // Scope determines the API selection strategy + // +kubebuilder:validation:Required + // +kubebuilder:default=Cluster + Scope APISelectorScope `json:"scope"` + + // Namespaces is a list of namespaces from which APIs are selected. + // Only used when Scope is "Namespaced". + // If empty with Namespaced scope, only APIs in the gateway's namespace are selected. + // +optional + Namespaces []string `json:"namespaces,omitempty"` + + // MatchLabels is a map of {key,value} pairs for label-based selection. + // Only used when Scope is "LabelSelector". + // An API must have all specified labels to be selected. + // +optional + MatchLabels map[string]string `json:"matchLabels,omitempty"` + + // MatchExpressions is a list of label selector requirements for label-based selection. + // Only used when Scope is "LabelSelector". + // +optional + MatchExpressions []metav1.LabelSelectorRequirement `json:"matchExpressions,omitempty"` +} + +// GatewayInfrastructure defines the infrastructure configuration for the gateway +type GatewayInfrastructure struct { + // Replicas is the number of gateway instances to deploy + // +kubebuilder:validation:Minimum=1 + // +kubebuilder:default=1 + // +optional + Replicas *int32 `json:"replicas,omitempty"` + + // Resources defines the compute resources for gateway pods + // +optional + Resources *corev1.ResourceRequirements `json:"resources,omitempty"` + + // Image is the container image for the gateway + // +optional + Image string `json:"image,omitempty"` + + // RouterImage is the container image for the router/proxy + // +optional + RouterImage string `json:"routerImage,omitempty"` + + // NodeSelector is a selector for node assignment + // +optional + NodeSelector map[string]string `json:"nodeSelector,omitempty"` + + // Tolerations for pod assignment + // +optional + Tolerations []corev1.Toleration `json:"tolerations,omitempty"` + + // Affinity for pod assignment + // +optional + Affinity *corev1.Affinity `json:"affinity,omitempty"` + + // Labels are custom labels propagated to all gateway-managed resources: + // Deployment metadata, Pod labels, Service metadata, and ConfigMaps. + // +optional + Labels map[string]string `json:"labels,omitempty"` + + // Annotations are custom annotations propagated to all gateway-managed resources: + // Deployment metadata, Pod annotations, Service metadata, and ConfigMaps. + // +optional + Annotations map[string]string `json:"annotations,omitempty"` +} + +// GatewaySpec defines the desired state of APIGateway +type GatewaySpec struct { + // APISelector defines how this gateway selects which APIs to route + // +kubebuilder:validation:Required + APISelector APISelector `json:"apiSelector"` + + // Infrastructure defines the deployment configuration for the gateway + // +optional + Infrastructure *GatewayInfrastructure `json:"infrastructure,omitempty"` + + // ControlPlane defines the control plane connection settings + // +optional + ControlPlane *GatewayControlPlane `json:"controlPlane,omitempty"` + + // Storage defines the storage configuration for the gateway + // +optional + Storage *GatewayStorage `json:"storage,omitempty"` + + // ConfigRef references a ConfigMap containing custom Helm values configuration. + // The ConfigMap data should contain a key "values.yaml" with the Helm values content. + // If not specified, the operator will use the default mounted configuration. + // +optional + ConfigRef *corev1.LocalObjectReference `json:"configRef,omitempty"` +} + +// GatewayControlPlane defines control plane connection settings +type GatewayControlPlane struct { + // Host is the control plane host address + // +optional + Host string `json:"host,omitempty"` + + // TokenSecretRef references a secret containing the authentication token + // +optional + TokenSecretRef *corev1.SecretKeySelector `json:"tokenSecretRef,omitempty"` + + // TLS settings for control plane connection + // +optional + TLS *GatewayTLSConfig `json:"tls,omitempty"` +} + +// GatewayTLSConfig defines TLS configuration +type GatewayTLSConfig struct { + // Enabled indicates whether TLS is enabled + // +kubebuilder:default=true + // +optional + Enabled *bool `json:"enabled,omitempty"` + + // CertSecretRef references a secret containing TLS certificates + // +optional + CertSecretRef *corev1.SecretKeySelector `json:"certSecretRef,omitempty"` +} + +// GatewayStorage defines storage configuration +type GatewayStorage struct { + // Type is the storage backend type (sqlite, postgres, mysql, etc.) + // +kubebuilder:validation:Enum=sqlite;postgres;mysql + // +kubebuilder:default=sqlite + // +optional + Type string `json:"type,omitempty"` + + // SQLitePath is the path for SQLite database (used when Type is sqlite) + // +optional + SQLitePath string `json:"sqlitePath,omitempty"` + + // ConnectionSecretRef references a secret containing database connection details + // (used for postgres, mysql, etc.) + // +optional + ConnectionSecretRef *corev1.SecretKeySelector `json:"connectionSecretRef,omitempty"` +} + +// Condition Types for Gateway +const ( + // GatewayConditionAccepted indicates the CR passed validation and is accepted for processing + GatewayConditionAccepted = "Accepted" + // GatewayConditionProgrammed indicates the Gateway is successfully deployed/programmed + GatewayConditionProgrammed = "Programmed" + // GatewayConditionReady is the canonical Ready condition type for Gateway (retained for compatibility) + GatewayConditionReady = "Ready" +) + +// Accepted Condition Reasons +const ( + // GatewayAcceptedReasonAccepted indicates the CR passed validation + GatewayAcceptedReasonAccepted = "Accepted" + // GatewayAcceptedReasonInvalidConfiguration indicates the CR failed validation + GatewayAcceptedReasonInvalidConfiguration = "InvalidConfiguration" + // GatewayAcceptedReasonPending indicates validation is pending + GatewayAcceptedReasonPending = "Pending" +) + +// Programmed Condition Reasons +const ( + // GatewayProgrammedReasonProgrammed indicates successful deployment + GatewayProgrammedReasonProgrammed = "Programmed" + // GatewayProgrammedReasonPending indicates deployment is pending + GatewayProgrammedReasonPending = "Pending" + // GatewayProgrammedReasonInvalid indicates configuration is invalid for deployment + GatewayProgrammedReasonInvalid = "Invalid" + // GatewayProgrammedReasonDeploymentFailed indicates deployment failed (non-retryable) + GatewayProgrammedReasonDeploymentFailed = "DeploymentFailed" + // GatewayProgrammedReasonRetrying indicates deployment failed and is being retried + GatewayProgrammedReasonRetrying = "Retrying" +) + +// GatewayPhase represents the lifecycle phase of a Gateway +// +kubebuilder:validation:Enum=Reconciling;Ready;Failed;Deleting +type GatewayPhase string + +const ( + // GatewayPhaseReconciling indicates the controller is reconciling resources + GatewayPhaseReconciling GatewayPhase = "Reconciling" + // GatewayPhaseReady indicates the gateway is fully reconciled + GatewayPhaseReady GatewayPhase = "Ready" + // GatewayPhaseFailed indicates the gateway failed to reconcile + GatewayPhaseFailed GatewayPhase = "Failed" + // GatewayPhaseDeleting indicates the gateway is being deleted and cleanup is running + GatewayPhaseDeleting GatewayPhase = "Deleting" +) + +// GatewayStatus defines the observed state of APIGateway +type GatewayStatus struct { + // Conditions represent the latest available observations of the gateway's state + // +optional + Conditions []metav1.Condition `json:"conditions,omitempty"` + + // Phase represents the current phase of the gateway (Pending, Ready, Failed) + // +optional + Phase GatewayPhase `json:"phase,omitempty"` + + // SelectedAPIs is the count of APIs currently selected by this gateway + // +optional + SelectedAPIs int `json:"selectedAPIs,omitempty"` + + // ObservedGeneration reflects the generation of the most recently observed spec + // +optional + ObservedGeneration int64 `json:"observedGeneration,omitempty"` + + // AppliedGeneration tracks the latest spec generation that was successfully applied to the cluster + // +optional + AppliedGeneration int64 `json:"appliedGeneration,omitempty"` + + // LastUpdateTime is the last time the status was updated + // +optional + LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"` + + // ConfigHash represents the hash of the referenced configuration + // used to detect changes in ConfigMap content + // +optional + ConfigHash string `json:"configHash,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:storageversion +//+kubebuilder:subresource:status + +// APIGateway is the Schema for the apigateways API +type APIGateway struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec GatewaySpec `json:"spec,omitempty"` + Status GatewayStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// APIGatewayList contains a list of APIGateway +type APIGatewayList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []APIGateway `json:"items"` +} + +func init() { + SchemeBuilder.Register(&APIGateway{}, &APIGatewayList{}) +} diff --git a/kubernetes/gateway-operator/api/v1/apikey_types.go b/kubernetes/gateway-operator/api/v1/apikey_types.go new file mode 100644 index 0000000000..cd3eec6e33 --- /dev/null +++ b/kubernetes/gateway-operator/api/v1/apikey_types.go @@ -0,0 +1,125 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// ApiKeyParentRef identifies the parent resource that owns this API key. +// Supported parents map to nested management-API paths: +// +// - RestApi -> /rest-apis/{name}/api-keys/... +// - LlmProvider -> /llm-providers/{name}/api-keys/... +// - LlmProxy -> /llm-proxies/{name}/api-keys/... +type ApiKeyParentRef struct { + // Kind selects the parent resource kind. + // +kubebuilder:validation:Required + // +kubebuilder:validation:Enum=RestApi;LlmProvider;LlmProxy + Kind string `json:"kind"` + + // Name is the parent resource handle (metadata.name). + // +kubebuilder:validation:Required + Name string `json:"name"` +} + +// ApiKeyExpiry describes an expiration duration for the API key. +type ApiKeyExpiry struct { + // Duration is the magnitude of the expiry duration (must be positive). + // +kubebuilder:validation:Required + // +kubebuilder:validation:Minimum=1 + Duration int64 `json:"duration"` + + // Unit is the time unit of the expiry duration. + // +kubebuilder:validation:Required + // +kubebuilder:validation:Enum=seconds;minutes;hours;days;weeks;months + Unit string `json:"unit"` +} + +// ApiKeySpec mirrors the management-API APIKeyCreationRequest payload, with +// the optional inline ApiKey expressed as a SecretValueSource for external- +// key injection (so the value need not be inlined in the CR). +// +kubebuilder:validation:XValidation:rule="!has(self.expiresAt) || !has(self.expiresIn)",message="expiresAt and expiresIn are mutually exclusive" +type ApiKeySpec struct { + // ParentRef identifies the resource the key is issued under. + // +kubebuilder:validation:Required + ParentRef ApiKeyParentRef `json:"parentRef"` + + // DisplayName is a human-readable label for the key. + // +optional + DisplayName *string `json:"displayName,omitempty"` + + // ApiKey is an optional pre-generated key value (>= 36 chars). When + // supplied the gateway hashes the value rather than generating its own. + // +optional + ApiKey *SecretValueSource `json:"apiKey,omitempty"` + + // MaskedApiKey is an optional masked rendering of an externally + // generated key, used purely for display by portals. + // +optional + MaskedApiKey *string `json:"maskedApiKey,omitempty"` + + // ExpiresIn is an optional duration after which the key expires. + // Mutually exclusive with expiresAt: the ApiKey spec CEL rule + // "!has(self.expiresAt) || !has(self.expiresIn)" rejects manifests that set both. + // +optional + ExpiresIn *ApiKeyExpiry `json:"expiresIn,omitempty"` + + // ExpiresAt is an optional absolute expiry time. + // Mutually exclusive with expiresIn: the ApiKey spec CEL rule + // "!has(self.expiresAt) || !has(self.expiresIn)" rejects manifests that set both. + // +optional + ExpiresAt *metav1.Time `json:"expiresAt,omitempty"` + + // Issuer optionally constrains regeneration to a single portal. + // +optional + Issuer *string `json:"issuer,omitempty"` + + // ExternalRefId is an optional reference id for tracing. + // +optional + ExternalRefId *string `json:"externalRefId,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:storageversion +//+kubebuilder:subresource:status +//+kubebuilder:resource:path=apikeys,singular=apikey,shortName=apik + +// ApiKey is the Schema for the apikeys API. +// +// The key handle in the management API is the CR's metadata.name. The +// nested REST path is built from spec.parentRef.kind + spec.parentRef.name. +type ApiKey struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ApiKeySpec `json:"spec,omitempty"` + Status ResourceStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// ApiKeyList contains a list of ApiKey. +type ApiKeyList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ApiKey `json:"items"` +} + +func init() { + SchemeBuilder.Register(&ApiKey{}, &ApiKeyList{}) +} diff --git a/kubernetes/gateway-operator/api/v1/certificate_types.go b/kubernetes/gateway-operator/api/v1/certificate_types.go new file mode 100644 index 0000000000..75d9486bec --- /dev/null +++ b/kubernetes/gateway-operator/api/v1/certificate_types.go @@ -0,0 +1,67 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// CertificateSpec mirrors the management-API CertificateUploadRequest, with +// the PEM bytes expressed as a SecretValueSource so production-grade +// certificates can be referenced from a Kubernetes Secret rather than +// inlined into the CR. +// +// The gateway-controller assigns a UUID id on first upload that the +// controller persists to .status.id; subsequent reconcile uses +// `/certificates/{status.id}` for PUT/DELETE. +type CertificateSpec struct { + // DisplayName is a human-readable certificate name. The controller + // passes it through to the management API as `name`. + // +kubebuilder:validation:Required + DisplayName string `json:"displayName"` + + // Certificate is the PEM-encoded X.509 certificate (single or bundle). + // +kubebuilder:validation:Required + Certificate SecretValueSource `json:"certificate"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:storageversion +//+kubebuilder:subresource:status +//+kubebuilder:resource:path=certificates,singular=certificate,shortName=cert + +// Certificate is the Schema for the certificates API. +type Certificate struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec CertificateSpec `json:"spec,omitempty"` + Status ResourceStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// CertificateList contains a list of Certificate. +type CertificateList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Certificate `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Certificate{}, &CertificateList{}) +} diff --git a/kubernetes/gateway-operator/api/v1/common_types.go b/kubernetes/gateway-operator/api/v1/common_types.go new file mode 100644 index 0000000000..1bf37dfccf --- /dev/null +++ b/kubernetes/gateway-operator/api/v1/common_types.go @@ -0,0 +1,93 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// SecretValueSource carries a sensitive string that may be either provided +// inline or sourced from a Kubernetes Secret. +// +// Exactly one of Value or ValueFrom must be set; controllers reject CRs that +// set neither or both. +// +// +kubebuilder:validation:XValidation:rule="has(self.value) != has(self.valueFrom)",message="exactly one of value or valueFrom must be set" +type SecretValueSource struct { + // Value is the inline plaintext value. Avoid for production use; prefer + // ValueFrom so the secret is stored in a Kubernetes Secret. + // +optional + Value *string `json:"value,omitempty"` + + // ValueFrom selects a key from a Kubernetes Secret in the same namespace + // as the owning CR. + // +optional + ValueFrom *corev1.SecretKeySelector `json:"valueFrom,omitempty"` +} + +// ResourceStatus carries the controller-managed lifecycle fields shared by +// the new management-API CRDs. +// +// For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the +// gateway-controller assigns Id on first deploy; controllers persist it and +// use it to address the resource for subsequent update/delete calls. +type ResourceStatus struct { + // Conditions represent the latest available observations of the + // resource's state. The standard types are Accepted and Programmed. + // +listType=map + // +listMapKey=type + // +optional + Conditions []metav1.Condition `json:"conditions,omitempty"` + + // Id is the gateway-issued identifier for UUID-keyed resources. When + // set the controller addresses the resource via PUT/DELETE //{id}. + // +optional + Id string `json:"id,omitempty"` + + // LastUpdateTime is the last time the status was updated. + // +optional + LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"` +} + +// Common condition types shared across the new management-API CRDs. They +// mirror the constants on RestApi so operators can reuse the same logic. +const ( + // ConditionAccepted indicates the CR passed validation and is accepted + // for processing. + ConditionAccepted = "Accepted" + // ConditionProgrammed indicates the resource is successfully deployed + // to the gateway. + ConditionProgrammed = "Programmed" +) + +// Accepted condition reasons. +const ( + ReasonAccepted = "Accepted" + ReasonInvalidConfiguration = "InvalidConfiguration" + ReasonPending = "Pending" +) + +// Programmed condition reasons. +const ( + ReasonProgrammed = "Programmed" + ReasonProgrammedPending = "Pending" + ReasonInvalid = "Invalid" + ReasonGatewayNotReady = "GatewayNotReady" + ReasonDeploymentFailed = "DeploymentFailed" + ReasonRetrying = "Retrying" +) diff --git a/kubernetes/gateway-operator/api/v1/conversion.go b/kubernetes/gateway-operator/api/v1/conversion.go new file mode 100644 index 0000000000..c86800ebf7 --- /dev/null +++ b/kubernetes/gateway-operator/api/v1/conversion.go @@ -0,0 +1,36 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +// The v1 types are the conversion hub (the CRD storage version). Each root +// kind implements the marker Hub() method from +// sigs.k8s.io/controller-runtime/pkg/conversion so that the served v1alpha1 +// spoke types can be converted to and from these canonical types by the +// conversion webhook. + +func (*RestApi) Hub() {} +func (*APIGateway) Hub() {} +func (*ApiKey) Hub() {} +func (*APIPolicy) Hub() {} +func (*Certificate) Hub() {} +func (*LlmProvider) Hub() {} +func (*LlmProviderTemplate) Hub() {} +func (*LlmProxy) Hub() {} +func (*ManagedSecret) Hub() {} +func (*Mcp) Hub() {} +func (*Subscription) Hub() {} +func (*SubscriptionPlan) Hub() {} diff --git a/kubernetes/gateway-operator/api/v1/groupversion_info.go b/kubernetes/gateway-operator/api/v1/groupversion_info.go new file mode 100644 index 0000000000..81efbe2ba0 --- /dev/null +++ b/kubernetes/gateway-operator/api/v1/groupversion_info.go @@ -0,0 +1,36 @@ +/* +Copyright 2025. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1 contains API Schema definitions for the v1 API group +// +kubebuilder:object:generate=true +// +groupName=gateway.api-platform.wso2.com +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects + GroupVersion = schema.GroupVersion{Group: "gateway.api-platform.wso2.com", Version: "v1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/kubernetes/gateway-operator/api/v1/llmprovider_types.go b/kubernetes/gateway-operator/api/v1/llmprovider_types.go new file mode 100644 index 0000000000..c0beab7936 --- /dev/null +++ b/kubernetes/gateway-operator/api/v1/llmprovider_types.go @@ -0,0 +1,202 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// HTTPMethod names an allowed HTTP verb for LLM access-control and policy paths. +// +kubebuilder:validation:Enum=GET;POST;PUT;PATCH;DELETE;HEAD;OPTIONS;* +type HTTPMethod string + +// RouteException defines a path/method exception used by LLM access control. +type RouteException struct { + // Path is the exception path pattern. + // +kubebuilder:validation:Required + Path string `json:"path"` + + // Methods is the list of HTTP methods covered by this exception. + // +kubebuilder:validation:Required + Methods []HTTPMethod `json:"methods"` +} + +// LLMAccessControl configures path-level access control for an LLM provider. +type LLMAccessControl struct { + // Mode selects the default access policy. + // +kubebuilder:validation:Required + // +kubebuilder:validation:Enum=allow_all;deny_all + Mode string `json:"mode"` + + // Exceptions are paths that override the default mode. + // +optional + Exceptions []RouteException `json:"exceptions,omitempty"` +} + +// LLMUpstreamAuth carries upstream credential information for an LLM +// provider. The plaintext credential may either be inlined via Value or +// loaded from a Kubernetes Secret via ValueFrom. +type LLMUpstreamAuth struct { + // Type identifies the auth scheme. Only api-key is currently supported. + // +kubebuilder:validation:Required + // +kubebuilder:validation:Enum=api-key + Type string `json:"type"` + + // Header is the HTTP header to set on outbound requests when the auth + // type uses headers (e.g. api-key). + // +optional + Header *string `json:"header,omitempty"` + + // Value sources the credential. Exactly one of value or valueFrom must + // be set. + // +kubebuilder:validation:Required + Value SecretValueSource `json:"value"` +} + +// LLMProviderUpstream describes the upstream backend for an LLM provider. +type LLMProviderUpstream struct { + // Url is the direct backend URL. + // +optional + Url *string `json:"url,omitempty"` + + // Ref selects a predefined upstream definition by name. + // +optional + Ref *string `json:"ref,omitempty"` + + // HostRewrite controls how the Host header is handled when routing. + // +optional + // +kubebuilder:validation:Enum=auto;manual + HostRewrite *string `json:"hostRewrite,omitempty"` + + // Auth configures upstream credentials. + // +optional + Auth *LLMUpstreamAuth `json:"auth,omitempty"` +} + +// LLMProviderConfigData mirrors the management-API LLMProviderConfigData. +type LLMProviderConfigData struct { + // DisplayName is a human-readable LLM provider name. + // +kubebuilder:validation:Required + DisplayName string `json:"displayName"` + + // Version is the semantic version of the LLM provider. + // +kubebuilder:validation:Required + // +kubebuilder:validation:Pattern=`^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$` + Version string `json:"version"` + + // Template is the LlmProviderTemplate name to apply. + // +kubebuilder:validation:Required + Template string `json:"template"` + + // AccessControl configures path-level access control. + // +kubebuilder:validation:Required + AccessControl LLMAccessControl `json:"accessControl"` + + // UpstreamDefinitions is the list of reusable upstream definitions (with optional + // connect timeout) that upstream.ref can reference. + // +optional + UpstreamDefinitions []UpstreamDefinition `json:"upstreamDefinitions,omitempty"` + + // Upstream configures the LLM upstream. + // +kubebuilder:validation:Required + Upstream LLMProviderUpstream `json:"upstream"` + + // Context is the base path for all routes (must start with /). + // +optional + // +kubebuilder:validation:Pattern=`^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$` + Context *string `json:"context,omitempty"` + + // Vhost is the virtual host for routing. + // +optional + Vhost *string `json:"vhost,omitempty"` + + // DeploymentState toggles whether the provider is router-attached. + // +optional + // +kubebuilder:validation:Enum=deployed;undeployed + DeploymentState *string `json:"deploymentState,omitempty"` + + // Policies is the list of policies applied to this LLM provider. + // +optional + Policies []LLMPolicy `json:"policies,omitempty"` + + // Resilience configures API-level backend/route timeouts applied to all routes + // generated for this LLM provider. Supported at the API level only. + // +optional + Resilience *Resilience `json:"resilience,omitempty"` +} + +// LLMPolicyPath defines a path/methods combination together with policy +// parameters; mirrors the management-API LLMPolicyPath. +type LLMPolicyPath struct { + // Path is the route path pattern. + // +kubebuilder:validation:Required + Path string `json:"path"` + + // Methods is the list of HTTP methods. + // +kubebuilder:validation:Required + Methods []HTTPMethod `json:"methods"` + + // Params is a free-form parameter object specific to the policy. + // +optional + // +kubebuilder:pruning:PreserveUnknownFields + // +kubebuilder:validation:Schemaless + Params *runtime.RawExtension `json:"params,omitempty"` +} + +// LLMPolicy describes a single LLM-level policy attachment. +type LLMPolicy struct { + // Name is the name of the policy. + // +kubebuilder:validation:Required + Name string `json:"name"` + + // Version is the policy version (e.g. v1). + // +kubebuilder:validation:Required + // +kubebuilder:validation:Pattern=`^v\d+$` + Version string `json:"version"` + + // Paths lists path/method/params triples for this policy. + // +kubebuilder:validation:Required + Paths []LLMPolicyPath `json:"paths"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:storageversion +//+kubebuilder:subresource:status +//+kubebuilder:resource:path=llmproviders,singular=llmprovider,shortName=llmp + +// LlmProvider is the Schema for the llmproviders API. +type LlmProvider struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec LLMProviderConfigData `json:"spec,omitempty"` + Status ResourceStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// LlmProviderList contains a list of LlmProvider. +type LlmProviderList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []LlmProvider `json:"items"` +} + +func init() { + SchemeBuilder.Register(&LlmProvider{}, &LlmProviderList{}) +} diff --git a/kubernetes/gateway-operator/api/v1/llmprovidertemplate_types.go b/kubernetes/gateway-operator/api/v1/llmprovidertemplate_types.go new file mode 100644 index 0000000000..e819233ce0 --- /dev/null +++ b/kubernetes/gateway-operator/api/v1/llmprovidertemplate_types.go @@ -0,0 +1,112 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// ExtractionIdentifier locates a value within an HTTP request or response. +// Mirrors the gateway-controller management API ExtractionIdentifier model. +type ExtractionIdentifier struct { + // Identifier is a JSONPath expression or header name. + // +kubebuilder:validation:Required + Identifier string `json:"identifier"` + + // Location is where to look for the value. + // +kubebuilder:validation:Required + // +kubebuilder:validation:Enum=header;pathParam;payload;queryParam + Location string `json:"location"` +} + +// LLMProviderTemplateResourceMapping maps a resource path pattern to per-field +// extraction identifiers for a given LLM API resource. +type LLMProviderTemplateResourceMapping struct { + // Resource is the resource path pattern this mapping applies to. + // +kubebuilder:validation:Required + Resource string `json:"resource"` + + // +optional + CompletionTokens *ExtractionIdentifier `json:"completionTokens,omitempty"` + // +optional + PromptTokens *ExtractionIdentifier `json:"promptTokens,omitempty"` + // +optional + RemainingTokens *ExtractionIdentifier `json:"remainingTokens,omitempty"` + // +optional + RequestModel *ExtractionIdentifier `json:"requestModel,omitempty"` + // +optional + ResponseModel *ExtractionIdentifier `json:"responseModel,omitempty"` + // +optional + TotalTokens *ExtractionIdentifier `json:"totalTokens,omitempty"` +} + +// LLMProviderTemplateResourceMappings lists per-resource extraction mappings. +type LLMProviderTemplateResourceMappings struct { + // +optional + Resources []LLMProviderTemplateResourceMapping `json:"resources,omitempty"` +} + +// LLMProviderTemplateData mirrors the management-API LLMProviderTemplateData +// payload. The non-resource extractor fields apply when no resourceMappings +// entry matches the request path. +type LLMProviderTemplateData struct { + // DisplayName is a human-readable LLM template name. + // +kubebuilder:validation:Required + DisplayName string `json:"displayName"` + + // +optional + CompletionTokens *ExtractionIdentifier `json:"completionTokens,omitempty"` + // +optional + PromptTokens *ExtractionIdentifier `json:"promptTokens,omitempty"` + // +optional + RemainingTokens *ExtractionIdentifier `json:"remainingTokens,omitempty"` + // +optional + RequestModel *ExtractionIdentifier `json:"requestModel,omitempty"` + // +optional + ResourceMappings *LLMProviderTemplateResourceMappings `json:"resourceMappings,omitempty"` + // +optional + ResponseModel *ExtractionIdentifier `json:"responseModel,omitempty"` + // +optional + TotalTokens *ExtractionIdentifier `json:"totalTokens,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:storageversion +//+kubebuilder:subresource:status +//+kubebuilder:resource:path=llmprovidertemplates,singular=llmprovidertemplate,shortName=llmpt + +// LlmProviderTemplate is the Schema for the llmprovidertemplates API. +type LlmProviderTemplate struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec LLMProviderTemplateData `json:"spec,omitempty"` + Status ResourceStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// LlmProviderTemplateList contains a list of LlmProviderTemplate. +type LlmProviderTemplateList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []LlmProviderTemplate `json:"items"` +} + +func init() { + SchemeBuilder.Register(&LlmProviderTemplate{}, &LlmProviderTemplateList{}) +} diff --git a/kubernetes/gateway-operator/api/v1/llmproxy_types.go b/kubernetes/gateway-operator/api/v1/llmproxy_types.go new file mode 100644 index 0000000000..5141f728f7 --- /dev/null +++ b/kubernetes/gateway-operator/api/v1/llmproxy_types.go @@ -0,0 +1,152 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// LLMProxyProvider references a deployed LlmProvider that this proxy fronts. +type LLMProxyProvider struct { + // Id is the LlmProvider handle (metadata.name). + // +kubebuilder:validation:Required + Id string `json:"id"` + + // Auth optionally overrides upstream credentials when calling the + // referenced LLM provider. + // +optional + Auth *LLMUpstreamAuth `json:"auth,omitempty"` +} + +// LLMProxyAdditionalProvider references an additional LlmProvider that this +// proxy can route to by policy-selected upstream name. +type LLMProxyAdditionalProvider struct { + // Id is the LlmProvider handle (metadata.name). + // +kubebuilder:validation:Required + Id string `json:"id"` + + // As is the logical upstream name used by policies. Defaults to Id. + // +optional + As *string `json:"as,omitempty"` + + // Auth optionally configures credentials for proxy-to-provider loopback + // calls when the referenced provider is protected by an auth policy. + // +optional + Auth *LLMUpstreamAuth `json:"auth,omitempty"` + + // Transformer optionally applies a request/response translator when this + // provider is the selected upstream. The proxy injects it as a conditional + // policy that runs only when this provider is selected. + // +optional + Transformer *LLMProxyTransformer `json:"transformer,omitempty"` +} + +// LLMProxyTransformer is a request/response translator applied when its owning +// provider is the selected upstream; mirrors the management-API +// LLMProxyTransformer payload. +type LLMProxyTransformer struct { + // Type is the translator policy name (for example openai-to-anthropic). + // +kubebuilder:validation:Required + Type string `json:"type"` + + // Version is the major-only translator policy version (for example v1). + // The Gateway Controller resolves it to the installed full version. + // +kubebuilder:validation:Required + // +kubebuilder:validation:Pattern=`^v\d+$` + Version string `json:"version"` + + // Params carries translator-specific parameters (for example model, + // apiVersion). + // +optional + // +kubebuilder:pruning:PreserveUnknownFields + // +kubebuilder:validation:Schemaless + Params *runtime.RawExtension `json:"params,omitempty"` +} + +// LLMProxyConfigData mirrors the management-API LLMProxyConfigData payload. +type LLMProxyConfigData struct { + // DisplayName is a human-readable LLM proxy name. + // +kubebuilder:validation:Required + DisplayName string `json:"displayName"` + + // Version is the semantic version of the LLM proxy. + // +kubebuilder:validation:Required + // +kubebuilder:validation:Pattern=`^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$` + Version string `json:"version"` + + // Provider references the deployed LLM provider this proxy fronts. + // +kubebuilder:validation:Required + Provider LLMProxyProvider `json:"provider"` + + // AdditionalProviders are extra LLM providers attached as selectable + // upstreams for multi-provider routing. + // +optional + AdditionalProviders []LLMProxyAdditionalProvider `json:"additionalProviders,omitempty"` + + // Context is the base path for routes (must start with /). + // +optional + // +kubebuilder:validation:Pattern=`^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$` + Context *string `json:"context,omitempty"` + + // Vhost is the virtual host for routing. + // +optional + Vhost *string `json:"vhost,omitempty"` + + // DeploymentState toggles whether the proxy is router-attached. + // +optional + // +kubebuilder:validation:Enum=deployed;undeployed + DeploymentState *string `json:"deploymentState,omitempty"` + + // Policies is the list of policies applied to this LLM proxy. + // +optional + Policies []LLMPolicy `json:"policies,omitempty"` + + // Resilience configures API-level backend/route timeouts applied to all routes + // generated for this LLM proxy. Supported at the API level only. + // +optional + Resilience *Resilience `json:"resilience,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:storageversion +//+kubebuilder:subresource:status +//+kubebuilder:resource:path=llmproxies,singular=llmproxy,shortName=llmpx + +// LlmProxy is the Schema for the llmproxies API. +type LlmProxy struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec is the LLM proxy configuration payload. + // +kubebuilder:validation:Required + Spec LLMProxyConfigData `json:"spec"` + Status ResourceStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// LlmProxyList contains a list of LlmProxy. +type LlmProxyList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []LlmProxy `json:"items"` +} + +func init() { + SchemeBuilder.Register(&LlmProxy{}, &LlmProxyList{}) +} diff --git a/kubernetes/gateway-operator/api/v1/mcp_types.go b/kubernetes/gateway-operator/api/v1/mcp_types.go new file mode 100644 index 0000000000..514afff924 --- /dev/null +++ b/kubernetes/gateway-operator/api/v1/mcp_types.go @@ -0,0 +1,236 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// MCPUpstreamAuth carries upstream credential configuration for an MCP +// proxy (mirrors the management-API MCPProxyConfigData.upstream.auth shape). +type MCPUpstreamAuth struct { + // Type identifies the auth scheme. Only api-key is currently supported. + // +kubebuilder:validation:Required + // +kubebuilder:validation:Enum=api-key + Type string `json:"type"` + + // Header is the HTTP header to set on outbound requests. + // +optional + Header *string `json:"header,omitempty"` + + // Value sources the credential plaintext. + // +kubebuilder:validation:Required + Value SecretValueSource `json:"value"` +} + +// MCPUpstream describes an MCP proxy upstream backend. +type MCPUpstream struct { + // Url is the direct backend URL. + // +optional + Url *string `json:"url,omitempty"` + + // Ref is the name of a predefined upstream definition. + // +optional + Ref *string `json:"ref,omitempty"` + + // HostRewrite controls how the Host header is handled. + // +optional + // +kubebuilder:validation:Enum=auto;manual + HostRewrite *string `json:"hostRewrite,omitempty"` + + // Auth configures upstream credentials. + // +optional + Auth *MCPUpstreamAuth `json:"auth,omitempty"` +} + +// MCPPromptArgument describes one input argument for an MCP prompt. +type MCPPromptArgument struct { + // Name is the argument name. + // +kubebuilder:validation:Required + Name string `json:"name"` + + // Title is an optional human-readable label. + // +optional + Title *string `json:"title,omitempty"` + + // Description is an optional argument description. + // +optional + Description *string `json:"description,omitempty"` + + // Required marks the argument as mandatory. + // +optional + Required *bool `json:"required,omitempty"` +} + +// MCPPrompt mirrors the management-API MCPPrompt schema. +type MCPPrompt struct { + // Name is the unique prompt identifier. + // +kubebuilder:validation:Required + Name string `json:"name"` + + // Title is an optional human-readable name. + // +optional + Title *string `json:"title,omitempty"` + + // Description is an optional description. + // +optional + Description *string `json:"description,omitempty"` + + // Arguments is the optional argument list. + // +optional + Arguments []MCPPromptArgument `json:"arguments,omitempty"` +} + +// MCPResource mirrors the management-API MCPResource schema. +type MCPResource struct { + // Uri is a unique identifier for the resource. + // +kubebuilder:validation:Required + Uri string `json:"uri"` + + // Name is a human-readable resource name. + // +kubebuilder:validation:Required + Name string `json:"name"` + + // Title is an optional human-readable label. + // +optional + Title *string `json:"title,omitempty"` + + // Description is an optional description. + // +optional + Description *string `json:"description,omitempty"` + + // MimeType is an optional MIME type. + // +optional + MimeType *string `json:"mimeType,omitempty"` + + // Size is the optional size in bytes. + // +optional + Size *int64 `json:"size,omitempty"` +} + +// MCPTool mirrors the management-API MCPTool schema. +type MCPTool struct { + // Name is the unique tool identifier. + // +kubebuilder:validation:Required + Name string `json:"name"` + + // Description is the human-readable functional description. + // +kubebuilder:validation:Required + Description string `json:"description"` + + // InputSchema is the JSON Schema for input parameters. + // +kubebuilder:validation:Required + InputSchema string `json:"inputSchema"` + + // Title is an optional human-readable label. + // +optional + Title *string `json:"title,omitempty"` + + // OutputSchema is the optional JSON Schema for the output. + // +optional + OutputSchema *string `json:"outputSchema,omitempty"` +} + +// MCPProxyConfigData mirrors the management-API MCPProxyConfigData payload. +type MCPProxyConfigData struct { + // DisplayName is a human-readable MCP proxy name. + // +kubebuilder:validation:Required + DisplayName string `json:"displayName"` + + // Version is the MCP proxy semantic version. + // +kubebuilder:validation:Required + // +kubebuilder:validation:Pattern=`^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$` + Version string `json:"version"` + + // UpstreamDefinitions is the list of reusable upstream definitions (with optional + // connect timeout) that upstream.ref can reference. + // +optional + UpstreamDefinitions []UpstreamDefinition `json:"upstreamDefinitions,omitempty"` + + // Upstream is the MCP backend. + // +kubebuilder:validation:Required + Upstream MCPUpstream `json:"upstream"` + + // Context is the base path for routes (must start with /). + // +optional + // +kubebuilder:validation:Pattern=`^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$` + Context *string `json:"context,omitempty"` + + // Vhost is the virtual host for routing. + // +optional + Vhost *string `json:"vhost,omitempty"` + + // SpecVersion is the MCP specification version. + // +optional + SpecVersion *string `json:"specVersion,omitempty"` + + // DeploymentState toggles whether the proxy is router-attached. + // +optional + // +kubebuilder:validation:Enum=deployed;undeployed + DeploymentState *string `json:"deploymentState,omitempty"` + + // Prompts lists optional prompts exposed by this MCP proxy. + // +optional + Prompts []MCPPrompt `json:"prompts,omitempty"` + + // Resources lists optional MCP resources exposed by this proxy. + // +optional + Resources []MCPResource `json:"resources,omitempty"` + + // Tools lists optional tools exposed by this MCP proxy. + // +optional + Tools []MCPTool `json:"tools,omitempty"` + + // Policies are MCP proxy-level policies. + // +optional + Policies []Policy `json:"policies,omitempty"` + + // Resilience configures API-level backend/route timeouts applied to the traffic-forwarding + // routes generated for this MCP proxy. Supported at the API level only. Because MCP transports + // are long-lived streams, the route timeout defaults to disabled ("0s") for MCP when unset. + // +optional + Resilience *Resilience `json:"resilience,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:storageversion +//+kubebuilder:subresource:status +//+kubebuilder:resource:path=mcps,singular=mcp,shortName=mcp + +// Mcp is the Schema for the mcps API. +type Mcp struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // Spec is the MCP proxy configuration. + // +kubebuilder:validation:Required + Spec MCPProxyConfigData `json:"spec"` + Status ResourceStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// McpList contains a list of Mcp. +type McpList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Mcp `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Mcp{}, &McpList{}) +} diff --git a/kubernetes/gateway-operator/api/v1/operation_match.go b/kubernetes/gateway-operator/api/v1/operation_match.go new file mode 100644 index 0000000000..a93abc8971 --- /dev/null +++ b/kubernetes/gateway-operator/api/v1/operation_match.go @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2026, WSO2 LLC. (http://www.wso2.org) All Rights Reserved. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package v1 + +// An operation can be expressed either with the simple top-level Method+Path fields or with the +// richer Match block (method + path{value,type} + headers). These helpers resolve the effective +// matching criteria: when Match is set it is authoritative and the top-level Method/Path are +// ignored; otherwise the top-level fields (the simple form) are used. + +// EffectiveMethod returns the operation's effective HTTP method. +func (o Operation) EffectiveMethod() OperationMethod { + if o.Match != nil { + return o.Match.Method + } + return o.Method +} + +// EffectivePath returns the operation's effective route path. +func (o Operation) EffectivePath() string { + if o.Match != nil { + return o.Match.Path.Value + } + return o.Path +} + +// EffectivePathMatchType returns the effective path match type. For the match form it is the +// explicit type or "Exact" (the default) when omitted. For the simple form it is empty, +// preserving the legacy path-matching behavior for operations that never carried a type. +func (o Operation) EffectivePathMatchType() OperationPathMatchType { + if o.Match != nil { + if o.Match.Path.Type != "" { + return o.Match.Path.Type + } + return OperationPathMatchExact + } + return "" +} + +// EffectiveHeaders returns the operation's header matchers. Header matching is expressible only +// via the match form; the simple form has none. +func (o Operation) EffectiveHeaders() []OperationHeaderMatch { + if o.Match != nil { + return o.Match.Headers + } + return nil +} diff --git a/kubernetes/gateway-operator/api/v1/policy_types.go b/kubernetes/gateway-operator/api/v1/policy_types.go new file mode 100644 index 0000000000..135cb462e4 --- /dev/null +++ b/kubernetes/gateway-operator/api/v1/policy_types.go @@ -0,0 +1,96 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// APIPolicyTargetRef identifies the HTTPRoute for API-level policies (optional). +// When omitted on APIPolicy, policies apply only when the CR is referenced from HTTPRoute rule filters (ExtensionRef). +type APIPolicyTargetRef struct { + // Group of the referent (e.g. gateway.networking.k8s.io). + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:Enum=gateway.networking.k8s.io + Group string `json:"group"` + // Kind of the referent. Use HTTPRoute for Gateway API integration. + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:Enum=HTTPRoute + Kind string `json:"kind"` + // Name of the referent HTTPRoute. + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength=1 + Name string `json:"name"` + // Namespace of the referent; defaults to the APIPolicy's namespace if unset. + // +optional + Namespace *string `json:"namespace,omitempty"` +} + +// APIPolicySpec holds an optional targetRef for API-level attachment and a list of policy instances (same shape as RestApi embedded policies). +type APIPolicySpec struct { + // TargetRef selects the HTTPRoute for API-level policies: when set, all spec.policies entries are merged into APIConfigData.policies for that route. + // When omitted, this APIPolicy applies only when referenced from HTTPRoute rule filters (ExtensionRef). + // +optional + TargetRef *APIPolicyTargetRef `json:"targetRef,omitempty"` + // Policies is the list of policy instances (name, version, optional params, executionCondition). + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinItems=1 + Policies []Policy `json:"policies"` +} + +// APIPolicyStatus defines observed state. +type APIPolicyStatus struct { + // Conditions represent the latest observations. + // +optional + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:storageversion +//+kubebuilder:subresource:status +//+kubebuilder:resource:path=apipolicies,singular=apipolicy,shortName=apol +//+kubebuilder:printcolumn:name="Target",type=string,JSONPath=`.spec.targetRef.name` +//+kubebuilder:printcolumn:name="First",type=string,JSONPath=`.spec.policies[0].name` +//+kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` + +// APIPolicy is a namespaced policy definition for the Gateway API HTTPRoute integration only. +// Set spec.targetRef to apply policies at API level for that HTTPRoute, or omit targetRef and reference +// this object from HTTPRoute rule filters (ExtensionRef) for rule/match scope. It does not apply to RestApi / APIGateway reconciliation. +// (Distinct from the embedded Policy type on RestApi.) +type APIPolicy struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + // +kubebuilder:validation:Required + Spec APIPolicySpec `json:"spec"` + Status APIPolicyStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// APIPolicyList contains a list of APIPolicy. +type APIPolicyList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []APIPolicy `json:"items"` +} + +func init() { + SchemeBuilder.Register(&APIPolicy{}, &APIPolicyList{}) +} diff --git a/kubernetes/gateway-operator/api/v1/restapi_types.go b/kubernetes/gateway-operator/api/v1/restapi_types.go new file mode 100644 index 0000000000..725751ec31 --- /dev/null +++ b/kubernetes/gateway-operator/api/v1/restapi_types.go @@ -0,0 +1,402 @@ +/* +Copyright 2025. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// RestApiStatus defines the observed state of RestApi +type RestApiStatus struct { + // Conditions represent the latest available observations of the API's state + // +optional + Conditions []metav1.Condition `json:"conditions,omitempty"` + + // LastUpdateTime is the last time the status was updated + // +optional + LastUpdateTime *metav1.Time `json:"lastUpdateTime,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:storageversion +//+kubebuilder:subresource:status + +// RestApi is the Schema for the restapis API +type RestApi struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec APIConfigData `json:"spec,omitempty"` + Status RestApiStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// RestApiList contains a list of RestApi +type RestApiList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []RestApi `json:"items"` +} + +// APIConfigData defines model for APIConfigData. +type APIConfigData struct { + // Context Base path for all API routes (must start with /, no trailing slash; "/" denotes the root context) + // +kubebuilder:validation:Required + // +kubebuilder:validation:Pattern=`^/([a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/])?$` + Context string `json:"context"` + + // DisplayName Human-readable API name (must be URL-friendly - only letters, numbers, spaces, hyphens, underscores, and dots allowed) + // +kubebuilder:validation:Required + // +kubebuilder:validation:Pattern=`^[a-zA-Z0-9\s\-_.]+$` + DisplayName string `json:"displayName" yaml:"displayName"` + + // Operations List of HTTP operations/routes + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinItems=1 + Operations []Operation `json:"operations"` + + // Policies List of API-level policies applied to all operations unless overridden + // +optional + Policies []Policy `json:"policies,omitempty"` + + // Resilience API-level backend/route timeout configuration applied to all operations + // unless overridden at the operation level + // +optional + Resilience *Resilience `json:"resilience,omitempty"` + + // UpstreamDefinitions is the list of reusable upstream definitions (with optional connect + // timeout and weighted load-balancing targets) that upstream.ref and the dynamic-endpoint + // policy can reference. + // +optional + UpstreamDefinitions []UpstreamDefinition `json:"upstreamDefinitions,omitempty"` + + // Upstream API-level upstream configuration + // +kubebuilder:validation:Required + Upstream UpstreamConfig `json:"upstream"` + + // Version Semantic version of the API + // +kubebuilder:validation:Required + // +kubebuilder:validation:Pattern=`^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$` + Version string `json:"version"` + + // Vhosts Custom virtual hosts/domains for the API + // +optional + Vhosts *VhostConfig `json:"vhosts,omitempty"` +} + +// UpstreamConfig defines the upstream backend configuration for the API +type UpstreamConfig struct { + // Main Upstream backend configuration for production traffic + // +kubebuilder:validation:Required + Main Upstream `json:"main"` + + // Sandbox Upstream backend configuration for sandbox/testing traffic + // +optional + Sandbox *Upstream `json:"sandbox,omitempty"` +} + +// VhostConfig defines custom virtual hosts/domains for the API +type VhostConfig struct { + // Main Custom virtual host(s)/domain(s) for production traffic. One or more hostnames separated + // by ";" — each serves the main upstream (e.g. when an HTTPRoute attaches to multiple listeners + // with distinct hostnames). The first entry is the primary vhost. + // +kubebuilder:validation:Required + Main string `json:"main"` + + // Sandbox Custom virtual host/domain for sandbox traffic + // +optional + Sandbox *string `json:"sandbox,omitempty"` +} + +// Operation defines model for Operation. +// An operation is matched either by the simple top-level method+path fields or by the richer +// Match block (method + path + headers). When Match is set it is authoritative and the +// top-level Method/Path are ignored. Exactly one form must be provided. +// +kubebuilder:validation:XValidation:rule="(has(self.method) && has(self.path)) || has(self.match)",message="operation must set both method and path, or set match" +type Operation struct { + // Method HTTP method (simple form; ignored when Match is set). + // +optional + // +kubebuilder:validation:Enum=GET;POST;PUT;PATCH;DELETE;HEAD;OPTIONS + Method OperationMethod `json:"method,omitempty"` + + // Path Route path with optional {param} placeholders (simple form; ignored when Match is set). + // +optional + // +kubebuilder:validation:Pattern=`^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/{}\[\]]*$` + Path string `json:"path,omitempty"` + + // Match Request matching criteria for the operation. Extensible with query params, cookies, etc. + // +optional + Match *OperationMatch `json:"match,omitempty"` + + // Policies List of policies applied only to this operation (overrides or adds to API-level policies) + // +optional + Policies []Policy `json:"policies,omitempty"` + + // Resilience Operation-level backend/route timeout configuration (overrides API-level) + // +optional + Resilience *Resilience `json:"resilience,omitempty"` +} + +// OperationMatch is the request matching criteria for an operation. +type OperationMatch struct { + // Method HTTP method + // +kubebuilder:validation:Required + // +kubebuilder:validation:Enum=GET;POST;PUT;PATCH;DELETE;HEAD;OPTIONS + Method OperationMethod `json:"method"` + + // Path Path match criteria + // +kubebuilder:validation:Required + Path OperationPathMatch `json:"path"` + + // Headers ANDed header matchers applied before routing to this operation. + // +optional + Headers []OperationHeaderMatch `json:"headers,omitempty"` +} + +// OperationPathMatch controls path matching for an operation. +type OperationPathMatch struct { + // Value Route path with optional {param} placeholders + // +kubebuilder:validation:Required + // +kubebuilder:validation:Pattern=`^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/{}\[\]]*$` + Value string `json:"value"` + + // Type How the path is matched (Exact or PathPrefix). Defaults to Exact when omitted. + // +optional + // +kubebuilder:validation:Enum=Exact;PathPrefix + Type OperationPathMatchType `json:"type,omitempty"` +} + +// OperationPathMatchType controls path matching semantics. +type OperationPathMatchType string + +const ( + OperationPathMatchExact OperationPathMatchType = "Exact" + OperationPathMatchPathPrefix OperationPathMatchType = "PathPrefix" +) + +// OperationHeaderMatch mirrors Gateway API HTTPHeaderMatch for Envoy route selection. +type OperationHeaderMatch struct { + // Name Header name (case-insensitive) + // +kubebuilder:validation:Required + Name string `json:"name"` + + // Value Header value to match + // +kubebuilder:validation:Required + Value string `json:"value"` + + // Type Match type (Exact or RegularExpression) + // +optional + // +kubebuilder:validation:Enum=Exact;RegularExpression + Type string `json:"type,omitempty"` +} + +// Resilience defines backend/route timeout configuration (maps to Envoy RouteAction +// timeouts). Settable at the API level (applies to all routes) and/or the operation level +// (overrides the API level). "0s" disables a timeout; unset falls back to the gateway's +// global route timeout defaults. +type Resilience struct { + // Timeout Maximum time for the entire route (request to upstream response). "0s" disables. + // +optional + // +kubebuilder:validation:Pattern=`^\d+(\.\d+)?(ms|s|m|h)$` + Timeout *string `json:"timeout,omitempty"` + + // IdleTimeout Per-route stream idle timeout. "0s" disables. + // +optional + // +kubebuilder:validation:Pattern=`^\d+(\.\d+)?(ms|s|m|h)$` + IdleTimeout *string `json:"idleTimeout,omitempty"` +} + +// OperationMethod HTTP method +type OperationMethod string + +const ( + // OperationMethodGET represents HTTP GET method + OperationMethodGET OperationMethod = "GET" + // OperationMethodPOST represents HTTP POST method + OperationMethodPOST OperationMethod = "POST" + // OperationMethodPUT represents HTTP PUT method + OperationMethodPUT OperationMethod = "PUT" + // OperationMethodPATCH represents HTTP PATCH method + OperationMethodPATCH OperationMethod = "PATCH" + // OperationMethodDELETE represents HTTP DELETE method + OperationMethodDELETE OperationMethod = "DELETE" + // OperationMethodHEAD represents HTTP HEAD method + OperationMethodHEAD OperationMethod = "HEAD" + // OperationMethodOPTIONS represents HTTP OPTIONS method + OperationMethodOPTIONS OperationMethod = "OPTIONS" +) + +// Policy defines a policy attachment as embedded in RestApi or APIConfigData. +type Policy struct { + // ExecutionCondition Expression controlling conditional execution of the policy + // +optional + ExecutionCondition *string `json:"executionCondition,omitempty"` + + // Name Name of the policy + // +kubebuilder:validation:Required + Name string `json:"name"` + + // Params Arbitrary parameters for the policy (free-form key/value structure) + // +optional + // +kubebuilder:pruning:PreserveUnknownFields + // +kubebuilder:validation:Schemaless + Params *runtime.RawExtension `json:"params,omitempty"` + + // Version Semantic version of the policy (for example, v1) + // +kubebuilder:validation:Required + // +kubebuilder:validation:Pattern=`^v\d+$` + Version string `json:"version"` +} + +// Upstream defines model for Upstream. Exactly one of url or ref must be set: a direct backend URL, +// or a reference to a predefined upstreamDefinition (which can carry a per-upstream connect timeout). +// +kubebuilder:validation:XValidation:rule="has(self.url) != has(self.ref)",message="exactly one of url or ref must be set" +type Upstream struct { + // Url Direct backend service URL (may include path prefix like /api/v2) + // +optional + // +kubebuilder:validation:Pattern=`^https?://[a-zA-Z0-9\-._~:/?#\[\]@!$&'()*+,;=%]+$` + Url *string `json:"url,omitempty"` + + // Ref Name of a predefined upstreamDefinition to route through. + // +optional + Ref *string `json:"ref,omitempty"` + + // HostRewrite controls how the Host header is handled when routing to the upstream. + // "auto" lets Envoy rewrite the Host header to the upstream cluster host; "manual" + // disables automatic rewriting so the incoming Host header is preserved. When unset, + // the gateway-controller defaults to "auto". + // +optional + // +kubebuilder:validation:Enum=auto;manual + HostRewrite *UpstreamHostRewrite `json:"hostRewrite,omitempty"` +} + +// UpstreamHostRewrite controls Host header handling toward the upstream. +type UpstreamHostRewrite string + +const ( + // UpstreamHostRewriteAuto lets Envoy rewrite the Host header to the upstream cluster host. + UpstreamHostRewriteAuto UpstreamHostRewrite = "auto" + // UpstreamHostRewriteManual disables automatic rewriting; the incoming Host header is preserved. + UpstreamHostRewriteManual UpstreamHostRewrite = "manual" +) + +// UpstreamDefinition is a reusable upstream configuration with an optional connect timeout and +// one or more weighted load-balancing targets. Referenced from an upstream via its `ref` field +// and by the dynamic-endpoint policy. Shared by RestApi, LLM Provider, and MCP; mirrors the +// management-API UpstreamDefinition schema. +type UpstreamDefinition struct { + // Name Unique identifier for this upstream definition (referenced by upstream.ref or the + // dynamic-endpoint policy). + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=100 + // +kubebuilder:validation:Pattern=`^[a-zA-Z0-9\-_]+$` + Name string `json:"name"` + + // BasePath Base path prefix prepended to all requests routed through this upstream (e.g. /api/v2). + // Must start with "/" and must not end with "/". Omit for root ("/"). + // +optional + // +kubebuilder:validation:Pattern=`^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$` + BasePath *string `json:"basePath,omitempty"` + + // Timeout Optional timeout configuration for this upstream (connect timeout). + // +optional + Timeout *UpstreamTimeout `json:"timeout,omitempty"` + + // Upstreams List of backend targets with optional weights for load balancing. + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinItems=1 + Upstreams []WeightedUpstream `json:"upstreams"` +} + +// UpstreamTimeout carries the per-upstream timeout configuration. Only the connect timeout is +// supported at the upstream-definition level. +type UpstreamTimeout struct { + // Connect Connection-establishment timeout duration (e.g. "5s", "500ms"). "0s" disables. + // +optional + // +kubebuilder:validation:Pattern=`^\d+(\.\d+)?(ms|s|m|h)$` + Connect *string `json:"connect,omitempty"` +} + +// WeightedUpstream is a single backend target within an UpstreamDefinition. +type WeightedUpstream struct { + // Url Backend URL (host and port; no path) + // +kubebuilder:validation:Required + Url string `json:"url"` + + // Weight Relative weight for load balancing across multiple upstream targets. Reserved for + // future multi-target load balancing; not applied yet (only the first target is currently used). + // +optional + // +kubebuilder:validation:Minimum=0 + // +kubebuilder:validation:Maximum=100 + Weight *int `json:"weight,omitempty"` +} + +// Condition Types for RestApi +const ( + // APIConditionAccepted indicates the CR passed validation and is accepted for processing + APIConditionAccepted = "Accepted" + // APIConditionProgrammed indicates the API is successfully deployed/programmed to the gateway + APIConditionProgrammed = "Programmed" + // APIConditionReady is the canonical Ready condition type for RestApi (retained for compatibility) + APIConditionReady = "Ready" +) + +// Accepted Condition Reasons +const ( + // APIAcceptedReasonAccepted indicates the CR passed validation + APIAcceptedReasonAccepted = "Accepted" + // APIAcceptedReasonInvalidConfiguration indicates the CR failed validation + APIAcceptedReasonInvalidConfiguration = "InvalidConfiguration" + // APIAcceptedReasonPending indicates validation is pending + APIAcceptedReasonPending = "Pending" +) + +// Programmed Condition Reasons +const ( + // APIProgrammedReasonProgrammed indicates successful deployment to gateway + APIProgrammedReasonProgrammed = "Programmed" + // APIProgrammedReasonPending indicates deployment is pending + APIProgrammedReasonPending = "Pending" + // APIProgrammedReasonInvalid indicates configuration is invalid for gateway + APIProgrammedReasonInvalid = "Invalid" + // APIProgrammedReasonGatewayNotReady indicates gateway is unavailable + APIProgrammedReasonGatewayNotReady = "GatewayNotReady" + // APIProgrammedReasonDeploymentFailed indicates deployment failed (non-retryable) + APIProgrammedReasonDeploymentFailed = "DeploymentFailed" + // APIProgrammedReasonRetrying indicates deployment failed and is being retried + APIProgrammedReasonRetrying = "Retrying" +) + +// APIPhase represents the lifecycle phase of an RestApi +// +kubebuilder:validation:Enum=Pending;Deployed;Failed +type APIPhase string + +const ( + // APIPhasePending indicates the controller is waiting to deploy the API + APIPhasePending APIPhase = "Pending" + // APIPhaseDeployed indicates the API has been deployed to all target gateways + APIPhaseDeployed APIPhase = "Deployed" + // APIPhaseFailed indicates the controller failed to deploy the API + APIPhaseFailed APIPhase = "Failed" +) + +func init() { + SchemeBuilder.Register(&RestApi{}, &RestApiList{}) +} diff --git a/kubernetes/gateway-operator/api/v1/secret_types.go b/kubernetes/gateway-operator/api/v1/secret_types.go new file mode 100644 index 0000000000..325deb0456 --- /dev/null +++ b/kubernetes/gateway-operator/api/v1/secret_types.go @@ -0,0 +1,69 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// SecretSpec mirrors the management-API SecretConfigData payload, with the +// sensitive Value field expressed as a SecretValueSource so operators can +// keep plaintext out of the CR by referencing a Kubernetes Secret. +type SecretSpec struct { + // DisplayName is a human-readable secret name. + // +kubebuilder:validation:Required + DisplayName string `json:"displayName"` + + // Description is an optional description of the secret. + // +optional + Description *string `json:"description,omitempty"` + + // Value is the secret plaintext, supplied either inline or via valueFrom. + // +kubebuilder:validation:Required + Value SecretValueSource `json:"value"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:storageversion +//+kubebuilder:subresource:status +//+kubebuilder:resource:path=managedsecrets,singular=managedsecret,shortName=msec + +// ManagedSecret represents a platform secret stored by the gateway-controller. +// +// The CRD is named ManagedSecret (rather than Secret) so it does not collide +// with the built-in core/v1 Secret kind. The plural "managedsecrets" is used +// in URLs and RBAC to remain unambiguous. +type ManagedSecret struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec SecretSpec `json:"spec,omitempty"` + Status ResourceStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// ManagedSecretList contains a list of ManagedSecret. +type ManagedSecretList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ManagedSecret `json:"items"` +} + +func init() { + SchemeBuilder.Register(&ManagedSecret{}, &ManagedSecretList{}) +} diff --git a/kubernetes/gateway-operator/api/v1/subscription_types.go b/kubernetes/gateway-operator/api/v1/subscription_types.go new file mode 100644 index 0000000000..5a92cbb49b --- /dev/null +++ b/kubernetes/gateway-operator/api/v1/subscription_types.go @@ -0,0 +1,88 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// SubscriptionSpec mirrors the management-API SubscriptionCreateRequest +// payload. The gateway-controller issues a UUID id which the controller +// persists to .status.id for subsequent PUT/DELETE. +type SubscriptionSpec struct { + // ApiId is the API identifier (deployment id or handle). + // +kubebuilder:validation:Required + ApiId string `json:"apiId"` + + // SubscriptionToken is the opaque token used to invoke the API. The + // token is sent as plaintext to the gateway which stores only its hash; + // inline in the CR or supplied via valueFrom. + // +kubebuilder:validation:Required + SubscriptionToken SecretValueSource `json:"subscriptionToken"` + + // ApplicationId is an optional application identifier. + // +optional + ApplicationId *string `json:"applicationId,omitempty"` + + // SubscriptionPlanId is an optional plan UUID. When the plan is also + // managed via SubscriptionPlan CR, set this to the SubscriptionPlan's + // .status.id once it has been deployed. + // +optional + SubscriptionPlanId *string `json:"subscriptionPlanId,omitempty"` + + // BillingCustomerId is an optional billing customer identifier. + // +optional + BillingCustomerId *string `json:"billingCustomerId,omitempty"` + + // BillingSubscriptionId is an optional billing subscription identifier. + // +optional + BillingSubscriptionId *string `json:"billingSubscriptionId,omitempty"` + + // Status is the lifecycle state for this subscription. Mirrors the + // management-API SubscriptionCreateRequest.Status enum. + // +optional + Status *string `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:storageversion +//+kubebuilder:subresource:status +//+kubebuilder:resource:path=subscriptions,singular=subscription,shortName=sub +//+kubebuilder:printcolumn:name="Id",type=string,JSONPath=`.status.id` +//+kubebuilder:printcolumn:name="ApiId",type=string,JSONPath=`.spec.apiId` + +// Subscription is the Schema for the subscriptions API. +type Subscription struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec SubscriptionSpec `json:"spec"` + Status ResourceStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// SubscriptionList contains a list of Subscription. +type SubscriptionList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Subscription `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Subscription{}, &SubscriptionList{}) +} diff --git a/kubernetes/gateway-operator/api/v1/subscriptionplan_types.go b/kubernetes/gateway-operator/api/v1/subscriptionplan_types.go new file mode 100644 index 0000000000..e5ac8e462c --- /dev/null +++ b/kubernetes/gateway-operator/api/v1/subscriptionplan_types.go @@ -0,0 +1,89 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// SubscriptionPlanSpec mirrors the management-API SubscriptionPlanCreateRequest +// payload. The gateway-controller assigns a UUID id on first POST; the +// controller persists it to .status.id and uses it for subsequent +// PUT/DELETE. +type SubscriptionPlanSpec struct { + // PlanName is the human-readable plan name. + // +kubebuilder:validation:Required + PlanName string `json:"planName"` + + // BillingPlan is an optional billing plan identifier. + // +optional + BillingPlan *string `json:"billingPlan,omitempty"` + + // ExpiryTime is the optional plan expiry. + // +optional + ExpiryTime *metav1.Time `json:"expiryTime,omitempty"` + + // Status is the lifecycle state for this plan (active/inactive/etc). + // Mirrors the management-API SubscriptionPlanCreateRequest.Status enum. + // +optional + // +kubebuilder:validation:Enum=ACTIVE;INACTIVE + Status *string `json:"status,omitempty"` + + // StopOnQuotaReach controls whether traffic is blocked when the quota + // is exhausted. + // +optional + StopOnQuotaReach *bool `json:"stopOnQuotaReach,omitempty"` + + // ThrottleLimitCount is the request count limit. + // +optional + // +kubebuilder:validation:Minimum=0 + ThrottleLimitCount *int64 `json:"throttleLimitCount,omitempty"` + + // ThrottleLimitUnit is the time unit for the throttle window. + // +optional + // +kubebuilder:validation:Enum=Day;Hour;Min;Month + ThrottleLimitUnit *string `json:"throttleLimitUnit,omitempty"` +} + +//+kubebuilder:object:root=true +//+kubebuilder:storageversion +//+kubebuilder:subresource:status +//+kubebuilder:resource:path=subscriptionplans,singular=subscriptionplan,shortName=splan +//+kubebuilder:printcolumn:name="Id",type=string,JSONPath=`.status.id` +//+kubebuilder:printcolumn:name="Plan",type=string,JSONPath=`.spec.planName` + +// SubscriptionPlan is the Schema for the subscriptionplans API. +type SubscriptionPlan struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec SubscriptionPlanSpec `json:"spec,omitempty"` + Status ResourceStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// SubscriptionPlanList contains a list of SubscriptionPlan. +type SubscriptionPlanList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []SubscriptionPlan `json:"items"` +} + +func init() { + SchemeBuilder.Register(&SubscriptionPlan{}, &SubscriptionPlanList{}) +} diff --git a/kubernetes/gateway-operator/api/v1/zz_generated.deepcopy.go b/kubernetes/gateway-operator/api/v1/zz_generated.deepcopy.go new file mode 100644 index 0000000000..f4ca5f8f1a --- /dev/null +++ b/kubernetes/gateway-operator/api/v1/zz_generated.deepcopy.go @@ -0,0 +1,2332 @@ +//go:build !ignore_autogenerated + +/* +Copyright 2025. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1 + +import ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *APIConfigData) DeepCopyInto(out *APIConfigData) { + *out = *in + if in.Operations != nil { + in, out := &in.Operations, &out.Operations + *out = make([]Operation, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Policies != nil { + in, out := &in.Policies, &out.Policies + *out = make([]Policy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Resilience != nil { + in, out := &in.Resilience, &out.Resilience + *out = new(Resilience) + (*in).DeepCopyInto(*out) + } + if in.UpstreamDefinitions != nil { + in, out := &in.UpstreamDefinitions, &out.UpstreamDefinitions + *out = make([]UpstreamDefinition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.Upstream.DeepCopyInto(&out.Upstream) + if in.Vhosts != nil { + in, out := &in.Vhosts, &out.Vhosts + *out = new(VhostConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIConfigData. +func (in *APIConfigData) DeepCopy() *APIConfigData { + if in == nil { + return nil + } + out := new(APIConfigData) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *APIGateway) DeepCopyInto(out *APIGateway) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIGateway. +func (in *APIGateway) DeepCopy() *APIGateway { + if in == nil { + return nil + } + out := new(APIGateway) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *APIGateway) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *APIGatewayList) DeepCopyInto(out *APIGatewayList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]APIGateway, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIGatewayList. +func (in *APIGatewayList) DeepCopy() *APIGatewayList { + if in == nil { + return nil + } + out := new(APIGatewayList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *APIGatewayList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *APIPolicy) DeepCopyInto(out *APIPolicy) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIPolicy. +func (in *APIPolicy) DeepCopy() *APIPolicy { + if in == nil { + return nil + } + out := new(APIPolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *APIPolicy) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *APIPolicyList) DeepCopyInto(out *APIPolicyList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]APIPolicy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIPolicyList. +func (in *APIPolicyList) DeepCopy() *APIPolicyList { + if in == nil { + return nil + } + out := new(APIPolicyList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *APIPolicyList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *APIPolicySpec) DeepCopyInto(out *APIPolicySpec) { + *out = *in + if in.TargetRef != nil { + in, out := &in.TargetRef, &out.TargetRef + *out = new(APIPolicyTargetRef) + (*in).DeepCopyInto(*out) + } + if in.Policies != nil { + in, out := &in.Policies, &out.Policies + *out = make([]Policy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIPolicySpec. +func (in *APIPolicySpec) DeepCopy() *APIPolicySpec { + if in == nil { + return nil + } + out := new(APIPolicySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *APIPolicyStatus) DeepCopyInto(out *APIPolicyStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIPolicyStatus. +func (in *APIPolicyStatus) DeepCopy() *APIPolicyStatus { + if in == nil { + return nil + } + out := new(APIPolicyStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *APIPolicyTargetRef) DeepCopyInto(out *APIPolicyTargetRef) { + *out = *in + if in.Namespace != nil { + in, out := &in.Namespace, &out.Namespace + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APIPolicyTargetRef. +func (in *APIPolicyTargetRef) DeepCopy() *APIPolicyTargetRef { + if in == nil { + return nil + } + out := new(APIPolicyTargetRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *APISelector) DeepCopyInto(out *APISelector) { + *out = *in + if in.Namespaces != nil { + in, out := &in.Namespaces, &out.Namespaces + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.MatchLabels != nil { + in, out := &in.MatchLabels, &out.MatchLabels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.MatchExpressions != nil { + in, out := &in.MatchExpressions, &out.MatchExpressions + *out = make([]metav1.LabelSelectorRequirement, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new APISelector. +func (in *APISelector) DeepCopy() *APISelector { + if in == nil { + return nil + } + out := new(APISelector) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApiKey) DeepCopyInto(out *ApiKey) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApiKey. +func (in *ApiKey) DeepCopy() *ApiKey { + if in == nil { + return nil + } + out := new(ApiKey) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ApiKey) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApiKeyExpiry) DeepCopyInto(out *ApiKeyExpiry) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApiKeyExpiry. +func (in *ApiKeyExpiry) DeepCopy() *ApiKeyExpiry { + if in == nil { + return nil + } + out := new(ApiKeyExpiry) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApiKeyList) DeepCopyInto(out *ApiKeyList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ApiKey, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApiKeyList. +func (in *ApiKeyList) DeepCopy() *ApiKeyList { + if in == nil { + return nil + } + out := new(ApiKeyList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ApiKeyList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApiKeyParentRef) DeepCopyInto(out *ApiKeyParentRef) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApiKeyParentRef. +func (in *ApiKeyParentRef) DeepCopy() *ApiKeyParentRef { + if in == nil { + return nil + } + out := new(ApiKeyParentRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ApiKeySpec) DeepCopyInto(out *ApiKeySpec) { + *out = *in + out.ParentRef = in.ParentRef + if in.DisplayName != nil { + in, out := &in.DisplayName, &out.DisplayName + *out = new(string) + **out = **in + } + if in.ApiKey != nil { + in, out := &in.ApiKey, &out.ApiKey + *out = new(SecretValueSource) + (*in).DeepCopyInto(*out) + } + if in.MaskedApiKey != nil { + in, out := &in.MaskedApiKey, &out.MaskedApiKey + *out = new(string) + **out = **in + } + if in.ExpiresIn != nil { + in, out := &in.ExpiresIn, &out.ExpiresIn + *out = new(ApiKeyExpiry) + **out = **in + } + if in.ExpiresAt != nil { + in, out := &in.ExpiresAt, &out.ExpiresAt + *out = (*in).DeepCopy() + } + if in.Issuer != nil { + in, out := &in.Issuer, &out.Issuer + *out = new(string) + **out = **in + } + if in.ExternalRefId != nil { + in, out := &in.ExternalRefId, &out.ExternalRefId + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ApiKeySpec. +func (in *ApiKeySpec) DeepCopy() *ApiKeySpec { + if in == nil { + return nil + } + out := new(ApiKeySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Certificate) DeepCopyInto(out *Certificate) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Certificate. +func (in *Certificate) DeepCopy() *Certificate { + if in == nil { + return nil + } + out := new(Certificate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Certificate) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CertificateList) DeepCopyInto(out *CertificateList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Certificate, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertificateList. +func (in *CertificateList) DeepCopy() *CertificateList { + if in == nil { + return nil + } + out := new(CertificateList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *CertificateList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CertificateSpec) DeepCopyInto(out *CertificateSpec) { + *out = *in + in.Certificate.DeepCopyInto(&out.Certificate) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CertificateSpec. +func (in *CertificateSpec) DeepCopy() *CertificateSpec { + if in == nil { + return nil + } + out := new(CertificateSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtractionIdentifier) DeepCopyInto(out *ExtractionIdentifier) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtractionIdentifier. +func (in *ExtractionIdentifier) DeepCopy() *ExtractionIdentifier { + if in == nil { + return nil + } + out := new(ExtractionIdentifier) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayControlPlane) DeepCopyInto(out *GatewayControlPlane) { + *out = *in + if in.TokenSecretRef != nil { + in, out := &in.TokenSecretRef, &out.TokenSecretRef + *out = new(corev1.SecretKeySelector) + (*in).DeepCopyInto(*out) + } + if in.TLS != nil { + in, out := &in.TLS, &out.TLS + *out = new(GatewayTLSConfig) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayControlPlane. +func (in *GatewayControlPlane) DeepCopy() *GatewayControlPlane { + if in == nil { + return nil + } + out := new(GatewayControlPlane) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayInfrastructure) DeepCopyInto(out *GatewayInfrastructure) { + *out = *in + if in.Replicas != nil { + in, out := &in.Replicas, &out.Replicas + *out = new(int32) + **out = **in + } + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = new(corev1.ResourceRequirements) + (*in).DeepCopyInto(*out) + } + if in.NodeSelector != nil { + in, out := &in.NodeSelector, &out.NodeSelector + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Tolerations != nil { + in, out := &in.Tolerations, &out.Tolerations + *out = make([]corev1.Toleration, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Affinity != nil { + in, out := &in.Affinity, &out.Affinity + *out = new(corev1.Affinity) + (*in).DeepCopyInto(*out) + } + if in.Labels != nil { + in, out := &in.Labels, &out.Labels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } + if in.Annotations != nil { + in, out := &in.Annotations, &out.Annotations + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayInfrastructure. +func (in *GatewayInfrastructure) DeepCopy() *GatewayInfrastructure { + if in == nil { + return nil + } + out := new(GatewayInfrastructure) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewaySpec) DeepCopyInto(out *GatewaySpec) { + *out = *in + in.APISelector.DeepCopyInto(&out.APISelector) + if in.Infrastructure != nil { + in, out := &in.Infrastructure, &out.Infrastructure + *out = new(GatewayInfrastructure) + (*in).DeepCopyInto(*out) + } + if in.ControlPlane != nil { + in, out := &in.ControlPlane, &out.ControlPlane + *out = new(GatewayControlPlane) + (*in).DeepCopyInto(*out) + } + if in.Storage != nil { + in, out := &in.Storage, &out.Storage + *out = new(GatewayStorage) + (*in).DeepCopyInto(*out) + } + if in.ConfigRef != nil { + in, out := &in.ConfigRef, &out.ConfigRef + *out = new(corev1.LocalObjectReference) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewaySpec. +func (in *GatewaySpec) DeepCopy() *GatewaySpec { + if in == nil { + return nil + } + out := new(GatewaySpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayStatus) DeepCopyInto(out *GatewayStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.LastUpdateTime != nil { + in, out := &in.LastUpdateTime, &out.LastUpdateTime + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayStatus. +func (in *GatewayStatus) DeepCopy() *GatewayStatus { + if in == nil { + return nil + } + out := new(GatewayStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayStorage) DeepCopyInto(out *GatewayStorage) { + *out = *in + if in.ConnectionSecretRef != nil { + in, out := &in.ConnectionSecretRef, &out.ConnectionSecretRef + *out = new(corev1.SecretKeySelector) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayStorage. +func (in *GatewayStorage) DeepCopy() *GatewayStorage { + if in == nil { + return nil + } + out := new(GatewayStorage) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *GatewayTLSConfig) DeepCopyInto(out *GatewayTLSConfig) { + *out = *in + if in.Enabled != nil { + in, out := &in.Enabled, &out.Enabled + *out = new(bool) + **out = **in + } + if in.CertSecretRef != nil { + in, out := &in.CertSecretRef, &out.CertSecretRef + *out = new(corev1.SecretKeySelector) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new GatewayTLSConfig. +func (in *GatewayTLSConfig) DeepCopy() *GatewayTLSConfig { + if in == nil { + return nil + } + out := new(GatewayTLSConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LLMAccessControl) DeepCopyInto(out *LLMAccessControl) { + *out = *in + if in.Exceptions != nil { + in, out := &in.Exceptions, &out.Exceptions + *out = make([]RouteException, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LLMAccessControl. +func (in *LLMAccessControl) DeepCopy() *LLMAccessControl { + if in == nil { + return nil + } + out := new(LLMAccessControl) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LLMPolicy) DeepCopyInto(out *LLMPolicy) { + *out = *in + if in.Paths != nil { + in, out := &in.Paths, &out.Paths + *out = make([]LLMPolicyPath, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LLMPolicy. +func (in *LLMPolicy) DeepCopy() *LLMPolicy { + if in == nil { + return nil + } + out := new(LLMPolicy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LLMPolicyPath) DeepCopyInto(out *LLMPolicyPath) { + *out = *in + if in.Methods != nil { + in, out := &in.Methods, &out.Methods + *out = make([]HTTPMethod, len(*in)) + copy(*out, *in) + } + if in.Params != nil { + in, out := &in.Params, &out.Params + *out = new(runtime.RawExtension) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LLMPolicyPath. +func (in *LLMPolicyPath) DeepCopy() *LLMPolicyPath { + if in == nil { + return nil + } + out := new(LLMPolicyPath) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LLMProviderConfigData) DeepCopyInto(out *LLMProviderConfigData) { + *out = *in + in.AccessControl.DeepCopyInto(&out.AccessControl) + if in.UpstreamDefinitions != nil { + in, out := &in.UpstreamDefinitions, &out.UpstreamDefinitions + *out = make([]UpstreamDefinition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.Upstream.DeepCopyInto(&out.Upstream) + if in.Context != nil { + in, out := &in.Context, &out.Context + *out = new(string) + **out = **in + } + if in.Vhost != nil { + in, out := &in.Vhost, &out.Vhost + *out = new(string) + **out = **in + } + if in.DeploymentState != nil { + in, out := &in.DeploymentState, &out.DeploymentState + *out = new(string) + **out = **in + } + if in.Policies != nil { + in, out := &in.Policies, &out.Policies + *out = make([]LLMPolicy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Resilience != nil { + in, out := &in.Resilience, &out.Resilience + *out = new(Resilience) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LLMProviderConfigData. +func (in *LLMProviderConfigData) DeepCopy() *LLMProviderConfigData { + if in == nil { + return nil + } + out := new(LLMProviderConfigData) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LLMProviderTemplateData) DeepCopyInto(out *LLMProviderTemplateData) { + *out = *in + if in.CompletionTokens != nil { + in, out := &in.CompletionTokens, &out.CompletionTokens + *out = new(ExtractionIdentifier) + **out = **in + } + if in.PromptTokens != nil { + in, out := &in.PromptTokens, &out.PromptTokens + *out = new(ExtractionIdentifier) + **out = **in + } + if in.RemainingTokens != nil { + in, out := &in.RemainingTokens, &out.RemainingTokens + *out = new(ExtractionIdentifier) + **out = **in + } + if in.RequestModel != nil { + in, out := &in.RequestModel, &out.RequestModel + *out = new(ExtractionIdentifier) + **out = **in + } + if in.ResourceMappings != nil { + in, out := &in.ResourceMappings, &out.ResourceMappings + *out = new(LLMProviderTemplateResourceMappings) + (*in).DeepCopyInto(*out) + } + if in.ResponseModel != nil { + in, out := &in.ResponseModel, &out.ResponseModel + *out = new(ExtractionIdentifier) + **out = **in + } + if in.TotalTokens != nil { + in, out := &in.TotalTokens, &out.TotalTokens + *out = new(ExtractionIdentifier) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LLMProviderTemplateData. +func (in *LLMProviderTemplateData) DeepCopy() *LLMProviderTemplateData { + if in == nil { + return nil + } + out := new(LLMProviderTemplateData) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LLMProviderTemplateResourceMapping) DeepCopyInto(out *LLMProviderTemplateResourceMapping) { + *out = *in + if in.CompletionTokens != nil { + in, out := &in.CompletionTokens, &out.CompletionTokens + *out = new(ExtractionIdentifier) + **out = **in + } + if in.PromptTokens != nil { + in, out := &in.PromptTokens, &out.PromptTokens + *out = new(ExtractionIdentifier) + **out = **in + } + if in.RemainingTokens != nil { + in, out := &in.RemainingTokens, &out.RemainingTokens + *out = new(ExtractionIdentifier) + **out = **in + } + if in.RequestModel != nil { + in, out := &in.RequestModel, &out.RequestModel + *out = new(ExtractionIdentifier) + **out = **in + } + if in.ResponseModel != nil { + in, out := &in.ResponseModel, &out.ResponseModel + *out = new(ExtractionIdentifier) + **out = **in + } + if in.TotalTokens != nil { + in, out := &in.TotalTokens, &out.TotalTokens + *out = new(ExtractionIdentifier) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LLMProviderTemplateResourceMapping. +func (in *LLMProviderTemplateResourceMapping) DeepCopy() *LLMProviderTemplateResourceMapping { + if in == nil { + return nil + } + out := new(LLMProviderTemplateResourceMapping) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LLMProviderTemplateResourceMappings) DeepCopyInto(out *LLMProviderTemplateResourceMappings) { + *out = *in + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = make([]LLMProviderTemplateResourceMapping, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LLMProviderTemplateResourceMappings. +func (in *LLMProviderTemplateResourceMappings) DeepCopy() *LLMProviderTemplateResourceMappings { + if in == nil { + return nil + } + out := new(LLMProviderTemplateResourceMappings) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LLMProviderUpstream) DeepCopyInto(out *LLMProviderUpstream) { + *out = *in + if in.Url != nil { + in, out := &in.Url, &out.Url + *out = new(string) + **out = **in + } + if in.Ref != nil { + in, out := &in.Ref, &out.Ref + *out = new(string) + **out = **in + } + if in.HostRewrite != nil { + in, out := &in.HostRewrite, &out.HostRewrite + *out = new(string) + **out = **in + } + if in.Auth != nil { + in, out := &in.Auth, &out.Auth + *out = new(LLMUpstreamAuth) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LLMProviderUpstream. +func (in *LLMProviderUpstream) DeepCopy() *LLMProviderUpstream { + if in == nil { + return nil + } + out := new(LLMProviderUpstream) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LLMProxyAdditionalProvider) DeepCopyInto(out *LLMProxyAdditionalProvider) { + *out = *in + if in.As != nil { + in, out := &in.As, &out.As + *out = new(string) + **out = **in + } + if in.Auth != nil { + in, out := &in.Auth, &out.Auth + *out = new(LLMUpstreamAuth) + (*in).DeepCopyInto(*out) + } + if in.Transformer != nil { + in, out := &in.Transformer, &out.Transformer + *out = new(LLMProxyTransformer) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LLMProxyAdditionalProvider. +func (in *LLMProxyAdditionalProvider) DeepCopy() *LLMProxyAdditionalProvider { + if in == nil { + return nil + } + out := new(LLMProxyAdditionalProvider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LLMProxyConfigData) DeepCopyInto(out *LLMProxyConfigData) { + *out = *in + in.Provider.DeepCopyInto(&out.Provider) + if in.AdditionalProviders != nil { + in, out := &in.AdditionalProviders, &out.AdditionalProviders + *out = make([]LLMProxyAdditionalProvider, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Context != nil { + in, out := &in.Context, &out.Context + *out = new(string) + **out = **in + } + if in.Vhost != nil { + in, out := &in.Vhost, &out.Vhost + *out = new(string) + **out = **in + } + if in.DeploymentState != nil { + in, out := &in.DeploymentState, &out.DeploymentState + *out = new(string) + **out = **in + } + if in.Policies != nil { + in, out := &in.Policies, &out.Policies + *out = make([]LLMPolicy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Resilience != nil { + in, out := &in.Resilience, &out.Resilience + *out = new(Resilience) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LLMProxyConfigData. +func (in *LLMProxyConfigData) DeepCopy() *LLMProxyConfigData { + if in == nil { + return nil + } + out := new(LLMProxyConfigData) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LLMProxyProvider) DeepCopyInto(out *LLMProxyProvider) { + *out = *in + if in.Auth != nil { + in, out := &in.Auth, &out.Auth + *out = new(LLMUpstreamAuth) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LLMProxyProvider. +func (in *LLMProxyProvider) DeepCopy() *LLMProxyProvider { + if in == nil { + return nil + } + out := new(LLMProxyProvider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LLMProxyTransformer) DeepCopyInto(out *LLMProxyTransformer) { + *out = *in + if in.Params != nil { + in, out := &in.Params, &out.Params + *out = new(runtime.RawExtension) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LLMProxyTransformer. +func (in *LLMProxyTransformer) DeepCopy() *LLMProxyTransformer { + if in == nil { + return nil + } + out := new(LLMProxyTransformer) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LLMUpstreamAuth) DeepCopyInto(out *LLMUpstreamAuth) { + *out = *in + if in.Header != nil { + in, out := &in.Header, &out.Header + *out = new(string) + **out = **in + } + in.Value.DeepCopyInto(&out.Value) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LLMUpstreamAuth. +func (in *LLMUpstreamAuth) DeepCopy() *LLMUpstreamAuth { + if in == nil { + return nil + } + out := new(LLMUpstreamAuth) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LlmProvider) DeepCopyInto(out *LlmProvider) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LlmProvider. +func (in *LlmProvider) DeepCopy() *LlmProvider { + if in == nil { + return nil + } + out := new(LlmProvider) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LlmProvider) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LlmProviderList) DeepCopyInto(out *LlmProviderList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]LlmProvider, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LlmProviderList. +func (in *LlmProviderList) DeepCopy() *LlmProviderList { + if in == nil { + return nil + } + out := new(LlmProviderList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LlmProviderList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LlmProviderTemplate) DeepCopyInto(out *LlmProviderTemplate) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LlmProviderTemplate. +func (in *LlmProviderTemplate) DeepCopy() *LlmProviderTemplate { + if in == nil { + return nil + } + out := new(LlmProviderTemplate) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LlmProviderTemplate) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LlmProviderTemplateList) DeepCopyInto(out *LlmProviderTemplateList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]LlmProviderTemplate, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LlmProviderTemplateList. +func (in *LlmProviderTemplateList) DeepCopy() *LlmProviderTemplateList { + if in == nil { + return nil + } + out := new(LlmProviderTemplateList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LlmProviderTemplateList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LlmProxy) DeepCopyInto(out *LlmProxy) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LlmProxy. +func (in *LlmProxy) DeepCopy() *LlmProxy { + if in == nil { + return nil + } + out := new(LlmProxy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LlmProxy) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LlmProxyList) DeepCopyInto(out *LlmProxyList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]LlmProxy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LlmProxyList. +func (in *LlmProxyList) DeepCopy() *LlmProxyList { + if in == nil { + return nil + } + out := new(LlmProxyList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *LlmProxyList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MCPPrompt) DeepCopyInto(out *MCPPrompt) { + *out = *in + if in.Title != nil { + in, out := &in.Title, &out.Title + *out = new(string) + **out = **in + } + if in.Description != nil { + in, out := &in.Description, &out.Description + *out = new(string) + **out = **in + } + if in.Arguments != nil { + in, out := &in.Arguments, &out.Arguments + *out = make([]MCPPromptArgument, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MCPPrompt. +func (in *MCPPrompt) DeepCopy() *MCPPrompt { + if in == nil { + return nil + } + out := new(MCPPrompt) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MCPPromptArgument) DeepCopyInto(out *MCPPromptArgument) { + *out = *in + if in.Title != nil { + in, out := &in.Title, &out.Title + *out = new(string) + **out = **in + } + if in.Description != nil { + in, out := &in.Description, &out.Description + *out = new(string) + **out = **in + } + if in.Required != nil { + in, out := &in.Required, &out.Required + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MCPPromptArgument. +func (in *MCPPromptArgument) DeepCopy() *MCPPromptArgument { + if in == nil { + return nil + } + out := new(MCPPromptArgument) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MCPProxyConfigData) DeepCopyInto(out *MCPProxyConfigData) { + *out = *in + if in.UpstreamDefinitions != nil { + in, out := &in.UpstreamDefinitions, &out.UpstreamDefinitions + *out = make([]UpstreamDefinition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + in.Upstream.DeepCopyInto(&out.Upstream) + if in.Context != nil { + in, out := &in.Context, &out.Context + *out = new(string) + **out = **in + } + if in.Vhost != nil { + in, out := &in.Vhost, &out.Vhost + *out = new(string) + **out = **in + } + if in.SpecVersion != nil { + in, out := &in.SpecVersion, &out.SpecVersion + *out = new(string) + **out = **in + } + if in.DeploymentState != nil { + in, out := &in.DeploymentState, &out.DeploymentState + *out = new(string) + **out = **in + } + if in.Prompts != nil { + in, out := &in.Prompts, &out.Prompts + *out = make([]MCPPrompt, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = make([]MCPResource, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Tools != nil { + in, out := &in.Tools, &out.Tools + *out = make([]MCPTool, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Policies != nil { + in, out := &in.Policies, &out.Policies + *out = make([]Policy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Resilience != nil { + in, out := &in.Resilience, &out.Resilience + *out = new(Resilience) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MCPProxyConfigData. +func (in *MCPProxyConfigData) DeepCopy() *MCPProxyConfigData { + if in == nil { + return nil + } + out := new(MCPProxyConfigData) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MCPResource) DeepCopyInto(out *MCPResource) { + *out = *in + if in.Title != nil { + in, out := &in.Title, &out.Title + *out = new(string) + **out = **in + } + if in.Description != nil { + in, out := &in.Description, &out.Description + *out = new(string) + **out = **in + } + if in.MimeType != nil { + in, out := &in.MimeType, &out.MimeType + *out = new(string) + **out = **in + } + if in.Size != nil { + in, out := &in.Size, &out.Size + *out = new(int64) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MCPResource. +func (in *MCPResource) DeepCopy() *MCPResource { + if in == nil { + return nil + } + out := new(MCPResource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MCPTool) DeepCopyInto(out *MCPTool) { + *out = *in + if in.Title != nil { + in, out := &in.Title, &out.Title + *out = new(string) + **out = **in + } + if in.OutputSchema != nil { + in, out := &in.OutputSchema, &out.OutputSchema + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MCPTool. +func (in *MCPTool) DeepCopy() *MCPTool { + if in == nil { + return nil + } + out := new(MCPTool) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MCPUpstream) DeepCopyInto(out *MCPUpstream) { + *out = *in + if in.Url != nil { + in, out := &in.Url, &out.Url + *out = new(string) + **out = **in + } + if in.Ref != nil { + in, out := &in.Ref, &out.Ref + *out = new(string) + **out = **in + } + if in.HostRewrite != nil { + in, out := &in.HostRewrite, &out.HostRewrite + *out = new(string) + **out = **in + } + if in.Auth != nil { + in, out := &in.Auth, &out.Auth + *out = new(MCPUpstreamAuth) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MCPUpstream. +func (in *MCPUpstream) DeepCopy() *MCPUpstream { + if in == nil { + return nil + } + out := new(MCPUpstream) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *MCPUpstreamAuth) DeepCopyInto(out *MCPUpstreamAuth) { + *out = *in + if in.Header != nil { + in, out := &in.Header, &out.Header + *out = new(string) + **out = **in + } + in.Value.DeepCopyInto(&out.Value) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MCPUpstreamAuth. +func (in *MCPUpstreamAuth) DeepCopy() *MCPUpstreamAuth { + if in == nil { + return nil + } + out := new(MCPUpstreamAuth) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedSecret) DeepCopyInto(out *ManagedSecret) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedSecret. +func (in *ManagedSecret) DeepCopy() *ManagedSecret { + if in == nil { + return nil + } + out := new(ManagedSecret) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ManagedSecret) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ManagedSecretList) DeepCopyInto(out *ManagedSecretList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ManagedSecret, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ManagedSecretList. +func (in *ManagedSecretList) DeepCopy() *ManagedSecretList { + if in == nil { + return nil + } + out := new(ManagedSecretList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ManagedSecretList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Mcp) DeepCopyInto(out *Mcp) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Mcp. +func (in *Mcp) DeepCopy() *Mcp { + if in == nil { + return nil + } + out := new(Mcp) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Mcp) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *McpList) DeepCopyInto(out *McpList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Mcp, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new McpList. +func (in *McpList) DeepCopy() *McpList { + if in == nil { + return nil + } + out := new(McpList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *McpList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Operation) DeepCopyInto(out *Operation) { + *out = *in + if in.Match != nil { + in, out := &in.Match, &out.Match + *out = new(OperationMatch) + (*in).DeepCopyInto(*out) + } + if in.Policies != nil { + in, out := &in.Policies, &out.Policies + *out = make([]Policy, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.Resilience != nil { + in, out := &in.Resilience, &out.Resilience + *out = new(Resilience) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Operation. +func (in *Operation) DeepCopy() *Operation { + if in == nil { + return nil + } + out := new(Operation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OperationHeaderMatch) DeepCopyInto(out *OperationHeaderMatch) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OperationHeaderMatch. +func (in *OperationHeaderMatch) DeepCopy() *OperationHeaderMatch { + if in == nil { + return nil + } + out := new(OperationHeaderMatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OperationMatch) DeepCopyInto(out *OperationMatch) { + *out = *in + out.Path = in.Path + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = make([]OperationHeaderMatch, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OperationMatch. +func (in *OperationMatch) DeepCopy() *OperationMatch { + if in == nil { + return nil + } + out := new(OperationMatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OperationPathMatch) DeepCopyInto(out *OperationPathMatch) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OperationPathMatch. +func (in *OperationPathMatch) DeepCopy() *OperationPathMatch { + if in == nil { + return nil + } + out := new(OperationPathMatch) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Policy) DeepCopyInto(out *Policy) { + *out = *in + if in.ExecutionCondition != nil { + in, out := &in.ExecutionCondition, &out.ExecutionCondition + *out = new(string) + **out = **in + } + if in.Params != nil { + in, out := &in.Params, &out.Params + *out = new(runtime.RawExtension) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Policy. +func (in *Policy) DeepCopy() *Policy { + if in == nil { + return nil + } + out := new(Policy) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Resilience) DeepCopyInto(out *Resilience) { + *out = *in + if in.Timeout != nil { + in, out := &in.Timeout, &out.Timeout + *out = new(string) + **out = **in + } + if in.IdleTimeout != nil { + in, out := &in.IdleTimeout, &out.IdleTimeout + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resilience. +func (in *Resilience) DeepCopy() *Resilience { + if in == nil { + return nil + } + out := new(Resilience) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceStatus) DeepCopyInto(out *ResourceStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.LastUpdateTime != nil { + in, out := &in.LastUpdateTime, &out.LastUpdateTime + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceStatus. +func (in *ResourceStatus) DeepCopy() *ResourceStatus { + if in == nil { + return nil + } + out := new(ResourceStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RestApi) DeepCopyInto(out *RestApi) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RestApi. +func (in *RestApi) DeepCopy() *RestApi { + if in == nil { + return nil + } + out := new(RestApi) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RestApi) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RestApiList) DeepCopyInto(out *RestApiList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]RestApi, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RestApiList. +func (in *RestApiList) DeepCopy() *RestApiList { + if in == nil { + return nil + } + out := new(RestApiList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *RestApiList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RestApiStatus) DeepCopyInto(out *RestApiStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + if in.LastUpdateTime != nil { + in, out := &in.LastUpdateTime, &out.LastUpdateTime + *out = (*in).DeepCopy() + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RestApiStatus. +func (in *RestApiStatus) DeepCopy() *RestApiStatus { + if in == nil { + return nil + } + out := new(RestApiStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *RouteException) DeepCopyInto(out *RouteException) { + *out = *in + if in.Methods != nil { + in, out := &in.Methods, &out.Methods + *out = make([]HTTPMethod, len(*in)) + copy(*out, *in) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new RouteException. +func (in *RouteException) DeepCopy() *RouteException { + if in == nil { + return nil + } + out := new(RouteException) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretSpec) DeepCopyInto(out *SecretSpec) { + *out = *in + if in.Description != nil { + in, out := &in.Description, &out.Description + *out = new(string) + **out = **in + } + in.Value.DeepCopyInto(&out.Value) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretSpec. +func (in *SecretSpec) DeepCopy() *SecretSpec { + if in == nil { + return nil + } + out := new(SecretSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SecretValueSource) DeepCopyInto(out *SecretValueSource) { + *out = *in + if in.Value != nil { + in, out := &in.Value, &out.Value + *out = new(string) + **out = **in + } + if in.ValueFrom != nil { + in, out := &in.ValueFrom, &out.ValueFrom + *out = new(corev1.SecretKeySelector) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SecretValueSource. +func (in *SecretValueSource) DeepCopy() *SecretValueSource { + if in == nil { + return nil + } + out := new(SecretValueSource) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Subscription) DeepCopyInto(out *Subscription) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Subscription. +func (in *Subscription) DeepCopy() *Subscription { + if in == nil { + return nil + } + out := new(Subscription) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Subscription) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionList) DeepCopyInto(out *SubscriptionList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Subscription, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionList. +func (in *SubscriptionList) DeepCopy() *SubscriptionList { + if in == nil { + return nil + } + out := new(SubscriptionList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *SubscriptionList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionPlan) DeepCopyInto(out *SubscriptionPlan) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionPlan. +func (in *SubscriptionPlan) DeepCopy() *SubscriptionPlan { + if in == nil { + return nil + } + out := new(SubscriptionPlan) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *SubscriptionPlan) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionPlanList) DeepCopyInto(out *SubscriptionPlanList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]SubscriptionPlan, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionPlanList. +func (in *SubscriptionPlanList) DeepCopy() *SubscriptionPlanList { + if in == nil { + return nil + } + out := new(SubscriptionPlanList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *SubscriptionPlanList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionPlanSpec) DeepCopyInto(out *SubscriptionPlanSpec) { + *out = *in + if in.BillingPlan != nil { + in, out := &in.BillingPlan, &out.BillingPlan + *out = new(string) + **out = **in + } + if in.ExpiryTime != nil { + in, out := &in.ExpiryTime, &out.ExpiryTime + *out = (*in).DeepCopy() + } + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(string) + **out = **in + } + if in.StopOnQuotaReach != nil { + in, out := &in.StopOnQuotaReach, &out.StopOnQuotaReach + *out = new(bool) + **out = **in + } + if in.ThrottleLimitCount != nil { + in, out := &in.ThrottleLimitCount, &out.ThrottleLimitCount + *out = new(int64) + **out = **in + } + if in.ThrottleLimitUnit != nil { + in, out := &in.ThrottleLimitUnit, &out.ThrottleLimitUnit + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionPlanSpec. +func (in *SubscriptionPlanSpec) DeepCopy() *SubscriptionPlanSpec { + if in == nil { + return nil + } + out := new(SubscriptionPlanSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *SubscriptionSpec) DeepCopyInto(out *SubscriptionSpec) { + *out = *in + in.SubscriptionToken.DeepCopyInto(&out.SubscriptionToken) + if in.ApplicationId != nil { + in, out := &in.ApplicationId, &out.ApplicationId + *out = new(string) + **out = **in + } + if in.SubscriptionPlanId != nil { + in, out := &in.SubscriptionPlanId, &out.SubscriptionPlanId + *out = new(string) + **out = **in + } + if in.BillingCustomerId != nil { + in, out := &in.BillingCustomerId, &out.BillingCustomerId + *out = new(string) + **out = **in + } + if in.BillingSubscriptionId != nil { + in, out := &in.BillingSubscriptionId, &out.BillingSubscriptionId + *out = new(string) + **out = **in + } + if in.Status != nil { + in, out := &in.Status, &out.Status + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new SubscriptionSpec. +func (in *SubscriptionSpec) DeepCopy() *SubscriptionSpec { + if in == nil { + return nil + } + out := new(SubscriptionSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Upstream) DeepCopyInto(out *Upstream) { + *out = *in + if in.Url != nil { + in, out := &in.Url, &out.Url + *out = new(string) + **out = **in + } + if in.Ref != nil { + in, out := &in.Ref, &out.Ref + *out = new(string) + **out = **in + } + if in.HostRewrite != nil { + in, out := &in.HostRewrite, &out.HostRewrite + *out = new(UpstreamHostRewrite) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Upstream. +func (in *Upstream) DeepCopy() *Upstream { + if in == nil { + return nil + } + out := new(Upstream) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UpstreamConfig) DeepCopyInto(out *UpstreamConfig) { + *out = *in + in.Main.DeepCopyInto(&out.Main) + if in.Sandbox != nil { + in, out := &in.Sandbox, &out.Sandbox + *out = new(Upstream) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpstreamConfig. +func (in *UpstreamConfig) DeepCopy() *UpstreamConfig { + if in == nil { + return nil + } + out := new(UpstreamConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UpstreamDefinition) DeepCopyInto(out *UpstreamDefinition) { + *out = *in + if in.BasePath != nil { + in, out := &in.BasePath, &out.BasePath + *out = new(string) + **out = **in + } + if in.Timeout != nil { + in, out := &in.Timeout, &out.Timeout + *out = new(UpstreamTimeout) + (*in).DeepCopyInto(*out) + } + if in.Upstreams != nil { + in, out := &in.Upstreams, &out.Upstreams + *out = make([]WeightedUpstream, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpstreamDefinition. +func (in *UpstreamDefinition) DeepCopy() *UpstreamDefinition { + if in == nil { + return nil + } + out := new(UpstreamDefinition) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *UpstreamTimeout) DeepCopyInto(out *UpstreamTimeout) { + *out = *in + if in.Connect != nil { + in, out := &in.Connect, &out.Connect + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new UpstreamTimeout. +func (in *UpstreamTimeout) DeepCopy() *UpstreamTimeout { + if in == nil { + return nil + } + out := new(UpstreamTimeout) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *VhostConfig) DeepCopyInto(out *VhostConfig) { + *out = *in + if in.Sandbox != nil { + in, out := &in.Sandbox, &out.Sandbox + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VhostConfig. +func (in *VhostConfig) DeepCopy() *VhostConfig { + if in == nil { + return nil + } + out := new(VhostConfig) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *WeightedUpstream) DeepCopyInto(out *WeightedUpstream) { + *out = *in + if in.Weight != nil { + in, out := &in.Weight, &out.Weight + *out = new(int) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new WeightedUpstream. +func (in *WeightedUpstream) DeepCopy() *WeightedUpstream { + if in == nil { + return nil + } + out := new(WeightedUpstream) + in.DeepCopyInto(out) + return out +} diff --git a/kubernetes/gateway-operator/api/v1alpha1/conversion.go b/kubernetes/gateway-operator/api/v1alpha1/conversion.go new file mode 100644 index 0000000000..e6e0dbdd05 --- /dev/null +++ b/kubernetes/gateway-operator/api/v1alpha1/conversion.go @@ -0,0 +1,289 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +// The v1alpha1 types are conversion spokes: each root kind implements the +// conversion.Convertible interface (ConvertTo/ConvertFrom) so the conversion +// webhook can translate them to and from the v1 hub (storage) types. +// +// The v1alpha1 and v1 schemas are field-identical (the promotion changed only +// the version label), so Spec and Status are copied with a JSON round-trip. +// ObjectMeta is copied directly. TypeMeta (apiVersion/kind) is deliberately +// NOT copied — the conversion machinery sets it on the destination. + +import ( + "encoding/json" + "fmt" + + "sigs.k8s.io/controller-runtime/pkg/conversion" + + v1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" +) + +// convertViaJSON copies in into out by marshaling to JSON and unmarshaling +// back. It is exact when in and out have identical JSON shapes, which holds +// for the v1alpha1 <-> v1 Spec/Status pairs. +func convertViaJSON(in, out any) error { + data, err := json.Marshal(in) + if err != nil { + return fmt.Errorf("marshal for conversion: %w", err) + } + if err := json.Unmarshal(data, out); err != nil { + return fmt.Errorf("unmarshal for conversion: %w", err) + } + return nil +} + +// --- RestApi --- + +func (src *RestApi) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*v1.RestApi) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +func (dst *RestApi) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*v1.RestApi) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +// --- APIGateway --- + +func (src *APIGateway) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*v1.APIGateway) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +func (dst *APIGateway) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*v1.APIGateway) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +// --- ApiKey --- + +func (src *ApiKey) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*v1.ApiKey) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +func (dst *ApiKey) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*v1.ApiKey) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +// --- APIPolicy --- + +func (src *APIPolicy) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*v1.APIPolicy) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +func (dst *APIPolicy) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*v1.APIPolicy) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +// --- Certificate --- + +func (src *Certificate) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*v1.Certificate) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +func (dst *Certificate) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*v1.Certificate) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +// --- LlmProvider --- + +func (src *LlmProvider) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*v1.LlmProvider) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +func (dst *LlmProvider) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*v1.LlmProvider) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +// --- LlmProviderTemplate --- + +func (src *LlmProviderTemplate) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*v1.LlmProviderTemplate) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +func (dst *LlmProviderTemplate) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*v1.LlmProviderTemplate) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +// --- LlmProxy --- + +func (src *LlmProxy) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*v1.LlmProxy) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +func (dst *LlmProxy) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*v1.LlmProxy) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +// --- ManagedSecret --- + +func (src *ManagedSecret) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*v1.ManagedSecret) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +func (dst *ManagedSecret) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*v1.ManagedSecret) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +// --- Mcp --- + +func (src *Mcp) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*v1.Mcp) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +func (dst *Mcp) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*v1.Mcp) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +// --- Subscription --- + +func (src *Subscription) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*v1.Subscription) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +func (dst *Subscription) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*v1.Subscription) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +// --- SubscriptionPlan --- + +func (src *SubscriptionPlan) ConvertTo(dstRaw conversion.Hub) error { + dst := dstRaw.(*v1.SubscriptionPlan) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} + +func (dst *SubscriptionPlan) ConvertFrom(srcRaw conversion.Hub) error { + src := srcRaw.(*v1.SubscriptionPlan) + dst.ObjectMeta = src.ObjectMeta + if err := convertViaJSON(src.Spec, &dst.Spec); err != nil { + return err + } + return convertViaJSON(src.Status, &dst.Status) +} diff --git a/kubernetes/gateway-operator/api/v1alpha1/conversion_test.go b/kubernetes/gateway-operator/api/v1alpha1/conversion_test.go new file mode 100644 index 0000000000..ea168a52d1 --- /dev/null +++ b/kubernetes/gateway-operator/api/v1alpha1/conversion_test.go @@ -0,0 +1,138 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "reflect" + "testing" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "sigs.k8s.io/controller-runtime/pkg/conversion" + + v1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" +) + +// TestRestApiConversionRoundTrip exercises a fully-populated RestApi through +// v1alpha1 -> v1 -> v1alpha1 and asserts equality across ObjectMeta, Spec and +// Status. +func TestRestApiConversionRoundTrip(t *testing.T) { + orig := &RestApi{ + ObjectMeta: metav1.ObjectMeta{ + Name: "orders-api", + Namespace: "apis", + Labels: map[string]string{"team": "platform"}, + Annotations: map[string]string{"note": "conversion"}, + Generation: 7, + }, + Spec: APIConfigData{ + Context: "/orders", + DisplayName: "Orders API", + Operations: []Operation{ + {Method: OperationMethod("GET"), Path: "/orders"}, + }, + }, + Status: RestApiStatus{ + Conditions: []metav1.Condition{ + {Type: "Ready", Status: metav1.ConditionTrue, Reason: "Deployed", Message: "ok"}, + }, + }, + } + + hub := &v1.RestApi{} + if err := orig.ConvertTo(hub); err != nil { + t.Fatalf("ConvertTo: %v", err) + } + if hub.Name != orig.Name || hub.Spec.Context != orig.Spec.Context || hub.Spec.DisplayName != orig.Spec.DisplayName { + t.Fatalf("hub not populated correctly: %+v", hub) + } + if len(hub.Spec.Operations) != 1 || string(hub.Spec.Operations[0].Method) != "GET" { + t.Fatalf("hub operations not converted: %+v", hub.Spec.Operations) + } + + back := &RestApi{} + if err := back.ConvertFrom(hub); err != nil { + t.Fatalf("ConvertFrom: %v", err) + } + if !reflect.DeepEqual(orig.ObjectMeta, back.ObjectMeta) { + t.Errorf("ObjectMeta round-trip mismatch:\n got %+v\n want %+v", back.ObjectMeta, orig.ObjectMeta) + } + if !reflect.DeepEqual(orig.Spec, back.Spec) { + t.Errorf("Spec round-trip mismatch:\n got %+v\n want %+v", back.Spec, orig.Spec) + } + if !reflect.DeepEqual(orig.Status, back.Status) { + t.Errorf("Status round-trip mismatch:\n got %+v\n want %+v", back.Status, orig.Status) + } +} + +// TestAllKindsConversionPlumbing verifies that every spoke kind implements the +// Convertible interface, converts to the correct hub type, preserves +// ObjectMeta, and converts back — for all 12 CRD kinds. +func TestAllKindsConversionPlumbing(t *testing.T) { + meta := func() metav1.ObjectMeta { + return metav1.ObjectMeta{ + Name: "sample", + Namespace: "ns", + Labels: map[string]string{"a": "b"}, + Generation: 3, + } + } + + cases := []struct { + name string + spoke conversion.Convertible + hub conversion.Hub + fresh conversion.Convertible + }{ + {"RestApi", &RestApi{ObjectMeta: meta()}, &v1.RestApi{}, &RestApi{}}, + {"APIGateway", &APIGateway{ObjectMeta: meta()}, &v1.APIGateway{}, &APIGateway{}}, + {"ApiKey", &ApiKey{ObjectMeta: meta()}, &v1.ApiKey{}, &ApiKey{}}, + {"APIPolicy", &APIPolicy{ObjectMeta: meta()}, &v1.APIPolicy{}, &APIPolicy{}}, + {"Certificate", &Certificate{ObjectMeta: meta()}, &v1.Certificate{}, &Certificate{}}, + {"LlmProvider", &LlmProvider{ObjectMeta: meta()}, &v1.LlmProvider{}, &LlmProvider{}}, + {"LlmProviderTemplate", &LlmProviderTemplate{ObjectMeta: meta()}, &v1.LlmProviderTemplate{}, &LlmProviderTemplate{}}, + {"LlmProxy", &LlmProxy{ObjectMeta: meta()}, &v1.LlmProxy{}, &LlmProxy{}}, + {"ManagedSecret", &ManagedSecret{ObjectMeta: meta()}, &v1.ManagedSecret{}, &ManagedSecret{}}, + {"Mcp", &Mcp{ObjectMeta: meta()}, &v1.Mcp{}, &Mcp{}}, + {"Subscription", &Subscription{ObjectMeta: meta()}, &v1.Subscription{}, &Subscription{}}, + {"SubscriptionPlan", &SubscriptionPlan{ObjectMeta: meta()}, &v1.SubscriptionPlan{}, &SubscriptionPlan{}}, + } + + for _, tc := range cases { + t.Run(tc.name, func(t *testing.T) { + if err := tc.spoke.ConvertTo(tc.hub); err != nil { + t.Fatalf("ConvertTo: %v", err) + } + spokeMeta := tc.spoke.(metav1.Object) + hubMeta := tc.hub.(metav1.Object) + if hubMeta.GetName() != spokeMeta.GetName() || + hubMeta.GetNamespace() != spokeMeta.GetNamespace() || + hubMeta.GetGeneration() != spokeMeta.GetGeneration() || + !reflect.DeepEqual(hubMeta.GetLabels(), spokeMeta.GetLabels()) { + t.Fatalf("hub ObjectMeta not preserved: got %+v", hubMeta) + } + + if err := tc.fresh.ConvertFrom(tc.hub); err != nil { + t.Fatalf("ConvertFrom: %v", err) + } + freshMeta := tc.fresh.(metav1.Object) + if freshMeta.GetName() != spokeMeta.GetName() || + !reflect.DeepEqual(freshMeta.GetLabels(), spokeMeta.GetLabels()) { + t.Fatalf("round-trip ObjectMeta mismatch: got %+v", freshMeta) + } + }) + } +} diff --git a/kubernetes/gateway-operator/cmd/main.go b/kubernetes/gateway-operator/cmd/main.go index d0f83aa312..027babfb7f 100644 --- a/kubernetes/gateway-operator/cmd/main.go +++ b/kubernetes/gateway-operator/cmd/main.go @@ -39,7 +39,8 @@ import ( gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" "github.com/go-logr/zapr" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" + apiv1alpha1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/config" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/controller" "github.com/wso2/api-platform/kubernetes/gateway-operator/pkg/logger" @@ -55,6 +56,7 @@ func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(apiv1.AddToScheme(scheme)) + utilruntime.Must(apiv1alpha1.AddToScheme(scheme)) utilruntime.Must(gatewayv1.AddToScheme(scheme)) utilruntime.Must(gatewayv1beta1.AddToScheme(scheme)) //+kubebuilder:scaffold:scheme @@ -125,8 +127,12 @@ func main() { tlsOpts = append(tlsOpts, disableHTTP2) } + // CertDir must match the path where the Helm chart mounts the webhook + // serving-cert Secret (see operator-helm-chart deployment.yaml). It is kept + // off /tmp to avoid nesting under the /tmp emptyDir mount. webhookServer := webhook.NewServer(webhook.Options{ TLSOpts: tlsOpts, + CertDir: "/etc/gateway-operator/webhook-certs", }) // Parse WATCH_NAMESPACES env var @@ -243,6 +249,31 @@ func main() { os.Exit(1) } } + // Register the CRD conversion webhook for every kind. The v1 types are the + // hub (storage version) and the served v1alpha1 types convert to/from them. + // Guarded by ENABLE_WEBHOOKS so environments without serving certs (e.g. + // envtest) can disable it. NewWebhookManagedBy is generic, so each kind is + // registered explicitly rather than in a loop. + if os.Getenv("ENABLE_WEBHOOKS") != "false" { + registerConversionWebhook := func(kind string, err error) { + if err != nil { + setupLog.Error(err, "unable to create conversion webhook", "kind", kind) + os.Exit(1) + } + } + registerConversionWebhook("RestApi", ctrl.NewWebhookManagedBy(mgr, &apiv1.RestApi{}).Complete()) + registerConversionWebhook("APIGateway", ctrl.NewWebhookManagedBy(mgr, &apiv1.APIGateway{}).Complete()) + registerConversionWebhook("ApiKey", ctrl.NewWebhookManagedBy(mgr, &apiv1.ApiKey{}).Complete()) + registerConversionWebhook("APIPolicy", ctrl.NewWebhookManagedBy(mgr, &apiv1.APIPolicy{}).Complete()) + registerConversionWebhook("Certificate", ctrl.NewWebhookManagedBy(mgr, &apiv1.Certificate{}).Complete()) + registerConversionWebhook("LlmProvider", ctrl.NewWebhookManagedBy(mgr, &apiv1.LlmProvider{}).Complete()) + registerConversionWebhook("LlmProviderTemplate", ctrl.NewWebhookManagedBy(mgr, &apiv1.LlmProviderTemplate{}).Complete()) + registerConversionWebhook("LlmProxy", ctrl.NewWebhookManagedBy(mgr, &apiv1.LlmProxy{}).Complete()) + registerConversionWebhook("ManagedSecret", ctrl.NewWebhookManagedBy(mgr, &apiv1.ManagedSecret{}).Complete()) + registerConversionWebhook("Mcp", ctrl.NewWebhookManagedBy(mgr, &apiv1.Mcp{}).Complete()) + registerConversionWebhook("Subscription", ctrl.NewWebhookManagedBy(mgr, &apiv1.Subscription{}).Complete()) + registerConversionWebhook("SubscriptionPlan", ctrl.NewWebhookManagedBy(mgr, &apiv1.SubscriptionPlan{}).Complete()) + } //+kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { @@ -253,6 +284,12 @@ func main() { setupLog.Error(err, "unable to set up ready check") os.Exit(1) } + if os.Getenv("ENABLE_WEBHOOKS") != "false" { + if err := mgr.AddReadyzCheck("webhook", mgr.GetWebhookServer().StartedChecker()); err != nil { + setupLog.Error(err, "unable to set up webhook readiness check") + os.Exit(1) + } + } setupLog.Info("starting manager") if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { diff --git a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_apigateways.yaml b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_apigateways.yaml index cd648866b8..a289afe7d2 100644 --- a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_apigateways.yaml +++ b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_apigateways.yaml @@ -14,6 +14,1377 @@ spec: singular: apigateway scope: Namespaced versions: + - name: v1 + schema: + openAPIV3Schema: + description: APIGateway is the Schema for the apigateways API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: GatewaySpec defines the desired state of APIGateway + properties: + apiSelector: + description: APISelector defines how this gateway selects which APIs + to route + properties: + matchExpressions: + description: |- + MatchExpressions is a list of label selector requirements for label-based selection. + Only used when Scope is "LabelSelector". + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + MatchLabels is a map of {key,value} pairs for label-based selection. + Only used when Scope is "LabelSelector". + An API must have all specified labels to be selected. + type: object + namespaces: + description: |- + Namespaces is a list of namespaces from which APIs are selected. + Only used when Scope is "Namespaced". + If empty with Namespaced scope, only APIs in the gateway's namespace are selected. + items: + type: string + type: array + scope: + default: Cluster + description: Scope determines the API selection strategy + enum: + - Cluster + - Namespaced + - LabelSelector + type: string + required: + - scope + type: object + configRef: + description: |- + ConfigRef references a ConfigMap containing custom Helm values configuration. + The ConfigMap data should contain a key "values.yaml" with the Helm values content. + If not specified, the operator will use the default mounted configuration. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + controlPlane: + description: ControlPlane defines the control plane connection settings + properties: + host: + description: Host is the control plane host address + type: string + tls: + description: TLS settings for control plane connection + properties: + certSecretRef: + description: CertSecretRef references a secret containing + TLS certificates + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + enabled: + default: true + description: Enabled indicates whether TLS is enabled + type: boolean + type: object + tokenSecretRef: + description: TokenSecretRef references a secret containing the + authentication token + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + infrastructure: + description: Infrastructure defines the deployment configuration for + the gateway + properties: + affinity: + description: Affinity for pod assignment + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + annotations: + additionalProperties: + type: string + description: |- + Annotations are custom annotations propagated to all gateway-managed resources: + Deployment metadata, Pod annotations, Service metadata, and ConfigMaps. + type: object + image: + description: Image is the container image for the gateway + type: string + labels: + additionalProperties: + type: string + description: |- + Labels are custom labels propagated to all gateway-managed resources: + Deployment metadata, Pod labels, Service metadata, and ConfigMaps. + type: object + nodeSelector: + additionalProperties: + type: string + description: NodeSelector is a selector for node assignment + type: object + replicas: + default: 1 + description: Replicas is the number of gateway instances to deploy + format: int32 + minimum: 1 + type: integer + resources: + description: Resources defines the compute resources for gateway + pods + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This field depends on the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + routerImage: + description: RouterImage is the container image for the router/proxy + type: string + tolerations: + description: Tolerations for pod assignment + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + type: object + storage: + description: Storage defines the storage configuration for the gateway + properties: + connectionSecretRef: + description: |- + ConnectionSecretRef references a secret containing database connection details + (used for postgres, mysql, etc.) + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + sqlitePath: + description: SQLitePath is the path for SQLite database (used + when Type is sqlite) + type: string + type: + default: sqlite + description: Type is the storage backend type (sqlite, postgres, + mysql, etc.) + enum: + - sqlite + - postgres + - mysql + type: string + type: object + required: + - apiSelector + type: object + status: + description: GatewayStatus defines the observed state of APIGateway + properties: + appliedGeneration: + description: AppliedGeneration tracks the latest spec generation that + was successfully applied to the cluster + format: int64 + type: integer + conditions: + description: Conditions represent the latest available observations + of the gateway's state + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + configHash: + description: |- + ConfigHash represents the hash of the referenced configuration + used to detect changes in ConfigMap content + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated + format: date-time + type: string + observedGeneration: + description: ObservedGeneration reflects the generation of the most + recently observed spec + format: int64 + type: integer + phase: + description: Phase represents the current phase of the gateway (Pending, + Ready, Failed) + enum: + - Reconciling + - Ready + - Failed + - Deleting + type: string + selectedAPIs: + description: SelectedAPIs is the count of APIs currently selected + by this gateway + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} - name: v1alpha1 schema: openAPIV3Schema: @@ -1382,6 +2753,6 @@ spec: type: object type: object served: true - storage: true + storage: false subresources: status: {} diff --git a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_apikeys.yaml b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_apikeys.yaml index 3e3e8d8c57..04e1f9502b 100644 --- a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_apikeys.yaml +++ b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_apikeys.yaml @@ -16,7 +16,7 @@ spec: singular: apikey scope: Namespaced versions: - - name: v1alpha1 + - name: v1 schema: openAPIV3Schema: description: |- @@ -245,3 +245,232 @@ spec: storage: true subresources: status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + ApiKey is the Schema for the apikeys API. + + The key handle in the management API is the CR's metadata.name. The + nested REST path is built from spec.parentRef.kind + spec.parentRef.name. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + ApiKeySpec mirrors the management-API APIKeyCreationRequest payload, with + the optional inline ApiKey expressed as a SecretValueSource for external- + key injection (so the value need not be inlined in the CR). + properties: + apiKey: + description: |- + ApiKey is an optional pre-generated key value (>= 36 chars). When + supplied the gateway hashes the value rather than generating its own. + properties: + value: + description: |- + Value is the inline plaintext value. Avoid for production use; prefer + ValueFrom so the secret is stored in a Kubernetes Secret. + type: string + valueFrom: + description: |- + ValueFrom selects a key from a Kubernetes Secret in the same namespace + as the owning CR. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: exactly one of value or valueFrom must be set + rule: has(self.value) != has(self.valueFrom) + displayName: + description: DisplayName is a human-readable label for the key. + type: string + expiresAt: + description: |- + ExpiresAt is an optional absolute expiry time. + Mutually exclusive with expiresIn: the ApiKey spec CEL rule + "!has(self.expiresAt) || !has(self.expiresIn)" rejects manifests that set both. + format: date-time + type: string + expiresIn: + description: |- + ExpiresIn is an optional duration after which the key expires. + Mutually exclusive with expiresAt: the ApiKey spec CEL rule + "!has(self.expiresAt) || !has(self.expiresIn)" rejects manifests that set both. + properties: + duration: + description: Duration is the magnitude of the expiry duration + (must be positive). + format: int64 + minimum: 1 + type: integer + unit: + description: Unit is the time unit of the expiry duration. + enum: + - seconds + - minutes + - hours + - days + - weeks + - months + type: string + required: + - duration + - unit + type: object + externalRefId: + description: ExternalRefId is an optional reference id for tracing. + type: string + issuer: + description: Issuer optionally constrains regeneration to a single + portal. + type: string + maskedApiKey: + description: |- + MaskedApiKey is an optional masked rendering of an externally + generated key, used purely for display by portals. + type: string + parentRef: + description: ParentRef identifies the resource the key is issued under. + properties: + kind: + description: Kind selects the parent resource kind. + enum: + - RestApi + - LlmProvider + - LlmProxy + type: string + name: + description: Name is the parent resource handle (metadata.name). + type: string + required: + - kind + - name + type: object + required: + - parentRef + type: object + x-kubernetes-validations: + - message: expiresAt and expiresIn are mutually exclusive + rule: '!has(self.expiresAt) || !has(self.expiresIn)' + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_apipolicies.yaml b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_apipolicies.yaml index 57f5b0d811..e3edf89b96 100644 --- a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_apipolicies.yaml +++ b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_apipolicies.yaml @@ -26,7 +26,7 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date - name: v1alpha1 + name: v1 schema: openAPIV3Schema: description: |- @@ -187,3 +187,174 @@ spec: storage: true subresources: status: {} + - additionalPrinterColumns: + - jsonPath: .spec.targetRef.name + name: Target + type: string + - jsonPath: .spec.policies[0].name + name: First + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + APIPolicy is a namespaced policy definition for the Gateway API HTTPRoute integration only. + Set spec.targetRef to apply policies at API level for that HTTPRoute, or omit targetRef and reference + this object from HTTPRoute rule filters (ExtensionRef) for rule/match scope. It does not apply to RestApi / APIGateway reconciliation. + (Distinct from the embedded Policy type on RestApi.) + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: APIPolicySpec holds an optional targetRef for API-level attachment + and a list of policy instances (same shape as RestApi embedded policies). + properties: + policies: + description: Policies is the list of policy instances (name, version, + optional params, executionCondition). + items: + description: Policy defines a policy attachment as embedded in RestApi + or APIConfigData. + properties: + executionCondition: + description: ExecutionCondition Expression controlling conditional + execution of the policy + type: string + name: + description: Name Name of the policy + type: string + params: + description: Params Arbitrary parameters for the policy (free-form + key/value structure) + x-kubernetes-preserve-unknown-fields: true + version: + description: Version Semantic version of the policy (for example, + v1) + pattern: ^v\d+$ + type: string + required: + - name + - version + type: object + minItems: 1 + type: array + targetRef: + description: |- + TargetRef selects the HTTPRoute for API-level policies: when set, all spec.policies entries are merged into APIConfigData.policies for that route. + When omitted, this APIPolicy applies only when referenced from HTTPRoute rule filters (ExtensionRef). + properties: + group: + description: Group of the referent (e.g. gateway.networking.k8s.io). + enum: + - gateway.networking.k8s.io + minLength: 1 + type: string + kind: + description: Kind of the referent. Use HTTPRoute for Gateway API + integration. + enum: + - HTTPRoute + minLength: 1 + type: string + name: + description: Name of the referent HTTPRoute. + minLength: 1 + type: string + namespace: + description: Namespace of the referent; defaults to the APIPolicy's + namespace if unset. + type: string + required: + - group + - kind + - name + type: object + required: + - policies + type: object + status: + description: APIPolicyStatus defines observed state. + properties: + conditions: + description: Conditions represent the latest observations. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_certificates.yaml b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_certificates.yaml index 33b61c6a7b..ae6c4d8e67 100644 --- a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_certificates.yaml +++ b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_certificates.yaml @@ -16,7 +16,7 @@ spec: singular: certificate scope: Namespaced versions: - - name: v1alpha1 + - name: v1 schema: openAPIV3Schema: description: Certificate is the Schema for the certificates API. @@ -183,3 +183,170 @@ spec: storage: true subresources: status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Certificate is the Schema for the certificates API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + CertificateSpec mirrors the management-API CertificateUploadRequest, with + the PEM bytes expressed as a SecretValueSource so production-grade + certificates can be referenced from a Kubernetes Secret rather than + inlined into the CR. + + The gateway-controller assigns a UUID id on first upload that the + controller persists to .status.id; subsequent reconcile uses + `/certificates/{status.id}` for PUT/DELETE. + properties: + certificate: + description: Certificate is the PEM-encoded X.509 certificate (single + or bundle). + properties: + value: + description: |- + Value is the inline plaintext value. Avoid for production use; prefer + ValueFrom so the secret is stored in a Kubernetes Secret. + type: string + valueFrom: + description: |- + ValueFrom selects a key from a Kubernetes Secret in the same namespace + as the owning CR. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: exactly one of value or valueFrom must be set + rule: has(self.value) != has(self.valueFrom) + displayName: + description: |- + DisplayName is a human-readable certificate name. The controller + passes it through to the management API as `name`. + type: string + required: + - certificate + - displayName + type: object + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_llmproviders.yaml b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_llmproviders.yaml index 75e0cb2c0e..72fb9c33fb 100644 --- a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_llmproviders.yaml +++ b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_llmproviders.yaml @@ -16,7 +16,7 @@ spec: singular: llmprovider scope: Namespaced versions: - - name: v1alpha1 + - name: v1 schema: openAPIV3Schema: description: LlmProvider is the Schema for the llmproviders API. @@ -408,3 +408,395 @@ spec: storage: true subresources: status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: LlmProvider is the Schema for the llmproviders API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: LLMProviderConfigData mirrors the management-API LLMProviderConfigData. + properties: + accessControl: + description: AccessControl configures path-level access control. + properties: + exceptions: + description: Exceptions are paths that override the default mode. + items: + description: RouteException defines a path/method exception + used by LLM access control. + properties: + methods: + description: Methods is the list of HTTP methods covered + by this exception. + items: + description: HTTPMethod names an allowed HTTP verb for + LLM access-control and policy paths. + enum: + - GET + - POST + - PUT + - PATCH + - DELETE + - HEAD + - OPTIONS + - '*' + type: string + type: array + path: + description: Path is the exception path pattern. + type: string + required: + - methods + - path + type: object + type: array + mode: + description: Mode selects the default access policy. + enum: + - allow_all + - deny_all + type: string + required: + - mode + type: object + context: + description: Context is the base path for all routes (must start with + /). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ + type: string + deploymentState: + description: DeploymentState toggles whether the provider is router-attached. + enum: + - deployed + - undeployed + type: string + displayName: + description: DisplayName is a human-readable LLM provider name. + type: string + policies: + description: Policies is the list of policies applied to this LLM + provider. + items: + description: LLMPolicy describes a single LLM-level policy attachment. + properties: + name: + description: Name is the name of the policy. + type: string + paths: + description: Paths lists path/method/params triples for this + policy. + items: + description: |- + LLMPolicyPath defines a path/methods combination together with policy + parameters; mirrors the management-API LLMPolicyPath. + properties: + methods: + description: Methods is the list of HTTP methods. + items: + description: HTTPMethod names an allowed HTTP verb for + LLM access-control and policy paths. + enum: + - GET + - POST + - PUT + - PATCH + - DELETE + - HEAD + - OPTIONS + - '*' + type: string + type: array + params: + description: Params is a free-form parameter object specific + to the policy. + x-kubernetes-preserve-unknown-fields: true + path: + description: Path is the route path pattern. + type: string + required: + - methods + - path + type: object + type: array + version: + description: Version is the policy version (e.g. v1). + pattern: ^v\d+$ + type: string + required: + - name + - paths + - version + type: object + type: array + resilience: + description: |- + Resilience configures API-level backend/route timeouts applied to all routes + generated for this LLM provider. Supported at the API level only. + properties: + idleTimeout: + description: IdleTimeout Per-route stream idle timeout. "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + timeout: + description: Timeout Maximum time for the entire route (request + to upstream response). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + template: + description: Template is the LlmProviderTemplate name to apply. + type: string + upstream: + description: Upstream configures the LLM upstream. + properties: + auth: + description: Auth configures upstream credentials. + properties: + header: + description: |- + Header is the HTTP header to set on outbound requests when the auth + type uses headers (e.g. api-key). + type: string + type: + description: Type identifies the auth scheme. Only api-key + is currently supported. + enum: + - api-key + type: string + value: + description: |- + Value sources the credential. Exactly one of value or valueFrom must + be set. + properties: + value: + description: |- + Value is the inline plaintext value. Avoid for production use; prefer + ValueFrom so the secret is stored in a Kubernetes Secret. + type: string + valueFrom: + description: |- + ValueFrom selects a key from a Kubernetes Secret in the same namespace + as the owning CR. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: exactly one of value or valueFrom must be set + rule: has(self.value) != has(self.valueFrom) + required: + - type + - value + type: object + hostRewrite: + description: HostRewrite controls how the Host header is handled + when routing. + enum: + - auto + - manual + type: string + ref: + description: Ref selects a predefined upstream definition by name. + type: string + url: + description: Url is the direct backend URL. + type: string + type: object + upstreamDefinitions: + description: |- + UpstreamDefinitions is the list of reusable upstream definitions (with optional + connect timeout) that upstream.ref can reference. + items: + description: |- + UpstreamDefinition is a reusable upstream configuration with an optional connect timeout and + one or more weighted load-balancing targets. Referenced from an upstream via its `ref` field + and by the dynamic-endpoint policy. Shared by RestApi, LLM Provider, and MCP; mirrors the + management-API UpstreamDefinition schema. + properties: + basePath: + description: |- + BasePath Base path prefix prepended to all requests routed through this upstream (e.g. /api/v2). + Must start with "/" and must not end with "/". Omit for root ("/"). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ + type: string + name: + description: |- + Name Unique identifier for this upstream definition (referenced by upstream.ref or the + dynamic-endpoint policy). + maxLength: 100 + minLength: 1 + pattern: ^[a-zA-Z0-9\-_]+$ + type: string + timeout: + description: Timeout Optional timeout configuration for this + upstream (connect timeout). + properties: + connect: + description: Connect Connection-establishment timeout duration + (e.g. "5s", "500ms"). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + upstreams: + description: Upstreams List of backend targets with optional + weights for load balancing. + items: + description: WeightedUpstream is a single backend target within + an UpstreamDefinition. + properties: + url: + description: Url Backend URL (host and port; no path) + type: string + weight: + description: |- + Weight Relative weight for load balancing across multiple upstream targets. Reserved for + future multi-target load balancing; not applied yet (only the first target is currently used). + maximum: 100 + minimum: 0 + type: integer + required: + - url + type: object + minItems: 1 + type: array + required: + - name + - upstreams + type: object + type: array + version: + description: Version is the semantic version of the LLM provider. + pattern: ^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ + type: string + vhost: + description: Vhost is the virtual host for routing. + type: string + required: + - accessControl + - displayName + - template + - upstream + - version + type: object + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_llmprovidertemplates.yaml b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_llmprovidertemplates.yaml index c6fee1cf83..299fa01e0c 100644 --- a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_llmprovidertemplates.yaml +++ b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_llmprovidertemplates.yaml @@ -16,7 +16,7 @@ spec: singular: llmprovidertemplate scope: Namespaced versions: - - name: v1alpha1 + - name: v1 schema: openAPIV3Schema: description: LlmProviderTemplate is the Schema for the llmprovidertemplates @@ -402,3 +402,389 @@ spec: storage: true subresources: status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: LlmProviderTemplate is the Schema for the llmprovidertemplates + API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + LLMProviderTemplateData mirrors the management-API LLMProviderTemplateData + payload. The non-resource extractor fields apply when no resourceMappings + entry matches the request path. + properties: + completionTokens: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + displayName: + description: DisplayName is a human-readable LLM template name. + type: string + promptTokens: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + remainingTokens: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + requestModel: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + resourceMappings: + description: LLMProviderTemplateResourceMappings lists per-resource + extraction mappings. + properties: + resources: + items: + description: |- + LLMProviderTemplateResourceMapping maps a resource path pattern to per-field + extraction identifiers for a given LLM API resource. + properties: + completionTokens: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or + header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + promptTokens: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or + header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + remainingTokens: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or + header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + requestModel: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or + header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + resource: + description: Resource is the resource path pattern this + mapping applies to. + type: string + responseModel: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or + header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + totalTokens: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or + header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + required: + - resource + type: object + type: array + type: object + responseModel: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + totalTokens: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + required: + - displayName + type: object + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_llmproxies.yaml b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_llmproxies.yaml index abb9ccb133..2d01119964 100644 --- a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_llmproxies.yaml +++ b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_llmproxies.yaml @@ -16,7 +16,7 @@ spec: singular: llmproxy scope: Namespaced versions: - - name: v1alpha1 + - name: v1 schema: openAPIV3Schema: description: LlmProxy is the Schema for the llmproxies API. @@ -400,3 +400,387 @@ spec: storage: true subresources: status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: LlmProxy is the Schema for the llmproxies API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec is the LLM proxy configuration payload. + properties: + additionalProviders: + description: |- + AdditionalProviders are extra LLM providers attached as selectable + upstreams for multi-provider routing. + items: + description: |- + LLMProxyAdditionalProvider references an additional LlmProvider that this + proxy can route to by policy-selected upstream name. + properties: + as: + description: As is the logical upstream name used by policies. + Defaults to Id. + type: string + auth: + description: |- + Auth optionally configures credentials for proxy-to-provider loopback + calls when the referenced provider is protected by an auth policy. + properties: + header: + description: |- + Header is the HTTP header to set on outbound requests when the auth + type uses headers (e.g. api-key). + type: string + type: + description: Type identifies the auth scheme. Only api-key + is currently supported. + enum: + - api-key + type: string + value: + description: |- + Value sources the credential. Exactly one of value or valueFrom must + be set. + properties: + value: + description: |- + Value is the inline plaintext value. Avoid for production use; prefer + ValueFrom so the secret is stored in a Kubernetes Secret. + type: string + valueFrom: + description: |- + ValueFrom selects a key from a Kubernetes Secret in the same namespace + as the owning CR. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: exactly one of value or valueFrom must be set + rule: has(self.value) != has(self.valueFrom) + required: + - type + - value + type: object + id: + description: Id is the LlmProvider handle (metadata.name). + type: string + transformer: + description: |- + Transformer optionally applies a request/response translator when this + provider is the selected upstream. The proxy injects it as a conditional + policy that runs only when this provider is selected. + properties: + params: + description: |- + Params carries translator-specific parameters (for example model, + apiVersion). + x-kubernetes-preserve-unknown-fields: true + type: + description: Type is the translator policy name (for example + openai-to-anthropic). + type: string + version: + description: |- + Version is the major-only translator policy version (for example v1). + The Gateway Controller resolves it to the installed full version. + pattern: ^v\d+$ + type: string + required: + - type + - version + type: object + required: + - id + type: object + type: array + context: + description: Context is the base path for routes (must start with + /). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ + type: string + deploymentState: + description: DeploymentState toggles whether the proxy is router-attached. + enum: + - deployed + - undeployed + type: string + displayName: + description: DisplayName is a human-readable LLM proxy name. + type: string + policies: + description: Policies is the list of policies applied to this LLM + proxy. + items: + description: LLMPolicy describes a single LLM-level policy attachment. + properties: + name: + description: Name is the name of the policy. + type: string + paths: + description: Paths lists path/method/params triples for this + policy. + items: + description: |- + LLMPolicyPath defines a path/methods combination together with policy + parameters; mirrors the management-API LLMPolicyPath. + properties: + methods: + description: Methods is the list of HTTP methods. + items: + description: HTTPMethod names an allowed HTTP verb for + LLM access-control and policy paths. + enum: + - GET + - POST + - PUT + - PATCH + - DELETE + - HEAD + - OPTIONS + - '*' + type: string + type: array + params: + description: Params is a free-form parameter object specific + to the policy. + x-kubernetes-preserve-unknown-fields: true + path: + description: Path is the route path pattern. + type: string + required: + - methods + - path + type: object + type: array + version: + description: Version is the policy version (e.g. v1). + pattern: ^v\d+$ + type: string + required: + - name + - paths + - version + type: object + type: array + provider: + description: Provider references the deployed LLM provider this proxy + fronts. + properties: + auth: + description: |- + Auth optionally overrides upstream credentials when calling the + referenced LLM provider. + properties: + header: + description: |- + Header is the HTTP header to set on outbound requests when the auth + type uses headers (e.g. api-key). + type: string + type: + description: Type identifies the auth scheme. Only api-key + is currently supported. + enum: + - api-key + type: string + value: + description: |- + Value sources the credential. Exactly one of value or valueFrom must + be set. + properties: + value: + description: |- + Value is the inline plaintext value. Avoid for production use; prefer + ValueFrom so the secret is stored in a Kubernetes Secret. + type: string + valueFrom: + description: |- + ValueFrom selects a key from a Kubernetes Secret in the same namespace + as the owning CR. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: exactly one of value or valueFrom must be set + rule: has(self.value) != has(self.valueFrom) + required: + - type + - value + type: object + id: + description: Id is the LlmProvider handle (metadata.name). + type: string + required: + - id + type: object + resilience: + description: |- + Resilience configures API-level backend/route timeouts applied to all routes + generated for this LLM proxy. Supported at the API level only. + properties: + idleTimeout: + description: IdleTimeout Per-route stream idle timeout. "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + timeout: + description: Timeout Maximum time for the entire route (request + to upstream response). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + version: + description: Version is the semantic version of the LLM proxy. + pattern: ^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ + type: string + vhost: + description: Vhost is the virtual host for routing. + type: string + required: + - displayName + - provider + - version + type: object + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_managedsecrets.yaml b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_managedsecrets.yaml index 5a430b9c03..9b3510d1ac 100644 --- a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_managedsecrets.yaml +++ b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_managedsecrets.yaml @@ -16,7 +16,7 @@ spec: singular: managedsecret scope: Namespaced versions: - - name: v1alpha1 + - name: v1 schema: openAPIV3Schema: description: |- @@ -184,3 +184,171 @@ spec: storage: true subresources: status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + ManagedSecret represents a platform secret stored by the gateway-controller. + + The CRD is named ManagedSecret (rather than Secret) so it does not collide + with the built-in core/v1 Secret kind. The plural "managedsecrets" is used + in URLs and RBAC to remain unambiguous. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + SecretSpec mirrors the management-API SecretConfigData payload, with the + sensitive Value field expressed as a SecretValueSource so operators can + keep plaintext out of the CR by referencing a Kubernetes Secret. + properties: + description: + description: Description is an optional description of the secret. + type: string + displayName: + description: DisplayName is a human-readable secret name. + type: string + value: + description: Value is the secret plaintext, supplied either inline + or via valueFrom. + properties: + value: + description: |- + Value is the inline plaintext value. Avoid for production use; prefer + ValueFrom so the secret is stored in a Kubernetes Secret. + type: string + valueFrom: + description: |- + ValueFrom selects a key from a Kubernetes Secret in the same namespace + as the owning CR. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: exactly one of value or valueFrom must be set + rule: has(self.value) != has(self.valueFrom) + required: + - displayName + - value + type: object + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_mcps.yaml b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_mcps.yaml index afbeba98d8..922c91fba6 100644 --- a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_mcps.yaml +++ b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_mcps.yaml @@ -16,7 +16,7 @@ spec: singular: mcp scope: Namespaced versions: - - name: v1alpha1 + - name: v1 schema: openAPIV3Schema: description: Mcp is the Schema for the mcps API. @@ -432,3 +432,419 @@ spec: storage: true subresources: status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Mcp is the Schema for the mcps API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec is the MCP proxy configuration. + properties: + context: + description: Context is the base path for routes (must start with + /). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ + type: string + deploymentState: + description: DeploymentState toggles whether the proxy is router-attached. + enum: + - deployed + - undeployed + type: string + displayName: + description: DisplayName is a human-readable MCP proxy name. + type: string + policies: + description: Policies are MCP proxy-level policies. + items: + description: Policy defines a policy attachment as embedded in RestApi + or APIConfigData. + properties: + executionCondition: + description: ExecutionCondition Expression controlling conditional + execution of the policy + type: string + name: + description: Name Name of the policy + type: string + params: + description: Params Arbitrary parameters for the policy (free-form + key/value structure) + x-kubernetes-preserve-unknown-fields: true + version: + description: Version Semantic version of the policy (for example, + v1) + pattern: ^v\d+$ + type: string + required: + - name + - version + type: object + type: array + prompts: + description: Prompts lists optional prompts exposed by this MCP proxy. + items: + description: MCPPrompt mirrors the management-API MCPPrompt schema. + properties: + arguments: + description: Arguments is the optional argument list. + items: + description: MCPPromptArgument describes one input argument + for an MCP prompt. + properties: + description: + description: Description is an optional argument description. + type: string + name: + description: Name is the argument name. + type: string + required: + description: Required marks the argument as mandatory. + type: boolean + title: + description: Title is an optional human-readable label. + type: string + required: + - name + type: object + type: array + description: + description: Description is an optional description. + type: string + name: + description: Name is the unique prompt identifier. + type: string + title: + description: Title is an optional human-readable name. + type: string + required: + - name + type: object + type: array + resilience: + description: |- + Resilience configures API-level backend/route timeouts applied to the traffic-forwarding + routes generated for this MCP proxy. Supported at the API level only. Because MCP transports + are long-lived streams, the route timeout defaults to disabled ("0s") for MCP when unset. + properties: + idleTimeout: + description: IdleTimeout Per-route stream idle timeout. "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + timeout: + description: Timeout Maximum time for the entire route (request + to upstream response). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + resources: + description: Resources lists optional MCP resources exposed by this + proxy. + items: + description: MCPResource mirrors the management-API MCPResource + schema. + properties: + description: + description: Description is an optional description. + type: string + mimeType: + description: MimeType is an optional MIME type. + type: string + name: + description: Name is a human-readable resource name. + type: string + size: + description: Size is the optional size in bytes. + format: int64 + type: integer + title: + description: Title is an optional human-readable label. + type: string + uri: + description: Uri is a unique identifier for the resource. + type: string + required: + - name + - uri + type: object + type: array + specVersion: + description: SpecVersion is the MCP specification version. + type: string + tools: + description: Tools lists optional tools exposed by this MCP proxy. + items: + description: MCPTool mirrors the management-API MCPTool schema. + properties: + description: + description: Description is the human-readable functional description. + type: string + inputSchema: + description: InputSchema is the JSON Schema for input parameters. + type: string + name: + description: Name is the unique tool identifier. + type: string + outputSchema: + description: OutputSchema is the optional JSON Schema for the + output. + type: string + title: + description: Title is an optional human-readable label. + type: string + required: + - description + - inputSchema + - name + type: object + type: array + upstream: + description: Upstream is the MCP backend. + properties: + auth: + description: Auth configures upstream credentials. + properties: + header: + description: Header is the HTTP header to set on outbound + requests. + type: string + type: + description: Type identifies the auth scheme. Only api-key + is currently supported. + enum: + - api-key + type: string + value: + description: Value sources the credential plaintext. + properties: + value: + description: |- + Value is the inline plaintext value. Avoid for production use; prefer + ValueFrom so the secret is stored in a Kubernetes Secret. + type: string + valueFrom: + description: |- + ValueFrom selects a key from a Kubernetes Secret in the same namespace + as the owning CR. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: exactly one of value or valueFrom must be set + rule: has(self.value) != has(self.valueFrom) + required: + - type + - value + type: object + hostRewrite: + description: HostRewrite controls how the Host header is handled. + enum: + - auto + - manual + type: string + ref: + description: Ref is the name of a predefined upstream definition. + type: string + url: + description: Url is the direct backend URL. + type: string + type: object + upstreamDefinitions: + description: |- + UpstreamDefinitions is the list of reusable upstream definitions (with optional + connect timeout) that upstream.ref can reference. + items: + description: |- + UpstreamDefinition is a reusable upstream configuration with an optional connect timeout and + one or more weighted load-balancing targets. Referenced from an upstream via its `ref` field + and by the dynamic-endpoint policy. Shared by RestApi, LLM Provider, and MCP; mirrors the + management-API UpstreamDefinition schema. + properties: + basePath: + description: |- + BasePath Base path prefix prepended to all requests routed through this upstream (e.g. /api/v2). + Must start with "/" and must not end with "/". Omit for root ("/"). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ + type: string + name: + description: |- + Name Unique identifier for this upstream definition (referenced by upstream.ref or the + dynamic-endpoint policy). + maxLength: 100 + minLength: 1 + pattern: ^[a-zA-Z0-9\-_]+$ + type: string + timeout: + description: Timeout Optional timeout configuration for this + upstream (connect timeout). + properties: + connect: + description: Connect Connection-establishment timeout duration + (e.g. "5s", "500ms"). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + upstreams: + description: Upstreams List of backend targets with optional + weights for load balancing. + items: + description: WeightedUpstream is a single backend target within + an UpstreamDefinition. + properties: + url: + description: Url Backend URL (host and port; no path) + type: string + weight: + description: |- + Weight Relative weight for load balancing across multiple upstream targets. Reserved for + future multi-target load balancing; not applied yet (only the first target is currently used). + maximum: 100 + minimum: 0 + type: integer + required: + - url + type: object + minItems: 1 + type: array + required: + - name + - upstreams + type: object + type: array + version: + description: Version is the MCP proxy semantic version. + pattern: ^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ + type: string + vhost: + description: Vhost is the virtual host for routing. + type: string + required: + - displayName + - upstream + - version + type: object + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_restapis.yaml b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_restapis.yaml index e3076e9cc2..5f24ae37a1 100644 --- a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_restapis.yaml +++ b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_restapis.yaml @@ -14,7 +14,7 @@ spec: singular: restapi scope: Namespaced versions: - - name: v1alpha1 + - name: v1 schema: openAPIV3Schema: description: RestApi is the Schema for the restapis API @@ -449,3 +449,438 @@ spec: storage: true subresources: status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: RestApi is the Schema for the restapis API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: APIConfigData defines model for APIConfigData. + properties: + context: + description: Context Base path for all API routes (must start with + /, no trailing slash; "/" denotes the root context) + pattern: ^/([a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/])?$ + type: string + displayName: + description: DisplayName Human-readable API name (must be URL-friendly + - only letters, numbers, spaces, hyphens, underscores, and dots + allowed) + pattern: ^[a-zA-Z0-9\s\-_.]+$ + type: string + operations: + description: Operations List of HTTP operations/routes + items: + description: |- + Operation defines model for Operation. + An operation is matched either by the simple top-level method+path fields or by the richer + Match block (method + path + headers). When Match is set it is authoritative and the + top-level Method/Path are ignored. Exactly one form must be provided. + properties: + match: + description: Match Request matching criteria for the operation. + Extensible with query params, cookies, etc. + properties: + headers: + description: Headers ANDed header matchers applied before + routing to this operation. + items: + description: OperationHeaderMatch mirrors Gateway API + HTTPHeaderMatch for Envoy route selection. + properties: + name: + description: Name Header name (case-insensitive) + type: string + type: + description: Type Match type (Exact or RegularExpression) + enum: + - Exact + - RegularExpression + type: string + value: + description: Value Header value to match + type: string + required: + - name + - value + type: object + type: array + method: + description: Method HTTP method + enum: + - GET + - POST + - PUT + - PATCH + - DELETE + - HEAD + - OPTIONS + type: string + path: + description: Path Path match criteria + properties: + type: + description: Type How the path is matched (Exact or + PathPrefix). Defaults to Exact when omitted. + enum: + - Exact + - PathPrefix + type: string + value: + description: Value Route path with optional {param} + placeholders + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/{}\[\]]*$ + type: string + required: + - value + type: object + required: + - method + - path + type: object + method: + description: Method HTTP method (simple form; ignored when Match + is set). + enum: + - GET + - POST + - PUT + - PATCH + - DELETE + - HEAD + - OPTIONS + type: string + path: + description: Path Route path with optional {param} placeholders + (simple form; ignored when Match is set). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/{}\[\]]*$ + type: string + policies: + description: Policies List of policies applied only to this + operation (overrides or adds to API-level policies) + items: + description: Policy defines a policy attachment as embedded + in RestApi or APIConfigData. + properties: + executionCondition: + description: ExecutionCondition Expression controlling + conditional execution of the policy + type: string + name: + description: Name Name of the policy + type: string + params: + description: Params Arbitrary parameters for the policy + (free-form key/value structure) + x-kubernetes-preserve-unknown-fields: true + version: + description: Version Semantic version of the policy (for + example, v1) + pattern: ^v\d+$ + type: string + required: + - name + - version + type: object + type: array + resilience: + description: Resilience Operation-level backend/route timeout + configuration (overrides API-level) + properties: + idleTimeout: + description: IdleTimeout Per-route stream idle timeout. + "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + timeout: + description: Timeout Maximum time for the entire route (request + to upstream response). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + type: object + x-kubernetes-validations: + - message: operation must set both method and path, or set match + rule: (has(self.method) && has(self.path)) || has(self.match) + minItems: 1 + type: array + policies: + description: Policies List of API-level policies applied to all operations + unless overridden + items: + description: Policy defines a policy attachment as embedded in RestApi + or APIConfigData. + properties: + executionCondition: + description: ExecutionCondition Expression controlling conditional + execution of the policy + type: string + name: + description: Name Name of the policy + type: string + params: + description: Params Arbitrary parameters for the policy (free-form + key/value structure) + x-kubernetes-preserve-unknown-fields: true + version: + description: Version Semantic version of the policy (for example, + v1) + pattern: ^v\d+$ + type: string + required: + - name + - version + type: object + type: array + resilience: + description: |- + Resilience API-level backend/route timeout configuration applied to all operations + unless overridden at the operation level + properties: + idleTimeout: + description: IdleTimeout Per-route stream idle timeout. "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + timeout: + description: Timeout Maximum time for the entire route (request + to upstream response). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + upstream: + description: Upstream API-level upstream configuration + properties: + main: + description: Main Upstream backend configuration for production + traffic + properties: + hostRewrite: + description: |- + HostRewrite controls how the Host header is handled when routing to the upstream. + "auto" lets Envoy rewrite the Host header to the upstream cluster host; "manual" + disables automatic rewriting so the incoming Host header is preserved. When unset, + the gateway-controller defaults to "auto". + enum: + - auto + - manual + type: string + ref: + description: Ref Name of a predefined upstreamDefinition to + route through. + type: string + url: + description: Url Direct backend service URL (may include path + prefix like /api/v2) + pattern: ^https?://[a-zA-Z0-9\-._~:/?#\[\]@!$&'()*+,;=%]+$ + type: string + type: object + x-kubernetes-validations: + - message: exactly one of url or ref must be set + rule: has(self.url) != has(self.ref) + sandbox: + description: Sandbox Upstream backend configuration for sandbox/testing + traffic + properties: + hostRewrite: + description: |- + HostRewrite controls how the Host header is handled when routing to the upstream. + "auto" lets Envoy rewrite the Host header to the upstream cluster host; "manual" + disables automatic rewriting so the incoming Host header is preserved. When unset, + the gateway-controller defaults to "auto". + enum: + - auto + - manual + type: string + ref: + description: Ref Name of a predefined upstreamDefinition to + route through. + type: string + url: + description: Url Direct backend service URL (may include path + prefix like /api/v2) + pattern: ^https?://[a-zA-Z0-9\-._~:/?#\[\]@!$&'()*+,;=%]+$ + type: string + type: object + x-kubernetes-validations: + - message: exactly one of url or ref must be set + rule: has(self.url) != has(self.ref) + required: + - main + type: object + upstreamDefinitions: + description: |- + UpstreamDefinitions is the list of reusable upstream definitions (with optional connect + timeout and weighted load-balancing targets) that upstream.ref and the dynamic-endpoint + policy can reference. + items: + description: |- + UpstreamDefinition is a reusable upstream configuration with an optional connect timeout and + one or more weighted load-balancing targets. Referenced from an upstream via its `ref` field + and by the dynamic-endpoint policy. Shared by RestApi, LLM Provider, and MCP; mirrors the + management-API UpstreamDefinition schema. + properties: + basePath: + description: |- + BasePath Base path prefix prepended to all requests routed through this upstream (e.g. /api/v2). + Must start with "/" and must not end with "/". Omit for root ("/"). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ + type: string + name: + description: |- + Name Unique identifier for this upstream definition (referenced by upstream.ref or the + dynamic-endpoint policy). + maxLength: 100 + minLength: 1 + pattern: ^[a-zA-Z0-9\-_]+$ + type: string + timeout: + description: Timeout Optional timeout configuration for this + upstream (connect timeout). + properties: + connect: + description: Connect Connection-establishment timeout duration + (e.g. "5s", "500ms"). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + upstreams: + description: Upstreams List of backend targets with optional + weights for load balancing. + items: + description: WeightedUpstream is a single backend target within + an UpstreamDefinition. + properties: + url: + description: Url Backend URL (host and port; no path) + type: string + weight: + description: |- + Weight Relative weight for load balancing across multiple upstream targets. Reserved for + future multi-target load balancing; not applied yet (only the first target is currently used). + maximum: 100 + minimum: 0 + type: integer + required: + - url + type: object + minItems: 1 + type: array + required: + - name + - upstreams + type: object + type: array + version: + description: Version Semantic version of the API + pattern: ^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ + type: string + vhosts: + description: Vhosts Custom virtual hosts/domains for the API + properties: + main: + description: |- + Main Custom virtual host(s)/domain(s) for production traffic. One or more hostnames separated + by ";" — each serves the main upstream (e.g. when an HTTPRoute attaches to multiple listeners + with distinct hostnames). The first entry is the primary vhost. + type: string + sandbox: + description: Sandbox Custom virtual host/domain for sandbox traffic + type: string + required: + - main + type: object + required: + - context + - displayName + - operations + - upstream + - version + type: object + status: + description: RestApiStatus defines the observed state of RestApi + properties: + conditions: + description: Conditions represent the latest available observations + of the API's state + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated + format: date-time + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_subscriptionplans.yaml b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_subscriptionplans.yaml index b09213cfd6..00ecadf155 100644 --- a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_subscriptionplans.yaml +++ b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_subscriptionplans.yaml @@ -23,7 +23,7 @@ spec: - jsonPath: .spec.planName name: Plan type: string - name: v1alpha1 + name: v1 schema: openAPIV3Schema: description: SubscriptionPlan is the Schema for the subscriptionplans API. @@ -177,3 +177,164 @@ spec: storage: true subresources: status: {} + - additionalPrinterColumns: + - jsonPath: .status.id + name: Id + type: string + - jsonPath: .spec.planName + name: Plan + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: SubscriptionPlan is the Schema for the subscriptionplans API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + SubscriptionPlanSpec mirrors the management-API SubscriptionPlanCreateRequest + payload. The gateway-controller assigns a UUID id on first POST; the + controller persists it to .status.id and uses it for subsequent + PUT/DELETE. + properties: + billingPlan: + description: BillingPlan is an optional billing plan identifier. + type: string + expiryTime: + description: ExpiryTime is the optional plan expiry. + format: date-time + type: string + planName: + description: PlanName is the human-readable plan name. + type: string + status: + description: |- + Status is the lifecycle state for this plan (active/inactive/etc). + Mirrors the management-API SubscriptionPlanCreateRequest.Status enum. + enum: + - ACTIVE + - INACTIVE + type: string + stopOnQuotaReach: + description: |- + StopOnQuotaReach controls whether traffic is blocked when the quota + is exhausted. + type: boolean + throttleLimitCount: + description: ThrottleLimitCount is the request count limit. + format: int64 + minimum: 0 + type: integer + throttleLimitUnit: + description: ThrottleLimitUnit is the time unit for the throttle window. + enum: + - Day + - Hour + - Min + - Month + type: string + required: + - planName + type: object + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_subscriptions.yaml b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_subscriptions.yaml index 27cf4f12b9..3746967daf 100644 --- a/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_subscriptions.yaml +++ b/kubernetes/gateway-operator/config/crd/bases/gateway.api-platform.wso2.com_subscriptions.yaml @@ -23,7 +23,7 @@ spec: - jsonPath: .spec.apiId name: ApiId type: string - name: v1alpha1 + name: v1 schema: openAPIV3Schema: description: Subscription is the Schema for the subscriptions API. @@ -208,3 +208,195 @@ spec: storage: true subresources: status: {} + - additionalPrinterColumns: + - jsonPath: .status.id + name: Id + type: string + - jsonPath: .spec.apiId + name: ApiId + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: Subscription is the Schema for the subscriptions API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + SubscriptionSpec mirrors the management-API SubscriptionCreateRequest + payload. The gateway-controller issues a UUID id which the controller + persists to .status.id for subsequent PUT/DELETE. + properties: + apiId: + description: ApiId is the API identifier (deployment id or handle). + type: string + applicationId: + description: ApplicationId is an optional application identifier. + type: string + billingCustomerId: + description: BillingCustomerId is an optional billing customer identifier. + type: string + billingSubscriptionId: + description: BillingSubscriptionId is an optional billing subscription + identifier. + type: string + status: + description: |- + Status is the lifecycle state for this subscription. Mirrors the + management-API SubscriptionCreateRequest.Status enum. + type: string + subscriptionPlanId: + description: |- + SubscriptionPlanId is an optional plan UUID. When the plan is also + managed via SubscriptionPlan CR, set this to the SubscriptionPlan's + .status.id once it has been deployed. + type: string + subscriptionToken: + description: |- + SubscriptionToken is the opaque token used to invoke the API. The + token is sent as plaintext to the gateway which stores only its hash; + inline in the CR or supplied via valueFrom. + properties: + value: + description: |- + Value is the inline plaintext value. Avoid for production use; prefer + ValueFrom so the secret is stored in a Kubernetes Secret. + type: string + valueFrom: + description: |- + ValueFrom selects a key from a Kubernetes Secret in the same namespace + as the owning CR. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: exactly one of value or valueFrom must be set + rule: has(self.value) != has(self.valueFrom) + required: + - apiId + - subscriptionToken + type: object + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/gateway-operator/internal/auth/auth_helper.go b/kubernetes/gateway-operator/internal/auth/auth_helper.go index fdb8e4f9aa..2536c0b65b 100644 --- a/kubernetes/gateway-operator/internal/auth/auth_helper.go +++ b/kubernetes/gateway-operator/internal/auth/auth_helper.go @@ -27,7 +27,7 @@ import ( corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/registry" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/types" diff --git a/kubernetes/gateway-operator/internal/controller/apigateway_controller.go b/kubernetes/gateway-operator/internal/controller/apigateway_controller.go index 3ae29eb9b4..749a456c21 100644 --- a/kubernetes/gateway-operator/internal/controller/apigateway_controller.go +++ b/kubernetes/gateway-operator/internal/controller/apigateway_controller.go @@ -45,7 +45,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/auth" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/config" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/helm" diff --git a/kubernetes/gateway-operator/internal/controller/apikey_controller.go b/kubernetes/gateway-operator/internal/controller/apikey_controller.go index 26845843b4..9b78e6c17d 100644 --- a/kubernetes/gateway-operator/internal/controller/apikey_controller.go +++ b/kubernetes/gateway-operator/internal/controller/apikey_controller.go @@ -31,7 +31,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/config" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/gatewayclient" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/secretsource" diff --git a/kubernetes/gateway-operator/internal/controller/apikey_external_deps_test.go b/kubernetes/gateway-operator/internal/controller/apikey_external_deps_test.go index e330654a3e..e3e4d6edcf 100644 --- a/kubernetes/gateway-operator/internal/controller/apikey_external_deps_test.go +++ b/kubernetes/gateway-operator/internal/controller/apikey_external_deps_test.go @@ -26,7 +26,7 @@ import ( clientgoscheme "k8s.io/client-go/kubernetes/scheme" "sigs.k8s.io/controller-runtime/pkg/client/fake" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/stretchr/testify/require" ) diff --git a/kubernetes/gateway-operator/internal/controller/certificate_controller.go b/kubernetes/gateway-operator/internal/controller/certificate_controller.go index 1712ddb53c..a61d5aa871 100644 --- a/kubernetes/gateway-operator/internal/controller/certificate_controller.go +++ b/kubernetes/gateway-operator/internal/controller/certificate_controller.go @@ -26,7 +26,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/config" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/gatewayclient" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/secretsource" diff --git a/kubernetes/gateway-operator/internal/controller/gateway_infra.go b/kubernetes/gateway-operator/internal/controller/gateway_infra.go index 6061f5ea5e..29d1764cff 100644 --- a/kubernetes/gateway-operator/internal/controller/gateway_infra.go +++ b/kubernetes/gateway-operator/internal/controller/gateway_infra.go @@ -26,7 +26,7 @@ import ( corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/helm" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/registry" ) diff --git a/kubernetes/gateway-operator/internal/controller/generic_reconciler.go b/kubernetes/gateway-operator/internal/controller/generic_reconciler.go index 1c81bd9993..bf4af0a87c 100644 --- a/kubernetes/gateway-operator/internal/controller/generic_reconciler.go +++ b/kubernetes/gateway-operator/internal/controller/generic_reconciler.go @@ -34,7 +34,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/auth" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/config" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/gatewayclient" diff --git a/kubernetes/gateway-operator/internal/controller/httproute_compile.go b/kubernetes/gateway-operator/internal/controller/httproute_compile.go index 3f6e531eec..979a964844 100644 --- a/kubernetes/gateway-operator/internal/controller/httproute_compile.go +++ b/kubernetes/gateway-operator/internal/controller/httproute_compile.go @@ -27,7 +27,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" ) // BuildAPIConfigFromHTTPRoute compiles an HTTPRoute into APIConfigData for gateway-controller deployment. diff --git a/kubernetes/gateway-operator/internal/controller/httproute_confighash_stability_test.go b/kubernetes/gateway-operator/internal/controller/httproute_confighash_stability_test.go index dd4c08dbe6..3db1a39c57 100644 --- a/kubernetes/gateway-operator/internal/controller/httproute_confighash_stability_test.go +++ b/kubernetes/gateway-operator/internal/controller/httproute_confighash_stability_test.go @@ -27,7 +27,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/gatewayclient" ) diff --git a/kubernetes/gateway-operator/internal/controller/httproute_controller.go b/kubernetes/gateway-operator/internal/controller/httproute_controller.go index 3c3423abfc..f03778be45 100644 --- a/kubernetes/gateway-operator/internal/controller/httproute_controller.go +++ b/kubernetes/gateway-operator/internal/controller/httproute_controller.go @@ -41,7 +41,7 @@ import ( gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/auth" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/config" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/gatewayclient" diff --git a/kubernetes/gateway-operator/internal/controller/httproute_direct_response_policy.go b/kubernetes/gateway-operator/internal/controller/httproute_direct_response_policy.go index 002cec3427..0d61b25ad8 100644 --- a/kubernetes/gateway-operator/internal/controller/httproute_direct_response_policy.go +++ b/kubernetes/gateway-operator/internal/controller/httproute_direct_response_policy.go @@ -18,7 +18,7 @@ package controller import ( - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" ) // This file maps a gateway-terminated immediate response (a rule with no/failed backends) diff --git a/kubernetes/gateway-operator/internal/controller/httproute_direct_response_policy_test.go b/kubernetes/gateway-operator/internal/controller/httproute_direct_response_policy_test.go index ed97b0b48e..80b6561948 100644 --- a/kubernetes/gateway-operator/internal/controller/httproute_direct_response_policy_test.go +++ b/kubernetes/gateway-operator/internal/controller/httproute_direct_response_policy_test.go @@ -27,7 +27,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" ) type respondParams struct { diff --git a/kubernetes/gateway-operator/internal/controller/httproute_enqueue.go b/kubernetes/gateway-operator/internal/controller/httproute_enqueue.go index f9af02dc1b..eae04ffa8a 100644 --- a/kubernetes/gateway-operator/internal/controller/httproute_enqueue.go +++ b/kubernetes/gateway-operator/internal/controller/httproute_enqueue.go @@ -22,7 +22,7 @@ import ( "encoding/json" "strings" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "go.uber.org/zap" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" diff --git a/kubernetes/gateway-operator/internal/controller/httproute_enqueue_test.go b/kubernetes/gateway-operator/internal/controller/httproute_enqueue_test.go index f2a5b4d6ed..dc5150f35b 100644 --- a/kubernetes/gateway-operator/internal/controller/httproute_enqueue_test.go +++ b/kubernetes/gateway-operator/internal/controller/httproute_enqueue_test.go @@ -23,7 +23,7 @@ import ( "testing" "github.com/stretchr/testify/require" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" diff --git a/kubernetes/gateway-operator/internal/controller/httproute_filters.go b/kubernetes/gateway-operator/internal/controller/httproute_filters.go index 59bff2aff6..d0a282408f 100644 --- a/kubernetes/gateway-operator/internal/controller/httproute_filters.go +++ b/kubernetes/gateway-operator/internal/controller/httproute_filters.go @@ -25,7 +25,7 @@ import ( "k8s.io/apimachinery/pkg/runtime" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" ) // dynamicEndpointPolicyName is the name of the dynamic-endpoint routing policy. diff --git a/kubernetes/gateway-operator/internal/controller/httproute_mapper.go b/kubernetes/gateway-operator/internal/controller/httproute_mapper.go index d9623ebf8b..c54fc0c32c 100644 --- a/kubernetes/gateway-operator/internal/controller/httproute_mapper.go +++ b/kubernetes/gateway-operator/internal/controller/httproute_mapper.go @@ -27,7 +27,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" ) const defaultKubernetesClusterDNS = "cluster.local" diff --git a/kubernetes/gateway-operator/internal/controller/httproute_mapper_test.go b/kubernetes/gateway-operator/internal/controller/httproute_mapper_test.go index 0c13e424b9..ee8713bd72 100644 --- a/kubernetes/gateway-operator/internal/controller/httproute_mapper_test.go +++ b/kubernetes/gateway-operator/internal/controller/httproute_mapper_test.go @@ -23,7 +23,7 @@ import ( "testing" "github.com/stretchr/testify/require" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" diff --git a/kubernetes/gateway-operator/internal/controller/httproute_match_emit_test.go b/kubernetes/gateway-operator/internal/controller/httproute_match_emit_test.go index 3599f00d05..3912c0d57d 100644 --- a/kubernetes/gateway-operator/internal/controller/httproute_match_emit_test.go +++ b/kubernetes/gateway-operator/internal/controller/httproute_match_emit_test.go @@ -28,7 +28,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" ) // TestBuildAPIConfigFromHTTPRoute_EmitsMatchForm verifies the operator compiles a Gateway-API diff --git a/kubernetes/gateway-operator/internal/controller/httproute_policies.go b/kubernetes/gateway-operator/internal/controller/httproute_policies.go index f6a99b48b2..ced24ce5b6 100644 --- a/kubernetes/gateway-operator/internal/controller/httproute_policies.go +++ b/kubernetes/gateway-operator/internal/controller/httproute_policies.go @@ -33,7 +33,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" ) // policyVersionPattern matches APIPolicy / RestApi policy version (e.g. v1), aligned with CRD schema pattern ^v\d+$. diff --git a/kubernetes/gateway-operator/internal/controller/httproute_policy_params_resolve.go b/kubernetes/gateway-operator/internal/controller/httproute_policy_params_resolve.go index 6e1c7581ee..574f0d8e5b 100644 --- a/kubernetes/gateway-operator/internal/controller/httproute_policy_params_resolve.go +++ b/kubernetes/gateway-operator/internal/controller/httproute_policy_params_resolve.go @@ -29,7 +29,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" ) // Reserved keys for the k8s-native valueFrom shape used inside policy params: diff --git a/kubernetes/gateway-operator/internal/controller/httproute_policy_params_resolve_test.go b/kubernetes/gateway-operator/internal/controller/httproute_policy_params_resolve_test.go index 611efd5d97..59271ae26e 100644 --- a/kubernetes/gateway-operator/internal/controller/httproute_policy_params_resolve_test.go +++ b/kubernetes/gateway-operator/internal/controller/httproute_policy_params_resolve_test.go @@ -30,7 +30,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" ) func resolverTestScheme(t *testing.T) *runtime.Scheme { diff --git a/kubernetes/gateway-operator/internal/controller/httproute_redirect_policy.go b/kubernetes/gateway-operator/internal/controller/httproute_redirect_policy.go index dade8a9ef8..4e759610ac 100644 --- a/kubernetes/gateway-operator/internal/controller/httproute_redirect_policy.go +++ b/kubernetes/gateway-operator/internal/controller/httproute_redirect_policy.go @@ -20,7 +20,7 @@ package controller import ( gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" ) // This file maps a Gateway-API RequestRedirect filter into the redirect policy. It is diff --git a/kubernetes/gateway-operator/internal/controller/httproute_redirect_policy_test.go b/kubernetes/gateway-operator/internal/controller/httproute_redirect_policy_test.go index db44e46361..8e9141cd22 100644 --- a/kubernetes/gateway-operator/internal/controller/httproute_redirect_policy_test.go +++ b/kubernetes/gateway-operator/internal/controller/httproute_redirect_policy_test.go @@ -31,7 +31,7 @@ import ( gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" ) type redirectParams struct { diff --git a/kubernetes/gateway-operator/internal/controller/k8s_gateway_controller.go b/kubernetes/gateway-operator/internal/controller/k8s_gateway_controller.go index 4b2948d4ae..b2996ec40b 100644 --- a/kubernetes/gateway-operator/internal/controller/k8s_gateway_controller.go +++ b/kubernetes/gateway-operator/internal/controller/k8s_gateway_controller.go @@ -46,7 +46,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/config" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/helm" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/helmgateway" diff --git a/kubernetes/gateway-operator/internal/controller/llmprovider_controller.go b/kubernetes/gateway-operator/internal/controller/llmprovider_controller.go index 933022b66b..c7807b4810 100644 --- a/kubernetes/gateway-operator/internal/controller/llmprovider_controller.go +++ b/kubernetes/gateway-operator/internal/controller/llmprovider_controller.go @@ -30,7 +30,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/config" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/gatewayclient" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/secretsource" diff --git a/kubernetes/gateway-operator/internal/controller/llmprovidertemplate_controller.go b/kubernetes/gateway-operator/internal/controller/llmprovidertemplate_controller.go index 9296bfbd52..b0bc93ffaf 100644 --- a/kubernetes/gateway-operator/internal/controller/llmprovidertemplate_controller.go +++ b/kubernetes/gateway-operator/internal/controller/llmprovidertemplate_controller.go @@ -27,7 +27,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/config" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/gatewayclient" ) diff --git a/kubernetes/gateway-operator/internal/controller/llmproxy_controller.go b/kubernetes/gateway-operator/internal/controller/llmproxy_controller.go index 99eb1f24bb..a217401727 100644 --- a/kubernetes/gateway-operator/internal/controller/llmproxy_controller.go +++ b/kubernetes/gateway-operator/internal/controller/llmproxy_controller.go @@ -30,7 +30,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/config" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/gatewayclient" ) diff --git a/kubernetes/gateway-operator/internal/controller/llmproxy_controller_test.go b/kubernetes/gateway-operator/internal/controller/llmproxy_controller_test.go index f6cec1c13c..6dfacd8cec 100644 --- a/kubernetes/gateway-operator/internal/controller/llmproxy_controller_test.go +++ b/kubernetes/gateway-operator/internal/controller/llmproxy_controller_test.go @@ -11,7 +11,7 @@ import ( "testing" "github.com/stretchr/testify/require" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" diff --git a/kubernetes/gateway-operator/internal/controller/managedsecret_controller.go b/kubernetes/gateway-operator/internal/controller/managedsecret_controller.go index adc5b02efd..7f0c9809fe 100644 --- a/kubernetes/gateway-operator/internal/controller/managedsecret_controller.go +++ b/kubernetes/gateway-operator/internal/controller/managedsecret_controller.go @@ -27,7 +27,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/config" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/gatewayclient" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/secretsource" diff --git a/kubernetes/gateway-operator/internal/controller/management_llm_enqueue.go b/kubernetes/gateway-operator/internal/controller/management_llm_enqueue.go index 966f9b1fd6..e7bd303dc2 100644 --- a/kubernetes/gateway-operator/internal/controller/management_llm_enqueue.go +++ b/kubernetes/gateway-operator/internal/controller/management_llm_enqueue.go @@ -23,7 +23,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" ) // enqueueLlmProvidersReferencingTemplate returns a mapper that enqueues every diff --git a/kubernetes/gateway-operator/internal/controller/management_resources_helpers.go b/kubernetes/gateway-operator/internal/controller/management_resources_helpers.go index 55fc668013..d950dd8aad 100644 --- a/kubernetes/gateway-operator/internal/controller/management_resources_helpers.go +++ b/kubernetes/gateway-operator/internal/controller/management_resources_helpers.go @@ -29,7 +29,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/reconcile" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/gatewayclient" ) diff --git a/kubernetes/gateway-operator/internal/controller/management_upstream_auth_payload_test.go b/kubernetes/gateway-operator/internal/controller/management_upstream_auth_payload_test.go index 476f8edcfd..0ba9193333 100644 --- a/kubernetes/gateway-operator/internal/controller/management_upstream_auth_payload_test.go +++ b/kubernetes/gateway-operator/internal/controller/management_upstream_auth_payload_test.go @@ -3,7 +3,7 @@ package controller import ( "testing" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" ) func TestFlattenUpstreamAuthCredentialValue_nestedValueBecomesPlainString(t *testing.T) { diff --git a/kubernetes/gateway-operator/internal/controller/management_valuefrom_enqueue.go b/kubernetes/gateway-operator/internal/controller/management_valuefrom_enqueue.go index 7760063f47..da1a360f23 100644 --- a/kubernetes/gateway-operator/internal/controller/management_valuefrom_enqueue.go +++ b/kubernetes/gateway-operator/internal/controller/management_valuefrom_enqueue.go @@ -21,7 +21,7 @@ import ( "encoding/json" "strings" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" diff --git a/kubernetes/gateway-operator/internal/controller/management_valuefrom_fingerprint.go b/kubernetes/gateway-operator/internal/controller/management_valuefrom_fingerprint.go index 16bd4a42dd..c72bad82f5 100644 --- a/kubernetes/gateway-operator/internal/controller/management_valuefrom_fingerprint.go +++ b/kubernetes/gateway-operator/internal/controller/management_valuefrom_fingerprint.go @@ -23,7 +23,7 @@ import ( "sort" "strings" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client" ) diff --git a/kubernetes/gateway-operator/internal/controller/management_valuefrom_fingerprint_test.go b/kubernetes/gateway-operator/internal/controller/management_valuefrom_fingerprint_test.go index e94bd8bdc9..c7b6cfe4bf 100644 --- a/kubernetes/gateway-operator/internal/controller/management_valuefrom_fingerprint_test.go +++ b/kubernetes/gateway-operator/internal/controller/management_valuefrom_fingerprint_test.go @@ -6,7 +6,7 @@ import ( "testing" "github.com/stretchr/testify/require" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" diff --git a/kubernetes/gateway-operator/internal/controller/mcp_controller.go b/kubernetes/gateway-operator/internal/controller/mcp_controller.go index 301cf21a75..e1a8594647 100644 --- a/kubernetes/gateway-operator/internal/controller/mcp_controller.go +++ b/kubernetes/gateway-operator/internal/controller/mcp_controller.go @@ -30,7 +30,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/config" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/gatewayclient" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/secretsource" diff --git a/kubernetes/gateway-operator/internal/controller/payload_metadata_test.go b/kubernetes/gateway-operator/internal/controller/payload_metadata_test.go index 3cafbc9cbe..3fe23a8a18 100644 --- a/kubernetes/gateway-operator/internal/controller/payload_metadata_test.go +++ b/kubernetes/gateway-operator/internal/controller/payload_metadata_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/stretchr/testify/require" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" ) diff --git a/kubernetes/gateway-operator/internal/controller/restapi_controller.go b/kubernetes/gateway-operator/internal/controller/restapi_controller.go index 03dcb7c8ba..651bf0bc24 100644 --- a/kubernetes/gateway-operator/internal/controller/restapi_controller.go +++ b/kubernetes/gateway-operator/internal/controller/restapi_controller.go @@ -24,7 +24,7 @@ import ( "sync" "time" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/auth" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/config" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/gatewayclient" diff --git a/kubernetes/gateway-operator/internal/controller/restapi_enqueue.go b/kubernetes/gateway-operator/internal/controller/restapi_enqueue.go index fddc6d82ef..b1cb2b3808 100644 --- a/kubernetes/gateway-operator/internal/controller/restapi_enqueue.go +++ b/kubernetes/gateway-operator/internal/controller/restapi_enqueue.go @@ -20,7 +20,7 @@ import ( "context" "encoding/json" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "go.uber.org/zap" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" diff --git a/kubernetes/gateway-operator/internal/controller/restapi_enqueue_test.go b/kubernetes/gateway-operator/internal/controller/restapi_enqueue_test.go index f77a2925b7..c45bbd65d5 100644 --- a/kubernetes/gateway-operator/internal/controller/restapi_enqueue_test.go +++ b/kubernetes/gateway-operator/internal/controller/restapi_enqueue_test.go @@ -22,7 +22,7 @@ import ( "testing" "github.com/stretchr/testify/require" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" diff --git a/kubernetes/gateway-operator/internal/controller/restapi_policy_valuefrom.go b/kubernetes/gateway-operator/internal/controller/restapi_policy_valuefrom.go index 5f69289c57..016212e9c0 100644 --- a/kubernetes/gateway-operator/internal/controller/restapi_policy_valuefrom.go +++ b/kubernetes/gateway-operator/internal/controller/restapi_policy_valuefrom.go @@ -23,7 +23,7 @@ import ( "sort" "strings" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/meta" diff --git a/kubernetes/gateway-operator/internal/controller/restapi_policy_valuefrom_test.go b/kubernetes/gateway-operator/internal/controller/restapi_policy_valuefrom_test.go index 543eeb895b..66e65e62c9 100644 --- a/kubernetes/gateway-operator/internal/controller/restapi_policy_valuefrom_test.go +++ b/kubernetes/gateway-operator/internal/controller/restapi_policy_valuefrom_test.go @@ -22,7 +22,7 @@ import ( "testing" "github.com/stretchr/testify/require" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" diff --git a/kubernetes/gateway-operator/internal/controller/serialization_test.go b/kubernetes/gateway-operator/internal/controller/serialization_test.go index b55ad07b80..38e4b198e8 100644 --- a/kubernetes/gateway-operator/internal/controller/serialization_test.go +++ b/kubernetes/gateway-operator/internal/controller/serialization_test.go @@ -5,7 +5,7 @@ import ( "testing" "github.com/stretchr/testify/assert" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "gopkg.in/yaml.v2" "k8s.io/apimachinery/pkg/runtime" ) diff --git a/kubernetes/gateway-operator/internal/controller/subscription_controller.go b/kubernetes/gateway-operator/internal/controller/subscription_controller.go index 1f051e8d02..5cb19b0efa 100644 --- a/kubernetes/gateway-operator/internal/controller/subscription_controller.go +++ b/kubernetes/gateway-operator/internal/controller/subscription_controller.go @@ -36,7 +36,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/reconcile" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/config" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/gatewayclient" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/secretsource" diff --git a/kubernetes/gateway-operator/internal/controller/subscription_external_deps_test.go b/kubernetes/gateway-operator/internal/controller/subscription_external_deps_test.go index f7cfec3447..e558b2be7d 100644 --- a/kubernetes/gateway-operator/internal/controller/subscription_external_deps_test.go +++ b/kubernetes/gateway-operator/internal/controller/subscription_external_deps_test.go @@ -26,7 +26,7 @@ import ( clientgoscheme "k8s.io/client-go/kubernetes/scheme" "sigs.k8s.io/controller-runtime/pkg/client/fake" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/stretchr/testify/require" ) diff --git a/kubernetes/gateway-operator/internal/controller/subscriptionplan_controller.go b/kubernetes/gateway-operator/internal/controller/subscriptionplan_controller.go index 3979c347ca..bd62d2e780 100644 --- a/kubernetes/gateway-operator/internal/controller/subscriptionplan_controller.go +++ b/kubernetes/gateway-operator/internal/controller/subscriptionplan_controller.go @@ -27,7 +27,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/handler" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/config" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/gatewayclient" ) diff --git a/kubernetes/gateway-operator/internal/gatewayclient/envelope_payload_test.go b/kubernetes/gateway-operator/internal/gatewayclient/envelope_payload_test.go index 7cf9ecfbee..fa7ce58210 100644 --- a/kubernetes/gateway-operator/internal/gatewayclient/envelope_payload_test.go +++ b/kubernetes/gateway-operator/internal/gatewayclient/envelope_payload_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/stretchr/testify/require" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" yamlv3 "gopkg.in/yaml.v3" ) diff --git a/kubernetes/gateway-operator/internal/gatewayclient/rest_api.go b/kubernetes/gateway-operator/internal/gatewayclient/rest_api.go index bb43f1b0b1..a26ab27dac 100644 --- a/kubernetes/gateway-operator/internal/gatewayclient/rest_api.go +++ b/kubernetes/gateway-operator/internal/gatewayclient/rest_api.go @@ -39,7 +39,7 @@ const ( // ManagementArtifactAPIVersion is the apiVersion stamped on all artifact // payloads sent to the gateway-controller management API. This is the // management API artifact version, which is independent of the Kubernetes - // CRD storage version (gateway.api-platform.wso2.com/v1alpha1). + // CRD versions (the CRDs serve v1alpha1 and v1, with v1 as storage). ManagementArtifactAPIVersion = "gateway.api-platform.wso2.com/v1" restAPIsResourcePath = ManagementAPIBasePath + "/rest-apis" diff --git a/kubernetes/gateway-operator/internal/gatewayclient/yaml_payload.go b/kubernetes/gateway-operator/internal/gatewayclient/yaml_payload.go index bdb81b1923..16c7891d51 100644 --- a/kubernetes/gateway-operator/internal/gatewayclient/yaml_payload.go +++ b/kubernetes/gateway-operator/internal/gatewayclient/yaml_payload.go @@ -21,7 +21,7 @@ import ( "encoding/json" "fmt" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "gopkg.in/yaml.v2" ) diff --git a/kubernetes/gateway-operator/internal/gatewayclient/yaml_payload_test.go b/kubernetes/gateway-operator/internal/gatewayclient/yaml_payload_test.go index f7bbd56324..c70360d31a 100644 --- a/kubernetes/gateway-operator/internal/gatewayclient/yaml_payload_test.go +++ b/kubernetes/gateway-operator/internal/gatewayclient/yaml_payload_test.go @@ -4,7 +4,7 @@ import ( "testing" "github.com/stretchr/testify/require" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" yamlv3 "gopkg.in/yaml.v3" "k8s.io/apimachinery/pkg/runtime" ) diff --git a/kubernetes/gateway-operator/internal/k8sutil/examples/template_usage.go b/kubernetes/gateway-operator/internal/k8sutil/examples/template_usage.go index c814a05ac9..94cc67c8ea 100644 --- a/kubernetes/gateway-operator/internal/k8sutil/examples/template_usage.go +++ b/kubernetes/gateway-operator/internal/k8sutil/examples/template_usage.go @@ -19,7 +19,7 @@ package examples import ( "context" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" "github.com/wso2/api-platform/kubernetes/gateway-operator/internal/k8sutil" "k8s.io/apimachinery/pkg/runtime" "sigs.k8s.io/controller-runtime/pkg/client" diff --git a/kubernetes/gateway-operator/internal/registry/gateway_registry.go b/kubernetes/gateway-operator/internal/registry/gateway_registry.go index 037a7ac4bc..b77d7b4ebb 100644 --- a/kubernetes/gateway-operator/internal/registry/gateway_registry.go +++ b/kubernetes/gateway-operator/internal/registry/gateway_registry.go @@ -20,7 +20,7 @@ import ( "fmt" "sync" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) diff --git a/kubernetes/gateway-operator/internal/secretsource/resolver.go b/kubernetes/gateway-operator/internal/secretsource/resolver.go index d2bb480eba..86a74817a6 100644 --- a/kubernetes/gateway-operator/internal/secretsource/resolver.go +++ b/kubernetes/gateway-operator/internal/secretsource/resolver.go @@ -29,7 +29,7 @@ import ( "k8s.io/apimachinery/pkg/types" "sigs.k8s.io/controller-runtime/pkg/client" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" ) // ErrNotConfigured indicates that neither value nor valueFrom is set. diff --git a/kubernetes/gateway-operator/internal/secretsource/resolver_test.go b/kubernetes/gateway-operator/internal/secretsource/resolver_test.go index 1356f55c8a..50203cc58f 100644 --- a/kubernetes/gateway-operator/internal/secretsource/resolver_test.go +++ b/kubernetes/gateway-operator/internal/secretsource/resolver_test.go @@ -12,7 +12,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client/fake" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" ) func newClient(t *testing.T, secrets ...*corev1.Secret) (cl client.Client) { diff --git a/kubernetes/gateway-operator/internal/selector/api_selector.go b/kubernetes/gateway-operator/internal/selector/api_selector.go index 0c5fa7bc62..97444b5675 100644 --- a/kubernetes/gateway-operator/internal/selector/api_selector.go +++ b/kubernetes/gateway-operator/internal/selector/api_selector.go @@ -19,7 +19,7 @@ package selector import ( "context" - apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1alpha1" + apiv1 "github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/selection" diff --git a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_apigateways.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_apigateways.yaml deleted file mode 100644 index 97d6234633..0000000000 --- a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_apigateways.yaml +++ /dev/null @@ -1,1386 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.5 - name: apigateways.gateway.api-platform.wso2.com -spec: - group: gateway.api-platform.wso2.com - names: - kind: APIGateway - listKind: APIGatewayList - plural: apigateways - singular: apigateway - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: APIGateway is the Schema for the apigateways API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: GatewaySpec defines the desired state of APIGateway - properties: - apiSelector: - description: APISelector defines how this gateway selects which APIs - to route - properties: - matchExpressions: - description: |- - MatchExpressions is a list of label selector requirements for label-based selection. - Only used when Scope is "LabelSelector". - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that the selector applies - to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - matchLabels: - additionalProperties: - type: string - description: |- - MatchLabels is a map of {key,value} pairs for label-based selection. - Only used when Scope is "LabelSelector". - An API must have all specified labels to be selected. - type: object - namespaces: - description: |- - Namespaces is a list of namespaces from which APIs are selected. - Only used when Scope is "Namespaced". - If empty with Namespaced scope, only APIs in the gateway's namespace are selected. - items: - type: string - type: array - scope: - default: Cluster - description: Scope determines the API selection strategy - enum: - - Cluster - - Namespaced - - LabelSelector - type: string - required: - - scope - type: object - configRef: - description: |- - ConfigRef references a ConfigMap containing custom Helm values configuration. - The ConfigMap data should contain a key "values.yaml" with the Helm values content. - If not specified, the operator will use the default mounted configuration. - properties: - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - type: object - x-kubernetes-map-type: atomic - controlPlane: - description: ControlPlane defines the control plane connection settings - properties: - host: - description: Host is the control plane host address - type: string - tls: - description: TLS settings for control plane connection - properties: - certSecretRef: - description: CertSecretRef references a secret containing - TLS certificates - properties: - key: - description: The key of the secret to select from. Must - be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret or its key must - be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - enabled: - default: true - description: Enabled indicates whether TLS is enabled - type: boolean - type: object - tokenSecretRef: - description: TokenSecretRef references a secret containing the - authentication token - properties: - key: - description: The key of the secret to select from. Must be - a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret or its key must be - defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - infrastructure: - description: Infrastructure defines the deployment configuration for - the gateway - properties: - affinity: - description: Affinity for pod assignment - properties: - nodeAffinity: - description: Describes node affinity scheduling rules for - the pod. - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node matches the corresponding matchExpressions; the - node(s) with the highest sum are the most preferred. - items: - description: |- - An empty preferred scheduling term matches all objects with implicit weight 0 - (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). - properties: - preference: - description: A node selector term, associated with - the corresponding weight. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - weight: - description: Weight associated with matching the - corresponding nodeSelectorTerm, in the range 1-100. - format: int32 - type: integer - required: - - preference - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to an update), the system - may or may not try to eventually evict the pod from its node. - properties: - nodeSelectorTerms: - description: Required. A list of node selector terms. - The terms are ORed. - items: - description: |- - A null or empty node selector term matches no objects. The requirements of - them are ANDed. - The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. - properties: - matchExpressions: - description: A list of node selector requirements - by node's labels. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchFields: - description: A list of node selector requirements - by node's fields. - items: - description: |- - A node selector requirement is a selector that contains values, a key, and an operator - that relates the key and values. - properties: - key: - description: The label key that the selector - applies to. - type: string - operator: - description: |- - Represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. - type: string - values: - description: |- - An array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. If the operator is Gt or Lt, the values - array must have a single element, which will be interpreted as an integer. - This array is replaced during a strategic merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - type: object - x-kubernetes-map-type: atomic - type: array - x-kubernetes-list-type: atomic - required: - - nodeSelectorTerms - type: object - x-kubernetes-map-type: atomic - type: object - podAffinity: - description: Describes pod affinity scheduling rules (e.g. - co-locate this pod in the same node, zone, etc. as some - other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - podAntiAffinity: - description: Describes pod anti-affinity scheduling rules - (e.g. avoid putting this pod in the same node, zone, etc. - as some other pod(s)). - properties: - preferredDuringSchedulingIgnoredDuringExecution: - description: |- - The scheduler will prefer to schedule pods to nodes that satisfy - the anti-affinity expressions specified by this field, but it may choose - a node that violates one or more of the expressions. The node that is - most preferred is the one with the greatest sum of weights, i.e. - for each node that meets all of the scheduling requirements (resource - request, requiredDuringScheduling anti-affinity expressions, etc.), - compute a sum by iterating through the elements of this field and adding - "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the - node(s) with the highest sum are the most preferred. - items: - description: The weights of all of the matched WeightedPodAffinityTerm - fields are added per-node to find the most preferred - node(s) - properties: - podAffinityTerm: - description: Required. A pod affinity term, associated - with the corresponding weight. - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list - of label selector requirements. The requirements - are ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key - that the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - weight: - description: |- - weight associated with matching the corresponding podAffinityTerm, - in the range 1-100. - format: int32 - type: integer - required: - - podAffinityTerm - - weight - type: object - type: array - x-kubernetes-list-type: atomic - requiredDuringSchedulingIgnoredDuringExecution: - description: |- - If the anti-affinity requirements specified by this field are not met at - scheduling time, the pod will not be scheduled onto the node. - If the anti-affinity requirements specified by this field cease to be met - at some point during pod execution (e.g. due to a pod label update), the - system may or may not try to eventually evict the pod from its node. - When there are multiple elements, the lists of nodes corresponding to each - podAffinityTerm are intersected, i.e. all terms must be satisfied. - items: - description: |- - Defines a set of pods (namely those matching the labelSelector - relative to the given namespace(s)) that this pod should be - co-located (affinity) or not co-located (anti-affinity) with, - where co-located is defined as running on a node whose value of - the label with key matches that of any node on which - a pod of the set of pods is running - properties: - labelSelector: - description: |- - A label query over a set of resources, in this case pods. - If it's null, this PodAffinityTerm matches with no Pods. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - matchLabelKeys: - description: |- - MatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both matchLabelKeys and labelSelector. - Also, matchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - mismatchLabelKeys: - description: |- - MismatchLabelKeys is a set of pod label keys to select which pods will - be taken into consideration. The keys are used to lookup values from the - incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` - to select the group of existing pods which pods will be taken into consideration - for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming - pod labels will be ignored. The default value is empty. - The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. - Also, mismatchLabelKeys cannot be set when labelSelector isn't set. - items: - type: string - type: array - x-kubernetes-list-type: atomic - namespaceSelector: - description: |- - A label query over the set of namespaces that the term applies to. - The term is applied to the union of the namespaces selected by this field - and the ones listed in the namespaces field. - null selector and null or empty namespaces list means "this pod's namespace". - An empty selector ({}) matches all namespaces. - properties: - matchExpressions: - description: matchExpressions is a list of label - selector requirements. The requirements are - ANDed. - items: - description: |- - A label selector requirement is a selector that contains values, a key, and an operator that - relates the key and values. - properties: - key: - description: key is the label key that - the selector applies to. - type: string - operator: - description: |- - operator represents a key's relationship to a set of values. - Valid operators are In, NotIn, Exists and DoesNotExist. - type: string - values: - description: |- - values is an array of string values. If the operator is In or NotIn, - the values array must be non-empty. If the operator is Exists or DoesNotExist, - the values array must be empty. This array is replaced during a strategic - merge patch. - items: - type: string - type: array - x-kubernetes-list-type: atomic - required: - - key - - operator - type: object - type: array - x-kubernetes-list-type: atomic - matchLabels: - additionalProperties: - type: string - description: |- - matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels - map is equivalent to an element of matchExpressions, whose key field is "key", the - operator is "In", and the values array contains only "value". The requirements are ANDed. - type: object - type: object - x-kubernetes-map-type: atomic - namespaces: - description: |- - namespaces specifies a static list of namespace names that the term applies to. - The term is applied to the union of the namespaces listed in this field - and the ones selected by namespaceSelector. - null or empty namespaces list and null namespaceSelector means "this pod's namespace". - items: - type: string - type: array - x-kubernetes-list-type: atomic - topologyKey: - description: |- - This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching - the labelSelector in the specified namespaces, where co-located is defined as running on a node - whose value of the label with key topologyKey matches that of any node on which any of the - selected pods is running. - Empty topologyKey is not allowed. - type: string - required: - - topologyKey - type: object - type: array - x-kubernetes-list-type: atomic - type: object - type: object - annotations: - additionalProperties: - type: string - description: |- - Annotations are custom annotations propagated to all gateway-managed resources: - Deployment metadata, Pod annotations, Service metadata, and ConfigMaps. - type: object - image: - description: Image is the container image for the gateway - type: string - labels: - additionalProperties: - type: string - description: |- - Labels are custom labels propagated to all gateway-managed resources: - Deployment metadata, Pod labels, Service metadata, and ConfigMaps. - type: object - nodeSelector: - additionalProperties: - type: string - description: NodeSelector is a selector for node assignment - type: object - replicas: - default: 1 - description: Replicas is the number of gateway instances to deploy - format: int32 - minimum: 1 - type: integer - resources: - description: Resources defines the compute resources for gateway - pods - properties: - claims: - description: |- - Claims lists the names of resources, defined in spec.resourceClaims, - that are used by this container. - - This is an alpha field and requires enabling the - DynamicResourceAllocation feature gate. - - This field is immutable. It can only be set for containers. - items: - description: ResourceClaim references one entry in PodSpec.ResourceClaims. - properties: - name: - description: |- - Name must match the name of one entry in pod.spec.resourceClaims of - the Pod where this field is used. It makes that resource available - inside a container. - type: string - request: - description: |- - Request is the name chosen for a request in the referenced claim. - If empty, everything from the claim is made available, otherwise - only the result of this request. - type: string - required: - - name - type: object - type: array - x-kubernetes-list-map-keys: - - name - x-kubernetes-list-type: map - limits: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Limits describes the maximum amount of compute resources allowed. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - requests: - additionalProperties: - anyOf: - - type: integer - - type: string - pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ - x-kubernetes-int-or-string: true - description: |- - Requests describes the minimum amount of compute resources required. - If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, - otherwise to an implementation-defined value. Requests cannot exceed Limits. - More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ - type: object - type: object - routerImage: - description: RouterImage is the container image for the router/proxy - type: string - tolerations: - description: Tolerations for pod assignment - items: - description: |- - The pod this Toleration is attached to tolerates any taint that matches - the triple using the matching operator . - properties: - effect: - description: |- - Effect indicates the taint effect to match. Empty means match all taint effects. - When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. - type: string - key: - description: |- - Key is the taint key that the toleration applies to. Empty means match all taint keys. - If the key is empty, operator must be Exists; this combination means to match all values and all keys. - type: string - operator: - description: |- - Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. - Exists is equivalent to wildcard for value, so that a pod can - tolerate all taints of a particular category. - type: string - tolerationSeconds: - description: |- - TolerationSeconds represents the period of time the toleration (which must be - of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, - it is not set, which means tolerate the taint forever (do not evict). Zero and - negative values will be treated as 0 (evict immediately) by the system. - format: int64 - type: integer - value: - description: |- - Value is the taint value the toleration matches to. - If the operator is Exists, the value should be empty, otherwise just a regular string. - type: string - type: object - type: array - type: object - storage: - description: Storage defines the storage configuration for the gateway - properties: - connectionSecretRef: - description: |- - ConnectionSecretRef references a secret containing database connection details - (used for postgres, mysql, etc.) - properties: - key: - description: The key of the secret to select from. Must be - a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret or its key must be - defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - sqlitePath: - description: SQLitePath is the path for SQLite database (used - when Type is sqlite) - type: string - type: - default: sqlite - description: Type is the storage backend type (sqlite, postgres, - mysql, etc.) - enum: - - sqlite - - postgres - - mysql - type: string - type: object - required: - - apiSelector - type: object - status: - description: GatewayStatus defines the observed state of APIGateway - properties: - appliedGeneration: - description: AppliedGeneration tracks the latest spec generation that - was successfully applied to the cluster - format: int64 - type: integer - conditions: - description: Conditions represent the latest available observations - of the gateway's state - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - configHash: - description: |- - ConfigHash represents the hash of the referenced configuration - used to detect changes in ConfigMap content - type: string - lastUpdateTime: - description: LastUpdateTime is the last time the status was updated - format: date-time - type: string - observedGeneration: - description: ObservedGeneration reflects the generation of the most - recently observed spec - format: int64 - type: integer - phase: - description: Phase represents the current phase of the gateway (Pending, - Ready, Failed) - enum: - - Reconciling - - Ready - - Failed - - Deleting - type: string - selectedAPIs: - description: SelectedAPIs is the count of APIs currently selected - by this gateway - type: integer - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmproviders.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmproviders.yaml deleted file mode 100644 index 3cc7e1366c..0000000000 --- a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmproviders.yaml +++ /dev/null @@ -1,410 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.5 - name: llmproviders.gateway.api-platform.wso2.com -spec: - group: gateway.api-platform.wso2.com - names: - kind: LlmProvider - listKind: LlmProviderList - plural: llmproviders - shortNames: - - llmp - singular: llmprovider - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: LlmProvider is the Schema for the llmproviders API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: LLMProviderConfigData mirrors the management-API LLMProviderConfigData. - properties: - accessControl: - description: AccessControl configures path-level access control. - properties: - exceptions: - description: Exceptions are paths that override the default mode. - items: - description: RouteException defines a path/method exception - used by LLM access control. - properties: - methods: - description: Methods is the list of HTTP methods covered - by this exception. - items: - description: HTTPMethod names an allowed HTTP verb for - LLM access-control and policy paths. - enum: - - GET - - POST - - PUT - - PATCH - - DELETE - - HEAD - - OPTIONS - - '*' - type: string - type: array - path: - description: Path is the exception path pattern. - type: string - required: - - methods - - path - type: object - type: array - mode: - description: Mode selects the default access policy. - enum: - - allow_all - - deny_all - type: string - required: - - mode - type: object - context: - description: Context is the base path for all routes (must start with - /). - pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ - type: string - deploymentState: - description: DeploymentState toggles whether the provider is router-attached. - enum: - - deployed - - undeployed - type: string - displayName: - description: DisplayName is a human-readable LLM provider name. - type: string - policies: - description: Policies is the list of policies applied to this LLM - provider. - items: - description: LLMPolicy describes a single LLM-level policy attachment. - properties: - name: - description: Name is the name of the policy. - type: string - paths: - description: Paths lists path/method/params triples for this - policy. - items: - description: |- - LLMPolicyPath defines a path/methods combination together with policy - parameters; mirrors the management-API LLMPolicyPath. - properties: - methods: - description: Methods is the list of HTTP methods. - items: - description: HTTPMethod names an allowed HTTP verb for - LLM access-control and policy paths. - enum: - - GET - - POST - - PUT - - PATCH - - DELETE - - HEAD - - OPTIONS - - '*' - type: string - type: array - params: - description: Params is a free-form parameter object specific - to the policy. - x-kubernetes-preserve-unknown-fields: true - path: - description: Path is the route path pattern. - type: string - required: - - methods - - path - type: object - type: array - version: - description: Version is the policy version (e.g. v1). - pattern: ^v\d+$ - type: string - required: - - name - - paths - - version - type: object - type: array - resilience: - description: |- - Resilience configures API-level backend/route timeouts applied to all routes - generated for this LLM provider. Supported at the API level only. - properties: - idleTimeout: - description: IdleTimeout Per-route stream idle timeout. "0s" disables. - pattern: ^\d+(\.\d+)?(ms|s|m|h)$ - type: string - timeout: - description: Timeout Maximum time for the entire route (request - to upstream response). "0s" disables. - pattern: ^\d+(\.\d+)?(ms|s|m|h)$ - type: string - type: object - template: - description: Template is the LlmProviderTemplate name to apply. - type: string - upstream: - description: Upstream configures the LLM upstream. - properties: - auth: - description: Auth configures upstream credentials. - properties: - header: - description: |- - Header is the HTTP header to set on outbound requests when the auth - type uses headers (e.g. api-key). - type: string - type: - description: Type identifies the auth scheme. Only api-key - is currently supported. - enum: - - api-key - type: string - value: - description: |- - Value sources the credential. Exactly one of value or valueFrom must - be set. - properties: - value: - description: |- - Value is the inline plaintext value. Avoid for production use; prefer - ValueFrom so the secret is stored in a Kubernetes Secret. - type: string - valueFrom: - description: |- - ValueFrom selects a key from a Kubernetes Secret in the same namespace - as the owning CR. - properties: - key: - description: The key of the secret to select from. Must - be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret or its key - must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-validations: - - message: exactly one of value or valueFrom must be set - rule: has(self.value) != has(self.valueFrom) - required: - - type - - value - type: object - hostRewrite: - description: HostRewrite controls how the Host header is handled - when routing. - enum: - - auto - - manual - type: string - ref: - description: Ref selects a predefined upstream definition by name. - type: string - url: - description: Url is the direct backend URL. - type: string - type: object - upstreamDefinitions: - description: |- - UpstreamDefinitions is the list of reusable upstream definitions (with optional - connect timeout) that upstream.ref can reference. - items: - description: |- - UpstreamDefinition is a reusable upstream configuration with an optional connect timeout and - load-balancing targets. Referenced from an upstream via its `ref` field. Shared by RestApi, - LLM Provider, and MCP; mirrors the management-API UpstreamDefinition schema. - properties: - basePath: - description: |- - BasePath Base path prefix prepended to all requests routed through this upstream (e.g. /api/v2). - Must start with "/" and must not end with "/". Omit for root ("/"). - pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ - type: string - name: - description: Name Unique identifier for this upstream definition - (referenced by upstream.ref). - maxLength: 100 - minLength: 1 - pattern: ^[a-zA-Z0-9\-_]+$ - type: string - timeout: - description: Timeout Optional timeout configuration for this - upstream (connect timeout). - properties: - connect: - description: Connect Connection-establishment timeout duration - (e.g. "5s", "500ms"). "0s" disables. - pattern: ^\d+(\.\d+)?(ms|s|m|h)$ - type: string - type: object - upstreams: - description: Upstreams List of backend targets with optional - weights for load balancing. - items: - description: UpstreamTarget is a single backend target within - an UpstreamDefinition. - properties: - url: - description: Url Backend URL (host and port only; path - comes from the definition's basePath). - pattern: ^https?://[a-zA-Z0-9\-._~:/?#\[\]@!$&'()*+,;=%]+$ - type: string - weight: - description: |- - Weight Relative weight for load balancing across multiple upstream targets. Reserved for - future multi-target load balancing; not applied yet (only the first target is currently used). - maximum: 100 - minimum: 0 - type: integer - required: - - url - type: object - minItems: 1 - type: array - required: - - name - - upstreams - type: object - type: array - version: - description: Version is the semantic version of the LLM provider. - pattern: ^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ - type: string - vhost: - description: Vhost is the virtual host for routing. - type: string - required: - - accessControl - - displayName - - template - - upstream - - version - type: object - status: - description: |- - ResourceStatus carries the controller-managed lifecycle fields shared by - the new management-API CRDs. - - For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the - gateway-controller assigns Id on first deploy; controllers persist it and - use it to address the resource for subsequent update/delete calls. - properties: - conditions: - description: |- - Conditions represent the latest available observations of the - resource's state. The standard types are Accepted and Programmed. - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - id: - description: |- - Id is the gateway-issued identifier for UUID-keyed resources. When - set the controller addresses the resource via PUT/DELETE //{id}. - type: string - lastUpdateTime: - description: LastUpdateTime is the last time the status was updated. - format: date-time - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_mcps.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_mcps.yaml deleted file mode 100644 index 096fac435a..0000000000 --- a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_mcps.yaml +++ /dev/null @@ -1,434 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.5 - name: mcps.gateway.api-platform.wso2.com -spec: - group: gateway.api-platform.wso2.com - names: - kind: Mcp - listKind: McpList - plural: mcps - shortNames: - - mcp - singular: mcp - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: Mcp is the Schema for the mcps API. - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: Spec is the MCP proxy configuration. - properties: - context: - description: Context is the base path for routes (must start with - /). - pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ - type: string - deploymentState: - description: DeploymentState toggles whether the proxy is router-attached. - enum: - - deployed - - undeployed - type: string - displayName: - description: DisplayName is a human-readable MCP proxy name. - type: string - policies: - description: Policies are MCP proxy-level policies. - items: - description: Policy defines a policy attachment as embedded in RestApi - or APIConfigData. - properties: - executionCondition: - description: ExecutionCondition Expression controlling conditional - execution of the policy - type: string - name: - description: Name Name of the policy - type: string - params: - description: Params Arbitrary parameters for the policy (free-form - key/value structure) - x-kubernetes-preserve-unknown-fields: true - version: - description: Version Semantic version of the policy (for example, - v1) - pattern: ^v\d+$ - type: string - required: - - name - - version - type: object - type: array - prompts: - description: Prompts lists optional prompts exposed by this MCP proxy. - items: - description: MCPPrompt mirrors the management-API MCPPrompt schema. - properties: - arguments: - description: Arguments is the optional argument list. - items: - description: MCPPromptArgument describes one input argument - for an MCP prompt. - properties: - description: - description: Description is an optional argument description. - type: string - name: - description: Name is the argument name. - type: string - required: - description: Required marks the argument as mandatory. - type: boolean - title: - description: Title is an optional human-readable label. - type: string - required: - - name - type: object - type: array - description: - description: Description is an optional description. - type: string - name: - description: Name is the unique prompt identifier. - type: string - title: - description: Title is an optional human-readable name. - type: string - required: - - name - type: object - type: array - resilience: - description: |- - Resilience configures API-level backend/route timeouts applied to the traffic-forwarding - routes generated for this MCP proxy. Supported at the API level only. Because MCP transports - are long-lived streams, the route timeout defaults to disabled ("0s") for MCP when unset. - properties: - idleTimeout: - description: IdleTimeout Per-route stream idle timeout. "0s" disables. - pattern: ^\d+(\.\d+)?(ms|s|m|h)$ - type: string - timeout: - description: Timeout Maximum time for the entire route (request - to upstream response). "0s" disables. - pattern: ^\d+(\.\d+)?(ms|s|m|h)$ - type: string - type: object - resources: - description: Resources lists optional MCP resources exposed by this - proxy. - items: - description: MCPResource mirrors the management-API MCPResource - schema. - properties: - description: - description: Description is an optional description. - type: string - mimeType: - description: MimeType is an optional MIME type. - type: string - name: - description: Name is a human-readable resource name. - type: string - size: - description: Size is the optional size in bytes. - format: int64 - type: integer - title: - description: Title is an optional human-readable label. - type: string - uri: - description: Uri is a unique identifier for the resource. - type: string - required: - - name - - uri - type: object - type: array - specVersion: - description: SpecVersion is the MCP specification version. - type: string - tools: - description: Tools lists optional tools exposed by this MCP proxy. - items: - description: MCPTool mirrors the management-API MCPTool schema. - properties: - description: - description: Description is the human-readable functional description. - type: string - inputSchema: - description: InputSchema is the JSON Schema for input parameters. - type: string - name: - description: Name is the unique tool identifier. - type: string - outputSchema: - description: OutputSchema is the optional JSON Schema for the - output. - type: string - title: - description: Title is an optional human-readable label. - type: string - required: - - description - - inputSchema - - name - type: object - type: array - upstream: - description: Upstream is the MCP backend. - properties: - auth: - description: Auth configures upstream credentials. - properties: - header: - description: Header is the HTTP header to set on outbound - requests. - type: string - type: - description: Type identifies the auth scheme. Only api-key - is currently supported. - enum: - - api-key - type: string - value: - description: Value sources the credential plaintext. - properties: - value: - description: |- - Value is the inline plaintext value. Avoid for production use; prefer - ValueFrom so the secret is stored in a Kubernetes Secret. - type: string - valueFrom: - description: |- - ValueFrom selects a key from a Kubernetes Secret in the same namespace - as the owning CR. - properties: - key: - description: The key of the secret to select from. Must - be a valid secret key. - type: string - name: - default: "" - description: |- - Name of the referent. - This field is effectively required, but due to backwards compatibility is - allowed to be empty. Instances of this type with an empty value here are - almost certainly wrong. - More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names - type: string - optional: - description: Specify whether the Secret or its key - must be defined - type: boolean - required: - - key - type: object - x-kubernetes-map-type: atomic - type: object - x-kubernetes-validations: - - message: exactly one of value or valueFrom must be set - rule: has(self.value) != has(self.valueFrom) - required: - - type - - value - type: object - hostRewrite: - description: HostRewrite controls how the Host header is handled. - enum: - - auto - - manual - type: string - ref: - description: Ref is the name of a predefined upstream definition. - type: string - url: - description: Url is the direct backend URL. - type: string - type: object - upstreamDefinitions: - description: |- - UpstreamDefinitions is the list of reusable upstream definitions (with optional - connect timeout) that upstream.ref can reference. - items: - description: |- - UpstreamDefinition is a reusable upstream configuration with an optional connect timeout and - load-balancing targets. Referenced from an upstream via its `ref` field. Shared by RestApi, - LLM Provider, and MCP; mirrors the management-API UpstreamDefinition schema. - properties: - basePath: - description: |- - BasePath Base path prefix prepended to all requests routed through this upstream (e.g. /api/v2). - Must start with "/" and must not end with "/". Omit for root ("/"). - pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ - type: string - name: - description: Name Unique identifier for this upstream definition - (referenced by upstream.ref). - maxLength: 100 - minLength: 1 - pattern: ^[a-zA-Z0-9\-_]+$ - type: string - timeout: - description: Timeout Optional timeout configuration for this - upstream (connect timeout). - properties: - connect: - description: Connect Connection-establishment timeout duration - (e.g. "5s", "500ms"). "0s" disables. - pattern: ^\d+(\.\d+)?(ms|s|m|h)$ - type: string - type: object - upstreams: - description: Upstreams List of backend targets with optional - weights for load balancing. - items: - description: UpstreamTarget is a single backend target within - an UpstreamDefinition. - properties: - url: - description: Url Backend URL (host and port only; path - comes from the definition's basePath). - pattern: ^https?://[a-zA-Z0-9\-._~:/?#\[\]@!$&'()*+,;=%]+$ - type: string - weight: - description: |- - Weight Relative weight for load balancing across multiple upstream targets. Reserved for - future multi-target load balancing; not applied yet (only the first target is currently used). - maximum: 100 - minimum: 0 - type: integer - required: - - url - type: object - minItems: 1 - type: array - required: - - name - - upstreams - type: object - type: array - version: - description: Version is the MCP proxy semantic version. - pattern: ^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ - type: string - vhost: - description: Vhost is the virtual host for routing. - type: string - required: - - displayName - - upstream - - version - type: object - status: - description: |- - ResourceStatus carries the controller-managed lifecycle fields shared by - the new management-API CRDs. - - For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the - gateway-controller assigns Id on first deploy; controllers persist it and - use it to address the resource for subsequent update/delete calls. - properties: - conditions: - description: |- - Conditions represent the latest available observations of the - resource's state. The standard types are Accepted and Programmed. - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - x-kubernetes-list-map-keys: - - type - x-kubernetes-list-type: map - id: - description: |- - Id is the gateway-issued identifier for UUID-keyed resources. When - set the controller addresses the resource via PUT/DELETE //{id}. - type: string - lastUpdateTime: - description: LastUpdateTime is the last time the status was updated. - format: date-time - type: string - type: object - required: - - spec - type: object - served: true - storage: true - subresources: - status: {} diff --git a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_restapis.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_restapis.yaml deleted file mode 100644 index 00e7fd4d24..0000000000 --- a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_restapis.yaml +++ /dev/null @@ -1,360 +0,0 @@ ---- -apiVersion: apiextensions.k8s.io/v1 -kind: CustomResourceDefinition -metadata: - annotations: - controller-gen.kubebuilder.io/version: v0.16.5 - name: restapis.gateway.api-platform.wso2.com -spec: - group: gateway.api-platform.wso2.com - names: - kind: RestApi - listKind: RestApiList - plural: restapis - singular: restapi - scope: Namespaced - versions: - - name: v1alpha1 - schema: - openAPIV3Schema: - description: RestApi is the Schema for the restapis API - properties: - apiVersion: - description: |- - APIVersion defines the versioned schema of this representation of an object. - Servers should convert recognized schemas to the latest internal value, and - may reject unrecognized values. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources - type: string - kind: - description: |- - Kind is a string value representing the REST resource this object represents. - Servers may infer this from the endpoint the client submits requests to. - Cannot be updated. - In CamelCase. - More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds - type: string - metadata: - type: object - spec: - description: APIConfigData defines model for APIConfigData. - properties: - context: - description: Context Base path for all API routes (must start with - /, no trailing slash; "/" denotes the root context) - pattern: ^/([a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/])?$ - type: string - displayName: - description: DisplayName Human-readable API name (must be URL-friendly - - only letters, numbers, spaces, hyphens, underscores, and dots - allowed) - pattern: ^[a-zA-Z0-9\s\-_.]+$ - type: string - operations: - description: Operations List of HTTP operations/routes - items: - description: Operation defines model for Operation. - properties: - method: - description: Method HTTP method - enum: - - GET - - POST - - PUT - - PATCH - - DELETE - - HEAD - - OPTIONS - type: string - path: - description: Path Route path with optional {param} placeholders - pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/{}\[\]]*$ - type: string - policies: - description: Policies List of policies applied only to this - operation (overrides or adds to API-level policies) - items: - description: Policy defines a policy attachment as embedded - in RestApi or APIConfigData. - properties: - executionCondition: - description: ExecutionCondition Expression controlling - conditional execution of the policy - type: string - name: - description: Name Name of the policy - type: string - params: - description: Params Arbitrary parameters for the policy - (free-form key/value structure) - x-kubernetes-preserve-unknown-fields: true - version: - description: Version Semantic version of the policy (for - example, v1) - pattern: ^v\d+$ - type: string - required: - - name - - version - type: object - type: array - resilience: - description: Resilience Operation-level backend/route timeout - configuration (overrides API-level) - properties: - idleTimeout: - description: IdleTimeout Per-route stream idle timeout. - "0s" disables. - pattern: ^\d+(\.\d+)?(ms|s|m|h)$ - type: string - timeout: - description: Timeout Maximum time for the entire route (request - to upstream response). "0s" disables. - pattern: ^\d+(\.\d+)?(ms|s|m|h)$ - type: string - type: object - required: - - method - - path - type: object - minItems: 1 - type: array - policies: - description: Policies List of API-level policies applied to all operations - unless overridden - items: - description: Policy defines a policy attachment as embedded in RestApi - or APIConfigData. - properties: - executionCondition: - description: ExecutionCondition Expression controlling conditional - execution of the policy - type: string - name: - description: Name Name of the policy - type: string - params: - description: Params Arbitrary parameters for the policy (free-form - key/value structure) - x-kubernetes-preserve-unknown-fields: true - version: - description: Version Semantic version of the policy (for example, - v1) - pattern: ^v\d+$ - type: string - required: - - name - - version - type: object - type: array - resilience: - description: |- - Resilience API-level backend/route timeout configuration applied to all operations - unless overridden at the operation level - properties: - idleTimeout: - description: IdleTimeout Per-route stream idle timeout. "0s" disables. - pattern: ^\d+(\.\d+)?(ms|s|m|h)$ - type: string - timeout: - description: Timeout Maximum time for the entire route (request - to upstream response). "0s" disables. - pattern: ^\d+(\.\d+)?(ms|s|m|h)$ - type: string - type: object - upstream: - description: Upstream API-level upstream configuration - properties: - main: - description: Main Upstream backend configuration for production - traffic - properties: - ref: - description: Ref Name of a predefined upstreamDefinition to - route through. - type: string - url: - description: Url Direct backend service URL (may include path - prefix like /api/v2) - pattern: ^https?://[a-zA-Z0-9\-._~:/?#\[\]@!$&'()*+,;=%]+$ - type: string - type: object - x-kubernetes-validations: - - message: exactly one of url or ref must be set - rule: has(self.url) != has(self.ref) - sandbox: - description: Sandbox Upstream backend configuration for sandbox/testing - traffic - properties: - ref: - description: Ref Name of a predefined upstreamDefinition to - route through. - type: string - url: - description: Url Direct backend service URL (may include path - prefix like /api/v2) - pattern: ^https?://[a-zA-Z0-9\-._~:/?#\[\]@!$&'()*+,;=%]+$ - type: string - type: object - x-kubernetes-validations: - - message: exactly one of url or ref must be set - rule: has(self.url) != has(self.ref) - required: - - main - type: object - upstreamDefinitions: - description: |- - UpstreamDefinitions is the list of reusable upstream definitions (with optional connect - timeout) that upstream.ref can reference. - items: - description: |- - UpstreamDefinition is a reusable upstream configuration with an optional connect timeout and - load-balancing targets. Referenced from an upstream via its `ref` field. Shared by RestApi, - LLM Provider, and MCP; mirrors the management-API UpstreamDefinition schema. - properties: - basePath: - description: |- - BasePath Base path prefix prepended to all requests routed through this upstream (e.g. /api/v2). - Must start with "/" and must not end with "/". Omit for root ("/"). - pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ - type: string - name: - description: Name Unique identifier for this upstream definition - (referenced by upstream.ref). - maxLength: 100 - minLength: 1 - pattern: ^[a-zA-Z0-9\-_]+$ - type: string - timeout: - description: Timeout Optional timeout configuration for this - upstream (connect timeout). - properties: - connect: - description: Connect Connection-establishment timeout duration - (e.g. "5s", "500ms"). "0s" disables. - pattern: ^\d+(\.\d+)?(ms|s|m|h)$ - type: string - type: object - upstreams: - description: Upstreams List of backend targets with optional - weights for load balancing. - items: - description: UpstreamTarget is a single backend target within - an UpstreamDefinition. - properties: - url: - description: Url Backend URL (host and port only; path - comes from the definition's basePath). - pattern: ^https?://[a-zA-Z0-9\-._~:/?#\[\]@!$&'()*+,;=%]+$ - type: string - weight: - description: |- - Weight Relative weight for load balancing across multiple upstream targets. Reserved for - future multi-target load balancing; not applied yet (only the first target is currently used). - maximum: 100 - minimum: 0 - type: integer - required: - - url - type: object - minItems: 1 - type: array - required: - - name - - upstreams - type: object - type: array - version: - description: Version Semantic version of the API - pattern: ^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ - type: string - vhosts: - description: Vhosts Custom virtual hosts/domains for the API - properties: - main: - description: Main Custom virtual host/domain for production traffic - type: string - sandbox: - description: Sandbox Custom virtual host/domain for sandbox traffic - type: string - required: - - main - type: object - required: - - context - - displayName - - operations - - upstream - - version - type: object - status: - description: RestApiStatus defines the observed state of RestApi - properties: - conditions: - description: Conditions represent the latest available observations - of the API's state - items: - description: Condition contains details for one aspect of the current - state of this API Resource. - properties: - lastTransitionTime: - description: |- - lastTransitionTime is the last time the condition transitioned from one status to another. - This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. - format: date-time - type: string - message: - description: |- - message is a human readable message indicating details about the transition. - This may be an empty string. - maxLength: 32768 - type: string - observedGeneration: - description: |- - observedGeneration represents the .metadata.generation that the condition was set based upon. - For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date - with respect to the current state of the instance. - format: int64 - minimum: 0 - type: integer - reason: - description: |- - reason contains a programmatic identifier indicating the reason for the condition's last transition. - Producers of specific condition types may define expected values and meanings for this field, - and whether the values are considered a guaranteed API. - The value should be a CamelCase string. - This field may not be empty. - maxLength: 1024 - minLength: 1 - pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ - type: string - status: - description: status of the condition, one of True, False, Unknown. - enum: - - "True" - - "False" - - Unknown - type: string - type: - description: type of condition in CamelCase or in foo.example.com/CamelCase. - maxLength: 316 - pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ - type: string - required: - - lastTransitionTime - - message - - reason - - status - - type - type: object - type: array - lastUpdateTime: - description: LastUpdateTime is the last time the status was updated - format: date-time - type: string - type: object - type: object - served: true - storage: true - subresources: - status: {} diff --git a/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_apigateways.yaml b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_apigateways.yaml new file mode 100644 index 0000000000..a289afe7d2 --- /dev/null +++ b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_apigateways.yaml @@ -0,0 +1,2758 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: apigateways.gateway.api-platform.wso2.com +spec: + group: gateway.api-platform.wso2.com + names: + kind: APIGateway + listKind: APIGatewayList + plural: apigateways + singular: apigateway + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: APIGateway is the Schema for the apigateways API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: GatewaySpec defines the desired state of APIGateway + properties: + apiSelector: + description: APISelector defines how this gateway selects which APIs + to route + properties: + matchExpressions: + description: |- + MatchExpressions is a list of label selector requirements for label-based selection. + Only used when Scope is "LabelSelector". + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + MatchLabels is a map of {key,value} pairs for label-based selection. + Only used when Scope is "LabelSelector". + An API must have all specified labels to be selected. + type: object + namespaces: + description: |- + Namespaces is a list of namespaces from which APIs are selected. + Only used when Scope is "Namespaced". + If empty with Namespaced scope, only APIs in the gateway's namespace are selected. + items: + type: string + type: array + scope: + default: Cluster + description: Scope determines the API selection strategy + enum: + - Cluster + - Namespaced + - LabelSelector + type: string + required: + - scope + type: object + configRef: + description: |- + ConfigRef references a ConfigMap containing custom Helm values configuration. + The ConfigMap data should contain a key "values.yaml" with the Helm values content. + If not specified, the operator will use the default mounted configuration. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + controlPlane: + description: ControlPlane defines the control plane connection settings + properties: + host: + description: Host is the control plane host address + type: string + tls: + description: TLS settings for control plane connection + properties: + certSecretRef: + description: CertSecretRef references a secret containing + TLS certificates + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + enabled: + default: true + description: Enabled indicates whether TLS is enabled + type: boolean + type: object + tokenSecretRef: + description: TokenSecretRef references a secret containing the + authentication token + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + infrastructure: + description: Infrastructure defines the deployment configuration for + the gateway + properties: + affinity: + description: Affinity for pod assignment + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + annotations: + additionalProperties: + type: string + description: |- + Annotations are custom annotations propagated to all gateway-managed resources: + Deployment metadata, Pod annotations, Service metadata, and ConfigMaps. + type: object + image: + description: Image is the container image for the gateway + type: string + labels: + additionalProperties: + type: string + description: |- + Labels are custom labels propagated to all gateway-managed resources: + Deployment metadata, Pod labels, Service metadata, and ConfigMaps. + type: object + nodeSelector: + additionalProperties: + type: string + description: NodeSelector is a selector for node assignment + type: object + replicas: + default: 1 + description: Replicas is the number of gateway instances to deploy + format: int32 + minimum: 1 + type: integer + resources: + description: Resources defines the compute resources for gateway + pods + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This field depends on the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + routerImage: + description: RouterImage is the container image for the router/proxy + type: string + tolerations: + description: Tolerations for pod assignment + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + type: object + storage: + description: Storage defines the storage configuration for the gateway + properties: + connectionSecretRef: + description: |- + ConnectionSecretRef references a secret containing database connection details + (used for postgres, mysql, etc.) + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + sqlitePath: + description: SQLitePath is the path for SQLite database (used + when Type is sqlite) + type: string + type: + default: sqlite + description: Type is the storage backend type (sqlite, postgres, + mysql, etc.) + enum: + - sqlite + - postgres + - mysql + type: string + type: object + required: + - apiSelector + type: object + status: + description: GatewayStatus defines the observed state of APIGateway + properties: + appliedGeneration: + description: AppliedGeneration tracks the latest spec generation that + was successfully applied to the cluster + format: int64 + type: integer + conditions: + description: Conditions represent the latest available observations + of the gateway's state + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + configHash: + description: |- + ConfigHash represents the hash of the referenced configuration + used to detect changes in ConfigMap content + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated + format: date-time + type: string + observedGeneration: + description: ObservedGeneration reflects the generation of the most + recently observed spec + format: int64 + type: integer + phase: + description: Phase represents the current phase of the gateway (Pending, + Ready, Failed) + enum: + - Reconciling + - Ready + - Failed + - Deleting + type: string + selectedAPIs: + description: SelectedAPIs is the count of APIs currently selected + by this gateway + type: integer + type: object + type: object + served: true + storage: true + subresources: + status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: APIGateway is the Schema for the apigateways API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: GatewaySpec defines the desired state of APIGateway + properties: + apiSelector: + description: APISelector defines how this gateway selects which APIs + to route + properties: + matchExpressions: + description: |- + MatchExpressions is a list of label selector requirements for label-based selection. + Only used when Scope is "LabelSelector". + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that the selector applies + to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + matchLabels: + additionalProperties: + type: string + description: |- + MatchLabels is a map of {key,value} pairs for label-based selection. + Only used when Scope is "LabelSelector". + An API must have all specified labels to be selected. + type: object + namespaces: + description: |- + Namespaces is a list of namespaces from which APIs are selected. + Only used when Scope is "Namespaced". + If empty with Namespaced scope, only APIs in the gateway's namespace are selected. + items: + type: string + type: array + scope: + default: Cluster + description: Scope determines the API selection strategy + enum: + - Cluster + - Namespaced + - LabelSelector + type: string + required: + - scope + type: object + configRef: + description: |- + ConfigRef references a ConfigMap containing custom Helm values configuration. + The ConfigMap data should contain a key "values.yaml" with the Helm values content. + If not specified, the operator will use the default mounted configuration. + properties: + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + type: object + x-kubernetes-map-type: atomic + controlPlane: + description: ControlPlane defines the control plane connection settings + properties: + host: + description: Host is the control plane host address + type: string + tls: + description: TLS settings for control plane connection + properties: + certSecretRef: + description: CertSecretRef references a secret containing + TLS certificates + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must + be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + enabled: + default: true + description: Enabled indicates whether TLS is enabled + type: boolean + type: object + tokenSecretRef: + description: TokenSecretRef references a secret containing the + authentication token + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + infrastructure: + description: Infrastructure defines the deployment configuration for + the gateway + properties: + affinity: + description: Affinity for pod assignment + properties: + nodeAffinity: + description: Describes node affinity scheduling rules for + the pod. + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node matches the corresponding matchExpressions; the + node(s) with the highest sum are the most preferred. + items: + description: |- + An empty preferred scheduling term matches all objects with implicit weight 0 + (i.e. it's a no-op). A null preferred scheduling term matches no objects (i.e. is also a no-op). + properties: + preference: + description: A node selector term, associated with + the corresponding weight. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + weight: + description: Weight associated with matching the + corresponding nodeSelectorTerm, in the range 1-100. + format: int32 + type: integer + required: + - preference + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to an update), the system + may or may not try to eventually evict the pod from its node. + properties: + nodeSelectorTerms: + description: Required. A list of node selector terms. + The terms are ORed. + items: + description: |- + A null or empty node selector term matches no objects. The requirements of + them are ANDed. + The TopologySelectorTerm type implements a subset of the NodeSelectorTerm. + properties: + matchExpressions: + description: A list of node selector requirements + by node's labels. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchFields: + description: A list of node selector requirements + by node's fields. + items: + description: |- + A node selector requirement is a selector that contains values, a key, and an operator + that relates the key and values. + properties: + key: + description: The label key that the selector + applies to. + type: string + operator: + description: |- + Represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists, DoesNotExist. Gt, and Lt. + type: string + values: + description: |- + An array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. If the operator is Gt or Lt, the values + array must have a single element, which will be interpreted as an integer. + This array is replaced during a strategic merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + type: object + x-kubernetes-map-type: atomic + type: array + x-kubernetes-list-type: atomic + required: + - nodeSelectorTerms + type: object + x-kubernetes-map-type: atomic + type: object + podAffinity: + description: Describes pod affinity scheduling rules (e.g. + co-locate this pod in the same node, zone, etc. as some + other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling affinity expressions, etc.), + compute a sum by iterating through the elements of this field and adding + "weight" to the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + podAntiAffinity: + description: Describes pod anti-affinity scheduling rules + (e.g. avoid putting this pod in the same node, zone, etc. + as some other pod(s)). + properties: + preferredDuringSchedulingIgnoredDuringExecution: + description: |- + The scheduler will prefer to schedule pods to nodes that satisfy + the anti-affinity expressions specified by this field, but it may choose + a node that violates one or more of the expressions. The node that is + most preferred is the one with the greatest sum of weights, i.e. + for each node that meets all of the scheduling requirements (resource + request, requiredDuringScheduling anti-affinity expressions, etc.), + compute a sum by iterating through the elements of this field and subtracting + "weight" from the sum if the node has pods which matches the corresponding podAffinityTerm; the + node(s) with the highest sum are the most preferred. + items: + description: The weights of all of the matched WeightedPodAffinityTerm + fields are added per-node to find the most preferred + node(s) + properties: + podAffinityTerm: + description: Required. A pod affinity term, associated + with the corresponding weight. + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list + of label selector requirements. The requirements + are ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key + that the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + weight: + description: |- + weight associated with matching the corresponding podAffinityTerm, + in the range 1-100. + format: int32 + type: integer + required: + - podAffinityTerm + - weight + type: object + type: array + x-kubernetes-list-type: atomic + requiredDuringSchedulingIgnoredDuringExecution: + description: |- + If the anti-affinity requirements specified by this field are not met at + scheduling time, the pod will not be scheduled onto the node. + If the anti-affinity requirements specified by this field cease to be met + at some point during pod execution (e.g. due to a pod label update), the + system may or may not try to eventually evict the pod from its node. + When there are multiple elements, the lists of nodes corresponding to each + podAffinityTerm are intersected, i.e. all terms must be satisfied. + items: + description: |- + Defines a set of pods (namely those matching the labelSelector + relative to the given namespace(s)) that this pod should be + co-located (affinity) or not co-located (anti-affinity) with, + where co-located is defined as running on a node whose value of + the label with key matches that of any node on which + a pod of the set of pods is running + properties: + labelSelector: + description: |- + A label query over a set of resources, in this case pods. + If it's null, this PodAffinityTerm matches with no Pods. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + matchLabelKeys: + description: |- + MatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key in (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both matchLabelKeys and labelSelector. + Also, matchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + mismatchLabelKeys: + description: |- + MismatchLabelKeys is a set of pod label keys to select which pods will + be taken into consideration. The keys are used to lookup values from the + incoming pod labels, those key-value labels are merged with `labelSelector` as `key notin (value)` + to select the group of existing pods which pods will be taken into consideration + for the incoming pod's pod (anti) affinity. Keys that don't exist in the incoming + pod labels will be ignored. The default value is empty. + The same key is forbidden to exist in both mismatchLabelKeys and labelSelector. + Also, mismatchLabelKeys cannot be set when labelSelector isn't set. + items: + type: string + type: array + x-kubernetes-list-type: atomic + namespaceSelector: + description: |- + A label query over the set of namespaces that the term applies to. + The term is applied to the union of the namespaces selected by this field + and the ones listed in the namespaces field. + null selector and null or empty namespaces list means "this pod's namespace". + An empty selector ({}) matches all namespaces. + properties: + matchExpressions: + description: matchExpressions is a list of label + selector requirements. The requirements are + ANDed. + items: + description: |- + A label selector requirement is a selector that contains values, a key, and an operator that + relates the key and values. + properties: + key: + description: key is the label key that + the selector applies to. + type: string + operator: + description: |- + operator represents a key's relationship to a set of values. + Valid operators are In, NotIn, Exists and DoesNotExist. + type: string + values: + description: |- + values is an array of string values. If the operator is In or NotIn, + the values array must be non-empty. If the operator is Exists or DoesNotExist, + the values array must be empty. This array is replaced during a strategic + merge patch. + items: + type: string + type: array + x-kubernetes-list-type: atomic + required: + - key + - operator + type: object + type: array + x-kubernetes-list-type: atomic + matchLabels: + additionalProperties: + type: string + description: |- + matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + map is equivalent to an element of matchExpressions, whose key field is "key", the + operator is "In", and the values array contains only "value". The requirements are ANDed. + type: object + type: object + x-kubernetes-map-type: atomic + namespaces: + description: |- + namespaces specifies a static list of namespace names that the term applies to. + The term is applied to the union of the namespaces listed in this field + and the ones selected by namespaceSelector. + null or empty namespaces list and null namespaceSelector means "this pod's namespace". + items: + type: string + type: array + x-kubernetes-list-type: atomic + topologyKey: + description: |- + This pod should be co-located (affinity) or not co-located (anti-affinity) with the pods matching + the labelSelector in the specified namespaces, where co-located is defined as running on a node + whose value of the label with key topologyKey matches that of any node on which any of the + selected pods is running. + Empty topologyKey is not allowed. + type: string + required: + - topologyKey + type: object + type: array + x-kubernetes-list-type: atomic + type: object + type: object + annotations: + additionalProperties: + type: string + description: |- + Annotations are custom annotations propagated to all gateway-managed resources: + Deployment metadata, Pod annotations, Service metadata, and ConfigMaps. + type: object + image: + description: Image is the container image for the gateway + type: string + labels: + additionalProperties: + type: string + description: |- + Labels are custom labels propagated to all gateway-managed resources: + Deployment metadata, Pod labels, Service metadata, and ConfigMaps. + type: object + nodeSelector: + additionalProperties: + type: string + description: NodeSelector is a selector for node assignment + type: object + replicas: + default: 1 + description: Replicas is the number of gateway instances to deploy + format: int32 + minimum: 1 + type: integer + resources: + description: Resources defines the compute resources for gateway + pods + properties: + claims: + description: |- + Claims lists the names of resources, defined in spec.resourceClaims, + that are used by this container. + + This field depends on the + DynamicResourceAllocation feature gate. + + This field is immutable. It can only be set for containers. + items: + description: ResourceClaim references one entry in PodSpec.ResourceClaims. + properties: + name: + description: |- + Name must match the name of one entry in pod.spec.resourceClaims of + the Pod where this field is used. It makes that resource available + inside a container. + type: string + request: + description: |- + Request is the name chosen for a request in the referenced claim. + If empty, everything from the claim is made available, otherwise + only the result of this request. + type: string + required: + - name + type: object + type: array + x-kubernetes-list-map-keys: + - name + x-kubernetes-list-type: map + limits: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Limits describes the maximum amount of compute resources allowed. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + requests: + additionalProperties: + anyOf: + - type: integer + - type: string + pattern: ^(\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))(([KMGTPE]i)|[numkMGTPE]|([eE](\+|-)?(([0-9]+(\.[0-9]*)?)|(\.[0-9]+))))?$ + x-kubernetes-int-or-string: true + description: |- + Requests describes the minimum amount of compute resources required. + If Requests is omitted for a container, it defaults to Limits if that is explicitly specified, + otherwise to an implementation-defined value. Requests cannot exceed Limits. + More info: https://kubernetes.io/docs/concepts/configuration/manage-resources-containers/ + type: object + type: object + routerImage: + description: RouterImage is the container image for the router/proxy + type: string + tolerations: + description: Tolerations for pod assignment + items: + description: |- + The pod this Toleration is attached to tolerates any taint that matches + the triple using the matching operator . + properties: + effect: + description: |- + Effect indicates the taint effect to match. Empty means match all taint effects. + When specified, allowed values are NoSchedule, PreferNoSchedule and NoExecute. + type: string + key: + description: |- + Key is the taint key that the toleration applies to. Empty means match all taint keys. + If the key is empty, operator must be Exists; this combination means to match all values and all keys. + type: string + operator: + description: |- + Operator represents a key's relationship to the value. + Valid operators are Exists, Equal, Lt, and Gt. Defaults to Equal. + Exists is equivalent to wildcard for value, so that a pod can + tolerate all taints of a particular category. + Lt and Gt perform numeric comparisons (requires feature gate TaintTolerationComparisonOperators). + type: string + tolerationSeconds: + description: |- + TolerationSeconds represents the period of time the toleration (which must be + of effect NoExecute, otherwise this field is ignored) tolerates the taint. By default, + it is not set, which means tolerate the taint forever (do not evict). Zero and + negative values will be treated as 0 (evict immediately) by the system. + format: int64 + type: integer + value: + description: |- + Value is the taint value the toleration matches to. + If the operator is Exists, the value should be empty, otherwise just a regular string. + type: string + type: object + type: array + type: object + storage: + description: Storage defines the storage configuration for the gateway + properties: + connectionSecretRef: + description: |- + ConnectionSecretRef references a secret containing database connection details + (used for postgres, mysql, etc.) + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + sqlitePath: + description: SQLitePath is the path for SQLite database (used + when Type is sqlite) + type: string + type: + default: sqlite + description: Type is the storage backend type (sqlite, postgres, + mysql, etc.) + enum: + - sqlite + - postgres + - mysql + type: string + type: object + required: + - apiSelector + type: object + status: + description: GatewayStatus defines the observed state of APIGateway + properties: + appliedGeneration: + description: AppliedGeneration tracks the latest spec generation that + was successfully applied to the cluster + format: int64 + type: integer + conditions: + description: Conditions represent the latest available observations + of the gateway's state + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + configHash: + description: |- + ConfigHash represents the hash of the referenced configuration + used to detect changes in ConfigMap content + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated + format: date-time + type: string + observedGeneration: + description: ObservedGeneration reflects the generation of the most + recently observed spec + format: int64 + type: integer + phase: + description: Phase represents the current phase of the gateway (Pending, + Ready, Failed) + enum: + - Reconciling + - Ready + - Failed + - Deleting + type: string + selectedAPIs: + description: SelectedAPIs is the count of APIs currently selected + by this gateway + type: integer + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_apikeys.yaml b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_apikeys.yaml similarity index 50% rename from kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_apikeys.yaml rename to kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_apikeys.yaml index 3e3e8d8c57..04e1f9502b 100644 --- a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_apikeys.yaml +++ b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_apikeys.yaml @@ -16,7 +16,7 @@ spec: singular: apikey scope: Namespaced versions: - - name: v1alpha1 + - name: v1 schema: openAPIV3Schema: description: |- @@ -245,3 +245,232 @@ spec: storage: true subresources: status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + ApiKey is the Schema for the apikeys API. + + The key handle in the management API is the CR's metadata.name. The + nested REST path is built from spec.parentRef.kind + spec.parentRef.name. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + ApiKeySpec mirrors the management-API APIKeyCreationRequest payload, with + the optional inline ApiKey expressed as a SecretValueSource for external- + key injection (so the value need not be inlined in the CR). + properties: + apiKey: + description: |- + ApiKey is an optional pre-generated key value (>= 36 chars). When + supplied the gateway hashes the value rather than generating its own. + properties: + value: + description: |- + Value is the inline plaintext value. Avoid for production use; prefer + ValueFrom so the secret is stored in a Kubernetes Secret. + type: string + valueFrom: + description: |- + ValueFrom selects a key from a Kubernetes Secret in the same namespace + as the owning CR. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: exactly one of value or valueFrom must be set + rule: has(self.value) != has(self.valueFrom) + displayName: + description: DisplayName is a human-readable label for the key. + type: string + expiresAt: + description: |- + ExpiresAt is an optional absolute expiry time. + Mutually exclusive with expiresIn: the ApiKey spec CEL rule + "!has(self.expiresAt) || !has(self.expiresIn)" rejects manifests that set both. + format: date-time + type: string + expiresIn: + description: |- + ExpiresIn is an optional duration after which the key expires. + Mutually exclusive with expiresAt: the ApiKey spec CEL rule + "!has(self.expiresAt) || !has(self.expiresIn)" rejects manifests that set both. + properties: + duration: + description: Duration is the magnitude of the expiry duration + (must be positive). + format: int64 + minimum: 1 + type: integer + unit: + description: Unit is the time unit of the expiry duration. + enum: + - seconds + - minutes + - hours + - days + - weeks + - months + type: string + required: + - duration + - unit + type: object + externalRefId: + description: ExternalRefId is an optional reference id for tracing. + type: string + issuer: + description: Issuer optionally constrains regeneration to a single + portal. + type: string + maskedApiKey: + description: |- + MaskedApiKey is an optional masked rendering of an externally + generated key, used purely for display by portals. + type: string + parentRef: + description: ParentRef identifies the resource the key is issued under. + properties: + kind: + description: Kind selects the parent resource kind. + enum: + - RestApi + - LlmProvider + - LlmProxy + type: string + name: + description: Name is the parent resource handle (metadata.name). + type: string + required: + - kind + - name + type: object + required: + - parentRef + type: object + x-kubernetes-validations: + - message: expiresAt and expiresIn are mutually exclusive + rule: '!has(self.expiresAt) || !has(self.expiresIn)' + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_apipolicies.yaml b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_apipolicies.yaml similarity index 51% rename from kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_apipolicies.yaml rename to kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_apipolicies.yaml index 57f5b0d811..e3edf89b96 100644 --- a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_apipolicies.yaml +++ b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_apipolicies.yaml @@ -26,7 +26,7 @@ spec: - jsonPath: .metadata.creationTimestamp name: Age type: date - name: v1alpha1 + name: v1 schema: openAPIV3Schema: description: |- @@ -187,3 +187,174 @@ spec: storage: true subresources: status: {} + - additionalPrinterColumns: + - jsonPath: .spec.targetRef.name + name: Target + type: string + - jsonPath: .spec.policies[0].name + name: First + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + APIPolicy is a namespaced policy definition for the Gateway API HTTPRoute integration only. + Set spec.targetRef to apply policies at API level for that HTTPRoute, or omit targetRef and reference + this object from HTTPRoute rule filters (ExtensionRef) for rule/match scope. It does not apply to RestApi / APIGateway reconciliation. + (Distinct from the embedded Policy type on RestApi.) + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: APIPolicySpec holds an optional targetRef for API-level attachment + and a list of policy instances (same shape as RestApi embedded policies). + properties: + policies: + description: Policies is the list of policy instances (name, version, + optional params, executionCondition). + items: + description: Policy defines a policy attachment as embedded in RestApi + or APIConfigData. + properties: + executionCondition: + description: ExecutionCondition Expression controlling conditional + execution of the policy + type: string + name: + description: Name Name of the policy + type: string + params: + description: Params Arbitrary parameters for the policy (free-form + key/value structure) + x-kubernetes-preserve-unknown-fields: true + version: + description: Version Semantic version of the policy (for example, + v1) + pattern: ^v\d+$ + type: string + required: + - name + - version + type: object + minItems: 1 + type: array + targetRef: + description: |- + TargetRef selects the HTTPRoute for API-level policies: when set, all spec.policies entries are merged into APIConfigData.policies for that route. + When omitted, this APIPolicy applies only when referenced from HTTPRoute rule filters (ExtensionRef). + properties: + group: + description: Group of the referent (e.g. gateway.networking.k8s.io). + enum: + - gateway.networking.k8s.io + minLength: 1 + type: string + kind: + description: Kind of the referent. Use HTTPRoute for Gateway API + integration. + enum: + - HTTPRoute + minLength: 1 + type: string + name: + description: Name of the referent HTTPRoute. + minLength: 1 + type: string + namespace: + description: Namespace of the referent; defaults to the APIPolicy's + namespace if unset. + type: string + required: + - group + - kind + - name + type: object + required: + - policies + type: object + status: + description: APIPolicyStatus defines observed state. + properties: + conditions: + description: Conditions represent the latest observations. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_certificates.yaml b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_certificates.yaml similarity index 51% rename from kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_certificates.yaml rename to kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_certificates.yaml index 33b61c6a7b..ae6c4d8e67 100644 --- a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_certificates.yaml +++ b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_certificates.yaml @@ -16,7 +16,7 @@ spec: singular: certificate scope: Namespaced versions: - - name: v1alpha1 + - name: v1 schema: openAPIV3Schema: description: Certificate is the Schema for the certificates API. @@ -183,3 +183,170 @@ spec: storage: true subresources: status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Certificate is the Schema for the certificates API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + CertificateSpec mirrors the management-API CertificateUploadRequest, with + the PEM bytes expressed as a SecretValueSource so production-grade + certificates can be referenced from a Kubernetes Secret rather than + inlined into the CR. + + The gateway-controller assigns a UUID id on first upload that the + controller persists to .status.id; subsequent reconcile uses + `/certificates/{status.id}` for PUT/DELETE. + properties: + certificate: + description: Certificate is the PEM-encoded X.509 certificate (single + or bundle). + properties: + value: + description: |- + Value is the inline plaintext value. Avoid for production use; prefer + ValueFrom so the secret is stored in a Kubernetes Secret. + type: string + valueFrom: + description: |- + ValueFrom selects a key from a Kubernetes Secret in the same namespace + as the owning CR. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: exactly one of value or valueFrom must be set + rule: has(self.value) != has(self.valueFrom) + displayName: + description: |- + DisplayName is a human-readable certificate name. The controller + passes it through to the management API as `name`. + type: string + required: + - certificate + - displayName + type: object + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_llmproviders.yaml b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_llmproviders.yaml new file mode 100644 index 0000000000..72fb9c33fb --- /dev/null +++ b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_llmproviders.yaml @@ -0,0 +1,802 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: llmproviders.gateway.api-platform.wso2.com +spec: + group: gateway.api-platform.wso2.com + names: + kind: LlmProvider + listKind: LlmProviderList + plural: llmproviders + shortNames: + - llmp + singular: llmprovider + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: LlmProvider is the Schema for the llmproviders API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: LLMProviderConfigData mirrors the management-API LLMProviderConfigData. + properties: + accessControl: + description: AccessControl configures path-level access control. + properties: + exceptions: + description: Exceptions are paths that override the default mode. + items: + description: RouteException defines a path/method exception + used by LLM access control. + properties: + methods: + description: Methods is the list of HTTP methods covered + by this exception. + items: + description: HTTPMethod names an allowed HTTP verb for + LLM access-control and policy paths. + enum: + - GET + - POST + - PUT + - PATCH + - DELETE + - HEAD + - OPTIONS + - '*' + type: string + type: array + path: + description: Path is the exception path pattern. + type: string + required: + - methods + - path + type: object + type: array + mode: + description: Mode selects the default access policy. + enum: + - allow_all + - deny_all + type: string + required: + - mode + type: object + context: + description: Context is the base path for all routes (must start with + /). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ + type: string + deploymentState: + description: DeploymentState toggles whether the provider is router-attached. + enum: + - deployed + - undeployed + type: string + displayName: + description: DisplayName is a human-readable LLM provider name. + type: string + policies: + description: Policies is the list of policies applied to this LLM + provider. + items: + description: LLMPolicy describes a single LLM-level policy attachment. + properties: + name: + description: Name is the name of the policy. + type: string + paths: + description: Paths lists path/method/params triples for this + policy. + items: + description: |- + LLMPolicyPath defines a path/methods combination together with policy + parameters; mirrors the management-API LLMPolicyPath. + properties: + methods: + description: Methods is the list of HTTP methods. + items: + description: HTTPMethod names an allowed HTTP verb for + LLM access-control and policy paths. + enum: + - GET + - POST + - PUT + - PATCH + - DELETE + - HEAD + - OPTIONS + - '*' + type: string + type: array + params: + description: Params is a free-form parameter object specific + to the policy. + x-kubernetes-preserve-unknown-fields: true + path: + description: Path is the route path pattern. + type: string + required: + - methods + - path + type: object + type: array + version: + description: Version is the policy version (e.g. v1). + pattern: ^v\d+$ + type: string + required: + - name + - paths + - version + type: object + type: array + resilience: + description: |- + Resilience configures API-level backend/route timeouts applied to all routes + generated for this LLM provider. Supported at the API level only. + properties: + idleTimeout: + description: IdleTimeout Per-route stream idle timeout. "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + timeout: + description: Timeout Maximum time for the entire route (request + to upstream response). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + template: + description: Template is the LlmProviderTemplate name to apply. + type: string + upstream: + description: Upstream configures the LLM upstream. + properties: + auth: + description: Auth configures upstream credentials. + properties: + header: + description: |- + Header is the HTTP header to set on outbound requests when the auth + type uses headers (e.g. api-key). + type: string + type: + description: Type identifies the auth scheme. Only api-key + is currently supported. + enum: + - api-key + type: string + value: + description: |- + Value sources the credential. Exactly one of value or valueFrom must + be set. + properties: + value: + description: |- + Value is the inline plaintext value. Avoid for production use; prefer + ValueFrom so the secret is stored in a Kubernetes Secret. + type: string + valueFrom: + description: |- + ValueFrom selects a key from a Kubernetes Secret in the same namespace + as the owning CR. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: exactly one of value or valueFrom must be set + rule: has(self.value) != has(self.valueFrom) + required: + - type + - value + type: object + hostRewrite: + description: HostRewrite controls how the Host header is handled + when routing. + enum: + - auto + - manual + type: string + ref: + description: Ref selects a predefined upstream definition by name. + type: string + url: + description: Url is the direct backend URL. + type: string + type: object + upstreamDefinitions: + description: |- + UpstreamDefinitions is the list of reusable upstream definitions (with optional + connect timeout) that upstream.ref can reference. + items: + description: |- + UpstreamDefinition is a reusable upstream configuration with an optional connect timeout and + one or more weighted load-balancing targets. Referenced from an upstream via its `ref` field + and by the dynamic-endpoint policy. Shared by RestApi, LLM Provider, and MCP; mirrors the + management-API UpstreamDefinition schema. + properties: + basePath: + description: |- + BasePath Base path prefix prepended to all requests routed through this upstream (e.g. /api/v2). + Must start with "/" and must not end with "/". Omit for root ("/"). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ + type: string + name: + description: |- + Name Unique identifier for this upstream definition (referenced by upstream.ref or the + dynamic-endpoint policy). + maxLength: 100 + minLength: 1 + pattern: ^[a-zA-Z0-9\-_]+$ + type: string + timeout: + description: Timeout Optional timeout configuration for this + upstream (connect timeout). + properties: + connect: + description: Connect Connection-establishment timeout duration + (e.g. "5s", "500ms"). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + upstreams: + description: Upstreams List of backend targets with optional + weights for load balancing. + items: + description: WeightedUpstream is a single backend target within + an UpstreamDefinition. + properties: + url: + description: Url Backend URL (host and port; no path) + type: string + weight: + description: |- + Weight Relative weight for load balancing across multiple upstream targets. Reserved for + future multi-target load balancing; not applied yet (only the first target is currently used). + maximum: 100 + minimum: 0 + type: integer + required: + - url + type: object + minItems: 1 + type: array + required: + - name + - upstreams + type: object + type: array + version: + description: Version is the semantic version of the LLM provider. + pattern: ^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ + type: string + vhost: + description: Vhost is the virtual host for routing. + type: string + required: + - accessControl + - displayName + - template + - upstream + - version + type: object + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: LlmProvider is the Schema for the llmproviders API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: LLMProviderConfigData mirrors the management-API LLMProviderConfigData. + properties: + accessControl: + description: AccessControl configures path-level access control. + properties: + exceptions: + description: Exceptions are paths that override the default mode. + items: + description: RouteException defines a path/method exception + used by LLM access control. + properties: + methods: + description: Methods is the list of HTTP methods covered + by this exception. + items: + description: HTTPMethod names an allowed HTTP verb for + LLM access-control and policy paths. + enum: + - GET + - POST + - PUT + - PATCH + - DELETE + - HEAD + - OPTIONS + - '*' + type: string + type: array + path: + description: Path is the exception path pattern. + type: string + required: + - methods + - path + type: object + type: array + mode: + description: Mode selects the default access policy. + enum: + - allow_all + - deny_all + type: string + required: + - mode + type: object + context: + description: Context is the base path for all routes (must start with + /). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ + type: string + deploymentState: + description: DeploymentState toggles whether the provider is router-attached. + enum: + - deployed + - undeployed + type: string + displayName: + description: DisplayName is a human-readable LLM provider name. + type: string + policies: + description: Policies is the list of policies applied to this LLM + provider. + items: + description: LLMPolicy describes a single LLM-level policy attachment. + properties: + name: + description: Name is the name of the policy. + type: string + paths: + description: Paths lists path/method/params triples for this + policy. + items: + description: |- + LLMPolicyPath defines a path/methods combination together with policy + parameters; mirrors the management-API LLMPolicyPath. + properties: + methods: + description: Methods is the list of HTTP methods. + items: + description: HTTPMethod names an allowed HTTP verb for + LLM access-control and policy paths. + enum: + - GET + - POST + - PUT + - PATCH + - DELETE + - HEAD + - OPTIONS + - '*' + type: string + type: array + params: + description: Params is a free-form parameter object specific + to the policy. + x-kubernetes-preserve-unknown-fields: true + path: + description: Path is the route path pattern. + type: string + required: + - methods + - path + type: object + type: array + version: + description: Version is the policy version (e.g. v1). + pattern: ^v\d+$ + type: string + required: + - name + - paths + - version + type: object + type: array + resilience: + description: |- + Resilience configures API-level backend/route timeouts applied to all routes + generated for this LLM provider. Supported at the API level only. + properties: + idleTimeout: + description: IdleTimeout Per-route stream idle timeout. "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + timeout: + description: Timeout Maximum time for the entire route (request + to upstream response). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + template: + description: Template is the LlmProviderTemplate name to apply. + type: string + upstream: + description: Upstream configures the LLM upstream. + properties: + auth: + description: Auth configures upstream credentials. + properties: + header: + description: |- + Header is the HTTP header to set on outbound requests when the auth + type uses headers (e.g. api-key). + type: string + type: + description: Type identifies the auth scheme. Only api-key + is currently supported. + enum: + - api-key + type: string + value: + description: |- + Value sources the credential. Exactly one of value or valueFrom must + be set. + properties: + value: + description: |- + Value is the inline plaintext value. Avoid for production use; prefer + ValueFrom so the secret is stored in a Kubernetes Secret. + type: string + valueFrom: + description: |- + ValueFrom selects a key from a Kubernetes Secret in the same namespace + as the owning CR. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: exactly one of value or valueFrom must be set + rule: has(self.value) != has(self.valueFrom) + required: + - type + - value + type: object + hostRewrite: + description: HostRewrite controls how the Host header is handled + when routing. + enum: + - auto + - manual + type: string + ref: + description: Ref selects a predefined upstream definition by name. + type: string + url: + description: Url is the direct backend URL. + type: string + type: object + upstreamDefinitions: + description: |- + UpstreamDefinitions is the list of reusable upstream definitions (with optional + connect timeout) that upstream.ref can reference. + items: + description: |- + UpstreamDefinition is a reusable upstream configuration with an optional connect timeout and + one or more weighted load-balancing targets. Referenced from an upstream via its `ref` field + and by the dynamic-endpoint policy. Shared by RestApi, LLM Provider, and MCP; mirrors the + management-API UpstreamDefinition schema. + properties: + basePath: + description: |- + BasePath Base path prefix prepended to all requests routed through this upstream (e.g. /api/v2). + Must start with "/" and must not end with "/". Omit for root ("/"). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ + type: string + name: + description: |- + Name Unique identifier for this upstream definition (referenced by upstream.ref or the + dynamic-endpoint policy). + maxLength: 100 + minLength: 1 + pattern: ^[a-zA-Z0-9\-_]+$ + type: string + timeout: + description: Timeout Optional timeout configuration for this + upstream (connect timeout). + properties: + connect: + description: Connect Connection-establishment timeout duration + (e.g. "5s", "500ms"). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + upstreams: + description: Upstreams List of backend targets with optional + weights for load balancing. + items: + description: WeightedUpstream is a single backend target within + an UpstreamDefinition. + properties: + url: + description: Url Backend URL (host and port; no path) + type: string + weight: + description: |- + Weight Relative weight for load balancing across multiple upstream targets. Reserved for + future multi-target load balancing; not applied yet (only the first target is currently used). + maximum: 100 + minimum: 0 + type: integer + required: + - url + type: object + minItems: 1 + type: array + required: + - name + - upstreams + type: object + type: array + version: + description: Version is the semantic version of the LLM provider. + pattern: ^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ + type: string + vhost: + description: Vhost is the virtual host for routing. + type: string + required: + - accessControl + - displayName + - template + - upstream + - version + type: object + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmprovidertemplates.yaml b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_llmprovidertemplates.yaml similarity index 50% rename from kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmprovidertemplates.yaml rename to kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_llmprovidertemplates.yaml index c6fee1cf83..299fa01e0c 100644 --- a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmprovidertemplates.yaml +++ b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_llmprovidertemplates.yaml @@ -16,7 +16,7 @@ spec: singular: llmprovidertemplate scope: Namespaced versions: - - name: v1alpha1 + - name: v1 schema: openAPIV3Schema: description: LlmProviderTemplate is the Schema for the llmprovidertemplates @@ -402,3 +402,389 @@ spec: storage: true subresources: status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: LlmProviderTemplate is the Schema for the llmprovidertemplates + API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + LLMProviderTemplateData mirrors the management-API LLMProviderTemplateData + payload. The non-resource extractor fields apply when no resourceMappings + entry matches the request path. + properties: + completionTokens: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + displayName: + description: DisplayName is a human-readable LLM template name. + type: string + promptTokens: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + remainingTokens: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + requestModel: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + resourceMappings: + description: LLMProviderTemplateResourceMappings lists per-resource + extraction mappings. + properties: + resources: + items: + description: |- + LLMProviderTemplateResourceMapping maps a resource path pattern to per-field + extraction identifiers for a given LLM API resource. + properties: + completionTokens: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or + header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + promptTokens: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or + header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + remainingTokens: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or + header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + requestModel: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or + header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + resource: + description: Resource is the resource path pattern this + mapping applies to. + type: string + responseModel: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or + header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + totalTokens: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or + header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + required: + - resource + type: object + type: array + type: object + responseModel: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + totalTokens: + description: |- + ExtractionIdentifier locates a value within an HTTP request or response. + Mirrors the gateway-controller management API ExtractionIdentifier model. + properties: + identifier: + description: Identifier is a JSONPath expression or header name. + type: string + location: + description: Location is where to look for the value. + enum: + - header + - pathParam + - payload + - queryParam + type: string + required: + - identifier + - location + type: object + required: + - displayName + type: object + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmproxies.yaml b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_llmproxies.yaml similarity index 50% rename from kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmproxies.yaml rename to kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_llmproxies.yaml index abb9ccb133..2d01119964 100644 --- a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmproxies.yaml +++ b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_llmproxies.yaml @@ -16,7 +16,7 @@ spec: singular: llmproxy scope: Namespaced versions: - - name: v1alpha1 + - name: v1 schema: openAPIV3Schema: description: LlmProxy is the Schema for the llmproxies API. @@ -400,3 +400,387 @@ spec: storage: true subresources: status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: LlmProxy is the Schema for the llmproxies API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec is the LLM proxy configuration payload. + properties: + additionalProviders: + description: |- + AdditionalProviders are extra LLM providers attached as selectable + upstreams for multi-provider routing. + items: + description: |- + LLMProxyAdditionalProvider references an additional LlmProvider that this + proxy can route to by policy-selected upstream name. + properties: + as: + description: As is the logical upstream name used by policies. + Defaults to Id. + type: string + auth: + description: |- + Auth optionally configures credentials for proxy-to-provider loopback + calls when the referenced provider is protected by an auth policy. + properties: + header: + description: |- + Header is the HTTP header to set on outbound requests when the auth + type uses headers (e.g. api-key). + type: string + type: + description: Type identifies the auth scheme. Only api-key + is currently supported. + enum: + - api-key + type: string + value: + description: |- + Value sources the credential. Exactly one of value or valueFrom must + be set. + properties: + value: + description: |- + Value is the inline plaintext value. Avoid for production use; prefer + ValueFrom so the secret is stored in a Kubernetes Secret. + type: string + valueFrom: + description: |- + ValueFrom selects a key from a Kubernetes Secret in the same namespace + as the owning CR. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: exactly one of value or valueFrom must be set + rule: has(self.value) != has(self.valueFrom) + required: + - type + - value + type: object + id: + description: Id is the LlmProvider handle (metadata.name). + type: string + transformer: + description: |- + Transformer optionally applies a request/response translator when this + provider is the selected upstream. The proxy injects it as a conditional + policy that runs only when this provider is selected. + properties: + params: + description: |- + Params carries translator-specific parameters (for example model, + apiVersion). + x-kubernetes-preserve-unknown-fields: true + type: + description: Type is the translator policy name (for example + openai-to-anthropic). + type: string + version: + description: |- + Version is the major-only translator policy version (for example v1). + The Gateway Controller resolves it to the installed full version. + pattern: ^v\d+$ + type: string + required: + - type + - version + type: object + required: + - id + type: object + type: array + context: + description: Context is the base path for routes (must start with + /). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ + type: string + deploymentState: + description: DeploymentState toggles whether the proxy is router-attached. + enum: + - deployed + - undeployed + type: string + displayName: + description: DisplayName is a human-readable LLM proxy name. + type: string + policies: + description: Policies is the list of policies applied to this LLM + proxy. + items: + description: LLMPolicy describes a single LLM-level policy attachment. + properties: + name: + description: Name is the name of the policy. + type: string + paths: + description: Paths lists path/method/params triples for this + policy. + items: + description: |- + LLMPolicyPath defines a path/methods combination together with policy + parameters; mirrors the management-API LLMPolicyPath. + properties: + methods: + description: Methods is the list of HTTP methods. + items: + description: HTTPMethod names an allowed HTTP verb for + LLM access-control and policy paths. + enum: + - GET + - POST + - PUT + - PATCH + - DELETE + - HEAD + - OPTIONS + - '*' + type: string + type: array + params: + description: Params is a free-form parameter object specific + to the policy. + x-kubernetes-preserve-unknown-fields: true + path: + description: Path is the route path pattern. + type: string + required: + - methods + - path + type: object + type: array + version: + description: Version is the policy version (e.g. v1). + pattern: ^v\d+$ + type: string + required: + - name + - paths + - version + type: object + type: array + provider: + description: Provider references the deployed LLM provider this proxy + fronts. + properties: + auth: + description: |- + Auth optionally overrides upstream credentials when calling the + referenced LLM provider. + properties: + header: + description: |- + Header is the HTTP header to set on outbound requests when the auth + type uses headers (e.g. api-key). + type: string + type: + description: Type identifies the auth scheme. Only api-key + is currently supported. + enum: + - api-key + type: string + value: + description: |- + Value sources the credential. Exactly one of value or valueFrom must + be set. + properties: + value: + description: |- + Value is the inline plaintext value. Avoid for production use; prefer + ValueFrom so the secret is stored in a Kubernetes Secret. + type: string + valueFrom: + description: |- + ValueFrom selects a key from a Kubernetes Secret in the same namespace + as the owning CR. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: exactly one of value or valueFrom must be set + rule: has(self.value) != has(self.valueFrom) + required: + - type + - value + type: object + id: + description: Id is the LlmProvider handle (metadata.name). + type: string + required: + - id + type: object + resilience: + description: |- + Resilience configures API-level backend/route timeouts applied to all routes + generated for this LLM proxy. Supported at the API level only. + properties: + idleTimeout: + description: IdleTimeout Per-route stream idle timeout. "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + timeout: + description: Timeout Maximum time for the entire route (request + to upstream response). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + version: + description: Version is the semantic version of the LLM proxy. + pattern: ^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ + type: string + vhost: + description: Vhost is the virtual host for routing. + type: string + required: + - displayName + - provider + - version + type: object + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_managedsecrets.yaml b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_managedsecrets.yaml similarity index 51% rename from kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_managedsecrets.yaml rename to kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_managedsecrets.yaml index 5a430b9c03..9b3510d1ac 100644 --- a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_managedsecrets.yaml +++ b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_managedsecrets.yaml @@ -16,7 +16,7 @@ spec: singular: managedsecret scope: Namespaced versions: - - name: v1alpha1 + - name: v1 schema: openAPIV3Schema: description: |- @@ -184,3 +184,171 @@ spec: storage: true subresources: status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + ManagedSecret represents a platform secret stored by the gateway-controller. + + The CRD is named ManagedSecret (rather than Secret) so it does not collide + with the built-in core/v1 Secret kind. The plural "managedsecrets" is used + in URLs and RBAC to remain unambiguous. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + SecretSpec mirrors the management-API SecretConfigData payload, with the + sensitive Value field expressed as a SecretValueSource so operators can + keep plaintext out of the CR by referencing a Kubernetes Secret. + properties: + description: + description: Description is an optional description of the secret. + type: string + displayName: + description: DisplayName is a human-readable secret name. + type: string + value: + description: Value is the secret plaintext, supplied either inline + or via valueFrom. + properties: + value: + description: |- + Value is the inline plaintext value. Avoid for production use; prefer + ValueFrom so the secret is stored in a Kubernetes Secret. + type: string + valueFrom: + description: |- + ValueFrom selects a key from a Kubernetes Secret in the same namespace + as the owning CR. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: exactly one of value or valueFrom must be set + rule: has(self.value) != has(self.valueFrom) + required: + - displayName + - value + type: object + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_mcps.yaml b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_mcps.yaml new file mode 100644 index 0000000000..922c91fba6 --- /dev/null +++ b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_mcps.yaml @@ -0,0 +1,850 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: mcps.gateway.api-platform.wso2.com +spec: + group: gateway.api-platform.wso2.com + names: + kind: Mcp + listKind: McpList + plural: mcps + shortNames: + - mcp + singular: mcp + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Mcp is the Schema for the mcps API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec is the MCP proxy configuration. + properties: + context: + description: Context is the base path for routes (must start with + /). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ + type: string + deploymentState: + description: DeploymentState toggles whether the proxy is router-attached. + enum: + - deployed + - undeployed + type: string + displayName: + description: DisplayName is a human-readable MCP proxy name. + type: string + policies: + description: Policies are MCP proxy-level policies. + items: + description: Policy defines a policy attachment as embedded in RestApi + or APIConfigData. + properties: + executionCondition: + description: ExecutionCondition Expression controlling conditional + execution of the policy + type: string + name: + description: Name Name of the policy + type: string + params: + description: Params Arbitrary parameters for the policy (free-form + key/value structure) + x-kubernetes-preserve-unknown-fields: true + version: + description: Version Semantic version of the policy (for example, + v1) + pattern: ^v\d+$ + type: string + required: + - name + - version + type: object + type: array + prompts: + description: Prompts lists optional prompts exposed by this MCP proxy. + items: + description: MCPPrompt mirrors the management-API MCPPrompt schema. + properties: + arguments: + description: Arguments is the optional argument list. + items: + description: MCPPromptArgument describes one input argument + for an MCP prompt. + properties: + description: + description: Description is an optional argument description. + type: string + name: + description: Name is the argument name. + type: string + required: + description: Required marks the argument as mandatory. + type: boolean + title: + description: Title is an optional human-readable label. + type: string + required: + - name + type: object + type: array + description: + description: Description is an optional description. + type: string + name: + description: Name is the unique prompt identifier. + type: string + title: + description: Title is an optional human-readable name. + type: string + required: + - name + type: object + type: array + resilience: + description: |- + Resilience configures API-level backend/route timeouts applied to the traffic-forwarding + routes generated for this MCP proxy. Supported at the API level only. Because MCP transports + are long-lived streams, the route timeout defaults to disabled ("0s") for MCP when unset. + properties: + idleTimeout: + description: IdleTimeout Per-route stream idle timeout. "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + timeout: + description: Timeout Maximum time for the entire route (request + to upstream response). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + resources: + description: Resources lists optional MCP resources exposed by this + proxy. + items: + description: MCPResource mirrors the management-API MCPResource + schema. + properties: + description: + description: Description is an optional description. + type: string + mimeType: + description: MimeType is an optional MIME type. + type: string + name: + description: Name is a human-readable resource name. + type: string + size: + description: Size is the optional size in bytes. + format: int64 + type: integer + title: + description: Title is an optional human-readable label. + type: string + uri: + description: Uri is a unique identifier for the resource. + type: string + required: + - name + - uri + type: object + type: array + specVersion: + description: SpecVersion is the MCP specification version. + type: string + tools: + description: Tools lists optional tools exposed by this MCP proxy. + items: + description: MCPTool mirrors the management-API MCPTool schema. + properties: + description: + description: Description is the human-readable functional description. + type: string + inputSchema: + description: InputSchema is the JSON Schema for input parameters. + type: string + name: + description: Name is the unique tool identifier. + type: string + outputSchema: + description: OutputSchema is the optional JSON Schema for the + output. + type: string + title: + description: Title is an optional human-readable label. + type: string + required: + - description + - inputSchema + - name + type: object + type: array + upstream: + description: Upstream is the MCP backend. + properties: + auth: + description: Auth configures upstream credentials. + properties: + header: + description: Header is the HTTP header to set on outbound + requests. + type: string + type: + description: Type identifies the auth scheme. Only api-key + is currently supported. + enum: + - api-key + type: string + value: + description: Value sources the credential plaintext. + properties: + value: + description: |- + Value is the inline plaintext value. Avoid for production use; prefer + ValueFrom so the secret is stored in a Kubernetes Secret. + type: string + valueFrom: + description: |- + ValueFrom selects a key from a Kubernetes Secret in the same namespace + as the owning CR. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: exactly one of value or valueFrom must be set + rule: has(self.value) != has(self.valueFrom) + required: + - type + - value + type: object + hostRewrite: + description: HostRewrite controls how the Host header is handled. + enum: + - auto + - manual + type: string + ref: + description: Ref is the name of a predefined upstream definition. + type: string + url: + description: Url is the direct backend URL. + type: string + type: object + upstreamDefinitions: + description: |- + UpstreamDefinitions is the list of reusable upstream definitions (with optional + connect timeout) that upstream.ref can reference. + items: + description: |- + UpstreamDefinition is a reusable upstream configuration with an optional connect timeout and + one or more weighted load-balancing targets. Referenced from an upstream via its `ref` field + and by the dynamic-endpoint policy. Shared by RestApi, LLM Provider, and MCP; mirrors the + management-API UpstreamDefinition schema. + properties: + basePath: + description: |- + BasePath Base path prefix prepended to all requests routed through this upstream (e.g. /api/v2). + Must start with "/" and must not end with "/". Omit for root ("/"). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ + type: string + name: + description: |- + Name Unique identifier for this upstream definition (referenced by upstream.ref or the + dynamic-endpoint policy). + maxLength: 100 + minLength: 1 + pattern: ^[a-zA-Z0-9\-_]+$ + type: string + timeout: + description: Timeout Optional timeout configuration for this + upstream (connect timeout). + properties: + connect: + description: Connect Connection-establishment timeout duration + (e.g. "5s", "500ms"). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + upstreams: + description: Upstreams List of backend targets with optional + weights for load balancing. + items: + description: WeightedUpstream is a single backend target within + an UpstreamDefinition. + properties: + url: + description: Url Backend URL (host and port; no path) + type: string + weight: + description: |- + Weight Relative weight for load balancing across multiple upstream targets. Reserved for + future multi-target load balancing; not applied yet (only the first target is currently used). + maximum: 100 + minimum: 0 + type: integer + required: + - url + type: object + minItems: 1 + type: array + required: + - name + - upstreams + type: object + type: array + version: + description: Version is the MCP proxy semantic version. + pattern: ^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ + type: string + vhost: + description: Vhost is the virtual host for routing. + type: string + required: + - displayName + - upstream + - version + type: object + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + required: + - spec + type: object + served: true + storage: true + subresources: + status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: Mcp is the Schema for the mcps API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: Spec is the MCP proxy configuration. + properties: + context: + description: Context is the base path for routes (must start with + /). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ + type: string + deploymentState: + description: DeploymentState toggles whether the proxy is router-attached. + enum: + - deployed + - undeployed + type: string + displayName: + description: DisplayName is a human-readable MCP proxy name. + type: string + policies: + description: Policies are MCP proxy-level policies. + items: + description: Policy defines a policy attachment as embedded in RestApi + or APIConfigData. + properties: + executionCondition: + description: ExecutionCondition Expression controlling conditional + execution of the policy + type: string + name: + description: Name Name of the policy + type: string + params: + description: Params Arbitrary parameters for the policy (free-form + key/value structure) + x-kubernetes-preserve-unknown-fields: true + version: + description: Version Semantic version of the policy (for example, + v1) + pattern: ^v\d+$ + type: string + required: + - name + - version + type: object + type: array + prompts: + description: Prompts lists optional prompts exposed by this MCP proxy. + items: + description: MCPPrompt mirrors the management-API MCPPrompt schema. + properties: + arguments: + description: Arguments is the optional argument list. + items: + description: MCPPromptArgument describes one input argument + for an MCP prompt. + properties: + description: + description: Description is an optional argument description. + type: string + name: + description: Name is the argument name. + type: string + required: + description: Required marks the argument as mandatory. + type: boolean + title: + description: Title is an optional human-readable label. + type: string + required: + - name + type: object + type: array + description: + description: Description is an optional description. + type: string + name: + description: Name is the unique prompt identifier. + type: string + title: + description: Title is an optional human-readable name. + type: string + required: + - name + type: object + type: array + resilience: + description: |- + Resilience configures API-level backend/route timeouts applied to the traffic-forwarding + routes generated for this MCP proxy. Supported at the API level only. Because MCP transports + are long-lived streams, the route timeout defaults to disabled ("0s") for MCP when unset. + properties: + idleTimeout: + description: IdleTimeout Per-route stream idle timeout. "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + timeout: + description: Timeout Maximum time for the entire route (request + to upstream response). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + resources: + description: Resources lists optional MCP resources exposed by this + proxy. + items: + description: MCPResource mirrors the management-API MCPResource + schema. + properties: + description: + description: Description is an optional description. + type: string + mimeType: + description: MimeType is an optional MIME type. + type: string + name: + description: Name is a human-readable resource name. + type: string + size: + description: Size is the optional size in bytes. + format: int64 + type: integer + title: + description: Title is an optional human-readable label. + type: string + uri: + description: Uri is a unique identifier for the resource. + type: string + required: + - name + - uri + type: object + type: array + specVersion: + description: SpecVersion is the MCP specification version. + type: string + tools: + description: Tools lists optional tools exposed by this MCP proxy. + items: + description: MCPTool mirrors the management-API MCPTool schema. + properties: + description: + description: Description is the human-readable functional description. + type: string + inputSchema: + description: InputSchema is the JSON Schema for input parameters. + type: string + name: + description: Name is the unique tool identifier. + type: string + outputSchema: + description: OutputSchema is the optional JSON Schema for the + output. + type: string + title: + description: Title is an optional human-readable label. + type: string + required: + - description + - inputSchema + - name + type: object + type: array + upstream: + description: Upstream is the MCP backend. + properties: + auth: + description: Auth configures upstream credentials. + properties: + header: + description: Header is the HTTP header to set on outbound + requests. + type: string + type: + description: Type identifies the auth scheme. Only api-key + is currently supported. + enum: + - api-key + type: string + value: + description: Value sources the credential plaintext. + properties: + value: + description: |- + Value is the inline plaintext value. Avoid for production use; prefer + ValueFrom so the secret is stored in a Kubernetes Secret. + type: string + valueFrom: + description: |- + ValueFrom selects a key from a Kubernetes Secret in the same namespace + as the owning CR. + properties: + key: + description: The key of the secret to select from. Must + be a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key + must be defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: exactly one of value or valueFrom must be set + rule: has(self.value) != has(self.valueFrom) + required: + - type + - value + type: object + hostRewrite: + description: HostRewrite controls how the Host header is handled. + enum: + - auto + - manual + type: string + ref: + description: Ref is the name of a predefined upstream definition. + type: string + url: + description: Url is the direct backend URL. + type: string + type: object + upstreamDefinitions: + description: |- + UpstreamDefinitions is the list of reusable upstream definitions (with optional + connect timeout) that upstream.ref can reference. + items: + description: |- + UpstreamDefinition is a reusable upstream configuration with an optional connect timeout and + one or more weighted load-balancing targets. Referenced from an upstream via its `ref` field + and by the dynamic-endpoint policy. Shared by RestApi, LLM Provider, and MCP; mirrors the + management-API UpstreamDefinition schema. + properties: + basePath: + description: |- + BasePath Base path prefix prepended to all requests routed through this upstream (e.g. /api/v2). + Must start with "/" and must not end with "/". Omit for root ("/"). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ + type: string + name: + description: |- + Name Unique identifier for this upstream definition (referenced by upstream.ref or the + dynamic-endpoint policy). + maxLength: 100 + minLength: 1 + pattern: ^[a-zA-Z0-9\-_]+$ + type: string + timeout: + description: Timeout Optional timeout configuration for this + upstream (connect timeout). + properties: + connect: + description: Connect Connection-establishment timeout duration + (e.g. "5s", "500ms"). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + upstreams: + description: Upstreams List of backend targets with optional + weights for load balancing. + items: + description: WeightedUpstream is a single backend target within + an UpstreamDefinition. + properties: + url: + description: Url Backend URL (host and port; no path) + type: string + weight: + description: |- + Weight Relative weight for load balancing across multiple upstream targets. Reserved for + future multi-target load balancing; not applied yet (only the first target is currently used). + maximum: 100 + minimum: 0 + type: integer + required: + - url + type: object + minItems: 1 + type: array + required: + - name + - upstreams + type: object + type: array + version: + description: Version is the MCP proxy semantic version. + pattern: ^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ + type: string + vhost: + description: Vhost is the virtual host for routing. + type: string + required: + - displayName + - upstream + - version + type: object + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_restapis.yaml b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_restapis.yaml new file mode 100644 index 0000000000..5f24ae37a1 --- /dev/null +++ b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_restapis.yaml @@ -0,0 +1,886 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.5 + name: restapis.gateway.api-platform.wso2.com +spec: + group: gateway.api-platform.wso2.com + names: + kind: RestApi + listKind: RestApiList + plural: restapis + singular: restapi + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: RestApi is the Schema for the restapis API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: APIConfigData defines model for APIConfigData. + properties: + context: + description: Context Base path for all API routes (must start with + /, no trailing slash; "/" denotes the root context) + pattern: ^/([a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/])?$ + type: string + displayName: + description: DisplayName Human-readable API name (must be URL-friendly + - only letters, numbers, spaces, hyphens, underscores, and dots + allowed) + pattern: ^[a-zA-Z0-9\s\-_.]+$ + type: string + operations: + description: Operations List of HTTP operations/routes + items: + description: |- + Operation defines model for Operation. + An operation is matched either by the simple top-level method+path fields or by the richer + Match block (method + path + headers). When Match is set it is authoritative and the + top-level Method/Path are ignored. Exactly one form must be provided. + properties: + match: + description: Match Request matching criteria for the operation. + Extensible with query params, cookies, etc. + properties: + headers: + description: Headers ANDed header matchers applied before + routing to this operation. + items: + description: OperationHeaderMatch mirrors Gateway API + HTTPHeaderMatch for Envoy route selection. + properties: + name: + description: Name Header name (case-insensitive) + type: string + type: + description: Type Match type (Exact or RegularExpression) + enum: + - Exact + - RegularExpression + type: string + value: + description: Value Header value to match + type: string + required: + - name + - value + type: object + type: array + method: + description: Method HTTP method + enum: + - GET + - POST + - PUT + - PATCH + - DELETE + - HEAD + - OPTIONS + type: string + path: + description: Path Path match criteria + properties: + type: + description: Type How the path is matched (Exact or + PathPrefix). Defaults to Exact when omitted. + enum: + - Exact + - PathPrefix + type: string + value: + description: Value Route path with optional {param} + placeholders + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/{}\[\]]*$ + type: string + required: + - value + type: object + required: + - method + - path + type: object + method: + description: Method HTTP method (simple form; ignored when Match + is set). + enum: + - GET + - POST + - PUT + - PATCH + - DELETE + - HEAD + - OPTIONS + type: string + path: + description: Path Route path with optional {param} placeholders + (simple form; ignored when Match is set). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/{}\[\]]*$ + type: string + policies: + description: Policies List of policies applied only to this + operation (overrides or adds to API-level policies) + items: + description: Policy defines a policy attachment as embedded + in RestApi or APIConfigData. + properties: + executionCondition: + description: ExecutionCondition Expression controlling + conditional execution of the policy + type: string + name: + description: Name Name of the policy + type: string + params: + description: Params Arbitrary parameters for the policy + (free-form key/value structure) + x-kubernetes-preserve-unknown-fields: true + version: + description: Version Semantic version of the policy (for + example, v1) + pattern: ^v\d+$ + type: string + required: + - name + - version + type: object + type: array + resilience: + description: Resilience Operation-level backend/route timeout + configuration (overrides API-level) + properties: + idleTimeout: + description: IdleTimeout Per-route stream idle timeout. + "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + timeout: + description: Timeout Maximum time for the entire route (request + to upstream response). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + type: object + x-kubernetes-validations: + - message: operation must set both method and path, or set match + rule: (has(self.method) && has(self.path)) || has(self.match) + minItems: 1 + type: array + policies: + description: Policies List of API-level policies applied to all operations + unless overridden + items: + description: Policy defines a policy attachment as embedded in RestApi + or APIConfigData. + properties: + executionCondition: + description: ExecutionCondition Expression controlling conditional + execution of the policy + type: string + name: + description: Name Name of the policy + type: string + params: + description: Params Arbitrary parameters for the policy (free-form + key/value structure) + x-kubernetes-preserve-unknown-fields: true + version: + description: Version Semantic version of the policy (for example, + v1) + pattern: ^v\d+$ + type: string + required: + - name + - version + type: object + type: array + resilience: + description: |- + Resilience API-level backend/route timeout configuration applied to all operations + unless overridden at the operation level + properties: + idleTimeout: + description: IdleTimeout Per-route stream idle timeout. "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + timeout: + description: Timeout Maximum time for the entire route (request + to upstream response). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + upstream: + description: Upstream API-level upstream configuration + properties: + main: + description: Main Upstream backend configuration for production + traffic + properties: + hostRewrite: + description: |- + HostRewrite controls how the Host header is handled when routing to the upstream. + "auto" lets Envoy rewrite the Host header to the upstream cluster host; "manual" + disables automatic rewriting so the incoming Host header is preserved. When unset, + the gateway-controller defaults to "auto". + enum: + - auto + - manual + type: string + ref: + description: Ref Name of a predefined upstreamDefinition to + route through. + type: string + url: + description: Url Direct backend service URL (may include path + prefix like /api/v2) + pattern: ^https?://[a-zA-Z0-9\-._~:/?#\[\]@!$&'()*+,;=%]+$ + type: string + type: object + x-kubernetes-validations: + - message: exactly one of url or ref must be set + rule: has(self.url) != has(self.ref) + sandbox: + description: Sandbox Upstream backend configuration for sandbox/testing + traffic + properties: + hostRewrite: + description: |- + HostRewrite controls how the Host header is handled when routing to the upstream. + "auto" lets Envoy rewrite the Host header to the upstream cluster host; "manual" + disables automatic rewriting so the incoming Host header is preserved. When unset, + the gateway-controller defaults to "auto". + enum: + - auto + - manual + type: string + ref: + description: Ref Name of a predefined upstreamDefinition to + route through. + type: string + url: + description: Url Direct backend service URL (may include path + prefix like /api/v2) + pattern: ^https?://[a-zA-Z0-9\-._~:/?#\[\]@!$&'()*+,;=%]+$ + type: string + type: object + x-kubernetes-validations: + - message: exactly one of url or ref must be set + rule: has(self.url) != has(self.ref) + required: + - main + type: object + upstreamDefinitions: + description: |- + UpstreamDefinitions is the list of reusable upstream definitions (with optional connect + timeout and weighted load-balancing targets) that upstream.ref and the dynamic-endpoint + policy can reference. + items: + description: |- + UpstreamDefinition is a reusable upstream configuration with an optional connect timeout and + one or more weighted load-balancing targets. Referenced from an upstream via its `ref` field + and by the dynamic-endpoint policy. Shared by RestApi, LLM Provider, and MCP; mirrors the + management-API UpstreamDefinition schema. + properties: + basePath: + description: |- + BasePath Base path prefix prepended to all requests routed through this upstream (e.g. /api/v2). + Must start with "/" and must not end with "/". Omit for root ("/"). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ + type: string + name: + description: |- + Name Unique identifier for this upstream definition (referenced by upstream.ref or the + dynamic-endpoint policy). + maxLength: 100 + minLength: 1 + pattern: ^[a-zA-Z0-9\-_]+$ + type: string + timeout: + description: Timeout Optional timeout configuration for this + upstream (connect timeout). + properties: + connect: + description: Connect Connection-establishment timeout duration + (e.g. "5s", "500ms"). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + upstreams: + description: Upstreams List of backend targets with optional + weights for load balancing. + items: + description: WeightedUpstream is a single backend target within + an UpstreamDefinition. + properties: + url: + description: Url Backend URL (host and port; no path) + type: string + weight: + description: |- + Weight Relative weight for load balancing across multiple upstream targets. Reserved for + future multi-target load balancing; not applied yet (only the first target is currently used). + maximum: 100 + minimum: 0 + type: integer + required: + - url + type: object + minItems: 1 + type: array + required: + - name + - upstreams + type: object + type: array + version: + description: Version Semantic version of the API + pattern: ^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ + type: string + vhosts: + description: Vhosts Custom virtual hosts/domains for the API + properties: + main: + description: |- + Main Custom virtual host(s)/domain(s) for production traffic. One or more hostnames separated + by ";" — each serves the main upstream (e.g. when an HTTPRoute attaches to multiple listeners + with distinct hostnames). The first entry is the primary vhost. + type: string + sandbox: + description: Sandbox Custom virtual host/domain for sandbox traffic + type: string + required: + - main + type: object + required: + - context + - displayName + - operations + - upstream + - version + type: object + status: + description: RestApiStatus defines the observed state of RestApi + properties: + conditions: + description: Conditions represent the latest available observations + of the API's state + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated + format: date-time + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} + - name: v1alpha1 + schema: + openAPIV3Schema: + description: RestApi is the Schema for the restapis API + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: APIConfigData defines model for APIConfigData. + properties: + context: + description: Context Base path for all API routes (must start with + /, no trailing slash; "/" denotes the root context) + pattern: ^/([a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/])?$ + type: string + displayName: + description: DisplayName Human-readable API name (must be URL-friendly + - only letters, numbers, spaces, hyphens, underscores, and dots + allowed) + pattern: ^[a-zA-Z0-9\s\-_.]+$ + type: string + operations: + description: Operations List of HTTP operations/routes + items: + description: |- + Operation defines model for Operation. + An operation is matched either by the simple top-level method+path fields or by the richer + Match block (method + path + headers). When Match is set it is authoritative and the + top-level Method/Path are ignored. Exactly one form must be provided. + properties: + match: + description: Match Request matching criteria for the operation. + Extensible with query params, cookies, etc. + properties: + headers: + description: Headers ANDed header matchers applied before + routing to this operation. + items: + description: OperationHeaderMatch mirrors Gateway API + HTTPHeaderMatch for Envoy route selection. + properties: + name: + description: Name Header name (case-insensitive) + type: string + type: + description: Type Match type (Exact or RegularExpression) + enum: + - Exact + - RegularExpression + type: string + value: + description: Value Header value to match + type: string + required: + - name + - value + type: object + type: array + method: + description: Method HTTP method + enum: + - GET + - POST + - PUT + - PATCH + - DELETE + - HEAD + - OPTIONS + type: string + path: + description: Path Path match criteria + properties: + type: + description: Type How the path is matched (Exact or + PathPrefix). Defaults to Exact when omitted. + enum: + - Exact + - PathPrefix + type: string + value: + description: Value Route path with optional {param} + placeholders + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/{}\[\]]*$ + type: string + required: + - value + type: object + required: + - method + - path + type: object + method: + description: Method HTTP method (simple form; ignored when Match + is set). + enum: + - GET + - POST + - PUT + - PATCH + - DELETE + - HEAD + - OPTIONS + type: string + path: + description: Path Route path with optional {param} placeholders + (simple form; ignored when Match is set). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/{}\[\]]*$ + type: string + policies: + description: Policies List of policies applied only to this + operation (overrides or adds to API-level policies) + items: + description: Policy defines a policy attachment as embedded + in RestApi or APIConfigData. + properties: + executionCondition: + description: ExecutionCondition Expression controlling + conditional execution of the policy + type: string + name: + description: Name Name of the policy + type: string + params: + description: Params Arbitrary parameters for the policy + (free-form key/value structure) + x-kubernetes-preserve-unknown-fields: true + version: + description: Version Semantic version of the policy (for + example, v1) + pattern: ^v\d+$ + type: string + required: + - name + - version + type: object + type: array + resilience: + description: Resilience Operation-level backend/route timeout + configuration (overrides API-level) + properties: + idleTimeout: + description: IdleTimeout Per-route stream idle timeout. + "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + timeout: + description: Timeout Maximum time for the entire route (request + to upstream response). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + type: object + x-kubernetes-validations: + - message: operation must set both method and path, or set match + rule: (has(self.method) && has(self.path)) || has(self.match) + minItems: 1 + type: array + policies: + description: Policies List of API-level policies applied to all operations + unless overridden + items: + description: Policy defines a policy attachment as embedded in RestApi + or APIConfigData. + properties: + executionCondition: + description: ExecutionCondition Expression controlling conditional + execution of the policy + type: string + name: + description: Name Name of the policy + type: string + params: + description: Params Arbitrary parameters for the policy (free-form + key/value structure) + x-kubernetes-preserve-unknown-fields: true + version: + description: Version Semantic version of the policy (for example, + v1) + pattern: ^v\d+$ + type: string + required: + - name + - version + type: object + type: array + resilience: + description: |- + Resilience API-level backend/route timeout configuration applied to all operations + unless overridden at the operation level + properties: + idleTimeout: + description: IdleTimeout Per-route stream idle timeout. "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + timeout: + description: Timeout Maximum time for the entire route (request + to upstream response). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + upstream: + description: Upstream API-level upstream configuration + properties: + main: + description: Main Upstream backend configuration for production + traffic + properties: + hostRewrite: + description: |- + HostRewrite controls how the Host header is handled when routing to the upstream. + "auto" lets Envoy rewrite the Host header to the upstream cluster host; "manual" + disables automatic rewriting so the incoming Host header is preserved. When unset, + the gateway-controller defaults to "auto". + enum: + - auto + - manual + type: string + ref: + description: Ref Name of a predefined upstreamDefinition to + route through. + type: string + url: + description: Url Direct backend service URL (may include path + prefix like /api/v2) + pattern: ^https?://[a-zA-Z0-9\-._~:/?#\[\]@!$&'()*+,;=%]+$ + type: string + type: object + x-kubernetes-validations: + - message: exactly one of url or ref must be set + rule: has(self.url) != has(self.ref) + sandbox: + description: Sandbox Upstream backend configuration for sandbox/testing + traffic + properties: + hostRewrite: + description: |- + HostRewrite controls how the Host header is handled when routing to the upstream. + "auto" lets Envoy rewrite the Host header to the upstream cluster host; "manual" + disables automatic rewriting so the incoming Host header is preserved. When unset, + the gateway-controller defaults to "auto". + enum: + - auto + - manual + type: string + ref: + description: Ref Name of a predefined upstreamDefinition to + route through. + type: string + url: + description: Url Direct backend service URL (may include path + prefix like /api/v2) + pattern: ^https?://[a-zA-Z0-9\-._~:/?#\[\]@!$&'()*+,;=%]+$ + type: string + type: object + x-kubernetes-validations: + - message: exactly one of url or ref must be set + rule: has(self.url) != has(self.ref) + required: + - main + type: object + upstreamDefinitions: + description: |- + UpstreamDefinitions is the list of reusable upstream definitions (with optional connect + timeout and weighted load-balancing targets) that upstream.ref and the dynamic-endpoint + policy can reference. + items: + description: |- + UpstreamDefinition is a reusable upstream configuration with an optional connect timeout and + one or more weighted load-balancing targets. Referenced from an upstream via its `ref` field + and by the dynamic-endpoint policy. Shared by RestApi, LLM Provider, and MCP; mirrors the + management-API UpstreamDefinition schema. + properties: + basePath: + description: |- + BasePath Base path prefix prepended to all requests routed through this upstream (e.g. /api/v2). + Must start with "/" and must not end with "/". Omit for root ("/"). + pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ + type: string + name: + description: |- + Name Unique identifier for this upstream definition (referenced by upstream.ref or the + dynamic-endpoint policy). + maxLength: 100 + minLength: 1 + pattern: ^[a-zA-Z0-9\-_]+$ + type: string + timeout: + description: Timeout Optional timeout configuration for this + upstream (connect timeout). + properties: + connect: + description: Connect Connection-establishment timeout duration + (e.g. "5s", "500ms"). "0s" disables. + pattern: ^\d+(\.\d+)?(ms|s|m|h)$ + type: string + type: object + upstreams: + description: Upstreams List of backend targets with optional + weights for load balancing. + items: + description: WeightedUpstream is a single backend target within + an UpstreamDefinition. + properties: + url: + description: Url Backend URL (host and port; no path) + type: string + weight: + description: |- + Weight Relative weight for load balancing across multiple upstream targets. Reserved for + future multi-target load balancing; not applied yet (only the first target is currently used). + maximum: 100 + minimum: 0 + type: integer + required: + - url + type: object + minItems: 1 + type: array + required: + - name + - upstreams + type: object + type: array + version: + description: Version Semantic version of the API + pattern: ^v?([0-9]+)(\.[0-9]+)?(\.[0-9]+)?(-[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$ + type: string + vhosts: + description: Vhosts Custom virtual hosts/domains for the API + properties: + main: + description: |- + Main Custom virtual host(s)/domain(s) for production traffic. One or more hostnames separated + by ";" — each serves the main upstream (e.g. when an HTTPRoute attaches to multiple listeners + with distinct hostnames). The first entry is the primary vhost. + type: string + sandbox: + description: Sandbox Custom virtual host/domain for sandbox traffic + type: string + required: + - main + type: object + required: + - context + - displayName + - operations + - upstream + - version + type: object + status: + description: RestApiStatus defines the observed state of RestApi + properties: + conditions: + description: Conditions represent the latest available observations + of the API's state + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated + format: date-time + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_subscriptionplans.yaml b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_subscriptionplans.yaml similarity index 51% rename from kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_subscriptionplans.yaml rename to kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_subscriptionplans.yaml index b09213cfd6..00ecadf155 100644 --- a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_subscriptionplans.yaml +++ b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_subscriptionplans.yaml @@ -23,7 +23,7 @@ spec: - jsonPath: .spec.planName name: Plan type: string - name: v1alpha1 + name: v1 schema: openAPIV3Schema: description: SubscriptionPlan is the Schema for the subscriptionplans API. @@ -177,3 +177,164 @@ spec: storage: true subresources: status: {} + - additionalPrinterColumns: + - jsonPath: .status.id + name: Id + type: string + - jsonPath: .spec.planName + name: Plan + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: SubscriptionPlan is the Schema for the subscriptionplans API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + SubscriptionPlanSpec mirrors the management-API SubscriptionPlanCreateRequest + payload. The gateway-controller assigns a UUID id on first POST; the + controller persists it to .status.id and uses it for subsequent + PUT/DELETE. + properties: + billingPlan: + description: BillingPlan is an optional billing plan identifier. + type: string + expiryTime: + description: ExpiryTime is the optional plan expiry. + format: date-time + type: string + planName: + description: PlanName is the human-readable plan name. + type: string + status: + description: |- + Status is the lifecycle state for this plan (active/inactive/etc). + Mirrors the management-API SubscriptionPlanCreateRequest.Status enum. + enum: + - ACTIVE + - INACTIVE + type: string + stopOnQuotaReach: + description: |- + StopOnQuotaReach controls whether traffic is blocked when the quota + is exhausted. + type: boolean + throttleLimitCount: + description: ThrottleLimitCount is the request count limit. + format: int64 + minimum: 0 + type: integer + throttleLimitUnit: + description: ThrottleLimitUnit is the time unit for the throttle window. + enum: + - Day + - Hour + - Min + - Month + type: string + required: + - planName + type: object + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_subscriptions.yaml b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_subscriptions.yaml similarity index 51% rename from kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_subscriptions.yaml rename to kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_subscriptions.yaml index 27cf4f12b9..3746967daf 100644 --- a/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_subscriptions.yaml +++ b/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_subscriptions.yaml @@ -23,7 +23,7 @@ spec: - jsonPath: .spec.apiId name: ApiId type: string - name: v1alpha1 + name: v1 schema: openAPIV3Schema: description: Subscription is the Schema for the subscriptions API. @@ -208,3 +208,195 @@ spec: storage: true subresources: status: {} + - additionalPrinterColumns: + - jsonPath: .status.id + name: Id + type: string + - jsonPath: .spec.apiId + name: ApiId + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: Subscription is the Schema for the subscriptions API. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: |- + SubscriptionSpec mirrors the management-API SubscriptionCreateRequest + payload. The gateway-controller issues a UUID id which the controller + persists to .status.id for subsequent PUT/DELETE. + properties: + apiId: + description: ApiId is the API identifier (deployment id or handle). + type: string + applicationId: + description: ApplicationId is an optional application identifier. + type: string + billingCustomerId: + description: BillingCustomerId is an optional billing customer identifier. + type: string + billingSubscriptionId: + description: BillingSubscriptionId is an optional billing subscription + identifier. + type: string + status: + description: |- + Status is the lifecycle state for this subscription. Mirrors the + management-API SubscriptionCreateRequest.Status enum. + type: string + subscriptionPlanId: + description: |- + SubscriptionPlanId is an optional plan UUID. When the plan is also + managed via SubscriptionPlan CR, set this to the SubscriptionPlan's + .status.id once it has been deployed. + type: string + subscriptionToken: + description: |- + SubscriptionToken is the opaque token used to invoke the API. The + token is sent as plaintext to the gateway which stores only its hash; + inline in the CR or supplied via valueFrom. + properties: + value: + description: |- + Value is the inline plaintext value. Avoid for production use; prefer + ValueFrom so the secret is stored in a Kubernetes Secret. + type: string + valueFrom: + description: |- + ValueFrom selects a key from a Kubernetes Secret in the same namespace + as the owning CR. + properties: + key: + description: The key of the secret to select from. Must be + a valid secret key. + type: string + name: + default: "" + description: |- + Name of the referent. + This field is effectively required, but due to backwards compatibility is + allowed to be empty. Instances of this type with an empty value here are + almost certainly wrong. + More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names + type: string + optional: + description: Specify whether the Secret or its key must be + defined + type: boolean + required: + - key + type: object + x-kubernetes-map-type: atomic + type: object + x-kubernetes-validations: + - message: exactly one of value or valueFrom must be set + rule: has(self.value) != has(self.valueFrom) + required: + - apiId + - subscriptionToken + type: object + status: + description: |- + ResourceStatus carries the controller-managed lifecycle fields shared by + the new management-API CRDs. + + For UUID-keyed kinds (Subscription, SubscriptionPlan, Certificate) the + gateway-controller assigns Id on first deploy; controllers persist it and + use it to address the resource for subsequent update/delete calls. + properties: + conditions: + description: |- + Conditions represent the latest available observations of the + resource's state. The standard types are Accepted and Programmed. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + id: + description: |- + Id is the gateway-issued identifier for UUID-keyed resources. When + set the controller addresses the resource via PUT/DELETE //{id}. + type: string + lastUpdateTime: + description: LastUpdateTime is the last time the status was updated. + format: date-time + type: string + type: object + required: + - spec + type: object + served: true + storage: false + subresources: + status: {} diff --git a/kubernetes/helm/operator-helm-chart/templates/deployment.yaml b/kubernetes/helm/operator-helm-chart/templates/deployment.yaml index 0f8a9ba943..a15c4f2eb6 100644 --- a/kubernetes/helm/operator-helm-chart/templates/deployment.yaml +++ b/kubernetes/helm/operator-helm-chart/templates/deployment.yaml @@ -34,6 +34,12 @@ spec: - name: manager image: {{ include "gateway-operator.image" . | quote }} imagePullPolicy: "{{ .Values.image.pullPolicy }}" + {{- if .Values.webhook.enabled }} + ports: + - name: webhook-server + containerPort: {{ .Values.webhook.port }} + protocol: TCP + {{- end }} {{ if .Values.debug.enabled }} # run under delve in headless mode for remote debugging command: @@ -67,6 +73,10 @@ spec: value: /tmp/helm/config - name: HELM_DATA_HOME value: /tmp/helm/data + {{- if not .Values.webhook.enabled }} + - name: ENABLE_WEBHOOKS + value: "false" + {{- end }} {{ if .Values.debug.enabled }} securityContext: capabilities: @@ -105,6 +115,11 @@ spec: subPath: gateway_values.yaml - name: tmp-volume mountPath: /tmp + {{- if .Values.webhook.enabled }} + - name: webhook-certs + mountPath: /etc/gateway-operator/webhook-certs + readOnly: true + {{- end }} volumes: - name: config configMap: @@ -113,4 +128,9 @@ spec: configMap: name: {{ include "gateway-operator.fullname" . }}-gateway-values - name: tmp-volume - emptyDir: {} \ No newline at end of file + emptyDir: {} + {{- if .Values.webhook.enabled }} + - name: webhook-certs + secret: + secretName: {{ include "gateway-operator.fullname" . }}-webhook-cert + {{- end }} \ No newline at end of file diff --git a/kubernetes/helm/operator-helm-chart/templates/operator-crds.yaml b/kubernetes/helm/operator-helm-chart/templates/operator-crds.yaml new file mode 100644 index 0000000000..3475063644 --- /dev/null +++ b/kubernetes/helm/operator-helm-chart/templates/operator-crds.yaml @@ -0,0 +1,75 @@ +{{/* +Operator CRDs + conversion-webhook serving certificate. + +The CRDs are served at two versions (v1 storage, v1alpha1 served). When the +conversion webhook is enabled a self-signed CA + serving certificate are +generated here (once, reused across upgrades via lookup), published as a TLS +Secret mounted into the operator pod, and the CA is injected into each CRD's +spec.conversion.webhook.clientConfig.caBundle. + +These CRDs live under templates/ (not the Helm crds/ dir) precisely so the +caBundle can be templated in and updated on upgrade. NOTE: an existing install +whose CRDs were previously installed from the chart's crds/ dir must have those +CRDs adopted by Helm (annotate/label with Helm ownership) before upgrading, or +reinstalled — Helm will not overwrite CRDs it does not own. +*/}} +{{- $fullname := include "gateway-operator.fullname" . -}} +{{- $svcName := printf "%s-webhook-service" $fullname -}} +{{- $ns := .Release.Namespace -}} +{{- $secretName := printf "%s-webhook-cert" $fullname -}} +{{- if .Values.webhook.enabled }} +{{- $cn := printf "%s.%s.svc" $svcName $ns -}} +{{- $altNames := list $cn (printf "%s.%s.svc.cluster.local" $svcName $ns) -}} +{{- $days := int .Values.webhook.certValidityDays -}} +{{- $existing := lookup "v1" "Secret" $ns $secretName -}} +{{- $caCrt := "" -}} +{{- $tlsCrt := "" -}} +{{- $tlsKey := "" -}} +{{- if and $existing $existing.data (index $existing.data "ca.crt") -}} +{{- $caCrt = index $existing.data "ca.crt" -}} +{{- $tlsCrt = index $existing.data "tls.crt" -}} +{{- $tlsKey = index $existing.data "tls.key" -}} +{{- else -}} +{{- $ca := genCA (printf "%s-webhook-ca" $fullname) $days -}} +{{- $cert := genSignedCert $cn nil $altNames $days $ca -}} +{{- $caCrt = b64enc $ca.Cert -}} +{{- $tlsCrt = b64enc $cert.Cert -}} +{{- $tlsKey = b64enc $cert.Key -}} +{{- end }} +--- +apiVersion: v1 +kind: Secret +metadata: + name: {{ $secretName }} + namespace: {{ $ns }} + labels: + app.kubernetes.io/name: {{ include "gateway-operator.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +type: kubernetes.io/tls +data: + tls.crt: {{ $tlsCrt }} + tls.key: {{ $tlsKey }} + ca.crt: {{ $caCrt }} +{{- range $path, $_ := .Files.Glob "files/operator-crds/*.yaml" }} +{{- $crd := $.Files.Get $path | fromYaml }} +{{- $_ := set $crd.spec "conversion" (dict + "strategy" "Webhook" + "webhook" (dict + "conversionReviewVersions" (list "v1") + "clientConfig" (dict + "service" (dict "name" $svcName "namespace" $ns "path" "/convert" "port" (int 443)) + "caBundle" $caCrt))) }} +--- +{{ toYaml $crd }} +{{- end }} +{{- else }} +{{/* Webhook disabled: install CRDs with conversion strategy None. Valid only + because the v1alpha1 and v1 schemas are identical. */}} +{{- range $path, $_ := .Files.Glob "files/operator-crds/*.yaml" }} +{{- $crd := $.Files.Get $path | fromYaml }} +{{- $_ := set $crd.spec "conversion" (dict "strategy" "None") }} +--- +{{ toYaml $crd }} +{{- end }} +{{- end }} diff --git a/kubernetes/helm/operator-helm-chart/templates/webhook-service.yaml b/kubernetes/helm/operator-helm-chart/templates/webhook-service.yaml new file mode 100644 index 0000000000..8c607e2eea --- /dev/null +++ b/kubernetes/helm/operator-helm-chart/templates/webhook-service.yaml @@ -0,0 +1,22 @@ +{{- if .Values.webhook.enabled }} +apiVersion: v1 +kind: Service +metadata: + name: {{ include "gateway-operator.fullname" . }}-webhook-service + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "gateway-operator.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + control-plane: controller-manager +spec: + selector: + app.kubernetes.io/name: {{ include "gateway-operator.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + control-plane: controller-manager + ports: + - port: 443 + targetPort: {{ .Values.webhook.port }} + protocol: TCP + name: webhook-server +{{- end }} diff --git a/kubernetes/helm/operator-helm-chart/values.yaml b/kubernetes/helm/operator-helm-chart/values.yaml index 9c132a2814..824c50957d 100644 --- a/kubernetes/helm/operator-helm-chart/values.yaml +++ b/kubernetes/helm/operator-helm-chart/values.yaml @@ -30,6 +30,18 @@ image: tag: "0.8.0" pullPolicy: Always # Uses locally loaded image from nerdctl load +# CRD conversion webhook. The operator CRDs are served at v1 (storage) and +# v1alpha1 (served). When enabled, the chart generates a self-signed serving +# certificate (reused across upgrades) and the CRDs use conversion strategy +# Webhook. When disabled, the CRDs use strategy None (valid because the two +# schemas are identical) and the operator runs with ENABLE_WEBHOOKS=false. +webhook: + enabled: true + # Container port the webhook server listens on (controller-runtime default). + port: 9443 + # Validity of the generated self-signed CA and serving certificate, in days. + certValidityDays: 3650 + serviceAccount: create: true name: controller-manager From 64a7598a39563158ffd2112a5923d2d2741fb3a9 Mon Sep 17 00:00:00 2001 From: Dineth Date: Mon, 20 Jul 2026 15:26:14 +0530 Subject: [PATCH 02/12] Drop live CRD conversion webhook; ship v1 via strategy: None The v1alpha1/v1 schemas are field-identical today (see api/v1alpha1/conversion.go), and the management API's 0.9->1.0 / v1alpha2->v1 bump was a pure version-label change with no schema drift, so a live conversion webhook isn't earning its operational cost yet (cert lifecycle, and coupling CRD read/write availability to operator pod health). Keep the Hub()/ConvertTo()/ConvertFrom() Go types as-is so switching to a real webhook later is a small, isolated change if a genuine breaking schema change is ever planned. - cmd/main.go: remove conversion webhook registration, ENABLE_WEBHOOKS gating, webhook readyz check, and the webhook TLS server/CertDir. - subscriptionplan_controller.go: make plan recovery-by-name reactive (only after the gateway returns 409 on create), matching subscription_controller.go, instead of proactively adopting any gateway-wide plan with a matching (non-unique) planName. - operator-crds.yaml: replace direct CRD-as-template rendering (which breaks `helm upgrade` for any CRD previously installed via the chart's native crds/ directory, since that path never carries Helm's ownership annotations) with a pre-install/pre-upgrade hook ConfigMap + Job that kubectl-applies the CRDs directly, bypassing Helm's ownership tracking entirely. Conversion strategy is now unconditionally None. - crd-manager-rbac.yaml: cluster-scoped RBAC for the apply-crds Job (CRDs aren't namespaced, so this can't ride on the namespace-scoped Role path). - Remove webhook-service.yaml and the webhook.* values/deployment wiring (port, cert volume/mount, ENABLE_WEBHOOKS env). - Chart.yaml: bump version for the CRD packaging/lifecycle change. --- kubernetes/gateway-operator/cmd/main.go | 41 --------- .../controller/subscriptionplan_controller.go | 30 ++++-- .../helm/operator-helm-chart/Chart.yaml | 2 +- .../templates/crd-manager-rbac.yaml | 34 +++++++ .../templates/deployment.yaml | 22 +---- .../templates/operator-crds-apply-job.yaml | 49 ++++++++++ .../templates/operator-crds.yaml | 91 +++++++------------ .../templates/webhook-service.yaml | 22 ----- .../helm/operator-helm-chart/values.yaml | 12 --- 9 files changed, 137 insertions(+), 166 deletions(-) create mode 100644 kubernetes/helm/operator-helm-chart/templates/crd-manager-rbac.yaml create mode 100644 kubernetes/helm/operator-helm-chart/templates/operator-crds-apply-job.yaml delete mode 100644 kubernetes/helm/operator-helm-chart/templates/webhook-service.yaml diff --git a/kubernetes/gateway-operator/cmd/main.go b/kubernetes/gateway-operator/cmd/main.go index 027babfb7f..6b6c49199e 100644 --- a/kubernetes/gateway-operator/cmd/main.go +++ b/kubernetes/gateway-operator/cmd/main.go @@ -34,7 +34,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" - "sigs.k8s.io/controller-runtime/pkg/webhook" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" @@ -127,14 +126,6 @@ func main() { tlsOpts = append(tlsOpts, disableHTTP2) } - // CertDir must match the path where the Helm chart mounts the webhook - // serving-cert Secret (see operator-helm-chart deployment.yaml). It is kept - // off /tmp to avoid nesting under the /tmp emptyDir mount. - webhookServer := webhook.NewServer(webhook.Options{ - TLSOpts: tlsOpts, - CertDir: "/etc/gateway-operator/webhook-certs", - }) - // Parse WATCH_NAMESPACES env var watchNamespaces := os.Getenv("WATCH_NAMESPACES") var defaultNamespaces map[string]cache.Config @@ -159,7 +150,6 @@ func main() { SecureServing: secureMetrics, TLSOpts: tlsOpts, }, - WebhookServer: webhookServer, HealthProbeBindAddress: probeAddr, LeaderElection: enableLeaderElection, LeaderElectionID: "a5e4ae5b.gateway.api-platform.wso2.com", @@ -249,31 +239,6 @@ func main() { os.Exit(1) } } - // Register the CRD conversion webhook for every kind. The v1 types are the - // hub (storage version) and the served v1alpha1 types convert to/from them. - // Guarded by ENABLE_WEBHOOKS so environments without serving certs (e.g. - // envtest) can disable it. NewWebhookManagedBy is generic, so each kind is - // registered explicitly rather than in a loop. - if os.Getenv("ENABLE_WEBHOOKS") != "false" { - registerConversionWebhook := func(kind string, err error) { - if err != nil { - setupLog.Error(err, "unable to create conversion webhook", "kind", kind) - os.Exit(1) - } - } - registerConversionWebhook("RestApi", ctrl.NewWebhookManagedBy(mgr, &apiv1.RestApi{}).Complete()) - registerConversionWebhook("APIGateway", ctrl.NewWebhookManagedBy(mgr, &apiv1.APIGateway{}).Complete()) - registerConversionWebhook("ApiKey", ctrl.NewWebhookManagedBy(mgr, &apiv1.ApiKey{}).Complete()) - registerConversionWebhook("APIPolicy", ctrl.NewWebhookManagedBy(mgr, &apiv1.APIPolicy{}).Complete()) - registerConversionWebhook("Certificate", ctrl.NewWebhookManagedBy(mgr, &apiv1.Certificate{}).Complete()) - registerConversionWebhook("LlmProvider", ctrl.NewWebhookManagedBy(mgr, &apiv1.LlmProvider{}).Complete()) - registerConversionWebhook("LlmProviderTemplate", ctrl.NewWebhookManagedBy(mgr, &apiv1.LlmProviderTemplate{}).Complete()) - registerConversionWebhook("LlmProxy", ctrl.NewWebhookManagedBy(mgr, &apiv1.LlmProxy{}).Complete()) - registerConversionWebhook("ManagedSecret", ctrl.NewWebhookManagedBy(mgr, &apiv1.ManagedSecret{}).Complete()) - registerConversionWebhook("Mcp", ctrl.NewWebhookManagedBy(mgr, &apiv1.Mcp{}).Complete()) - registerConversionWebhook("Subscription", ctrl.NewWebhookManagedBy(mgr, &apiv1.Subscription{}).Complete()) - registerConversionWebhook("SubscriptionPlan", ctrl.NewWebhookManagedBy(mgr, &apiv1.SubscriptionPlan{}).Complete()) - } //+kubebuilder:scaffold:builder if err := mgr.AddHealthzCheck("healthz", healthz.Ping); err != nil { @@ -284,12 +249,6 @@ func main() { setupLog.Error(err, "unable to set up ready check") os.Exit(1) } - if os.Getenv("ENABLE_WEBHOOKS") != "false" { - if err := mgr.AddReadyzCheck("webhook", mgr.GetWebhookServer().StartedChecker()); err != nil { - setupLog.Error(err, "unable to set up webhook readiness check") - os.Exit(1) - } - } setupLog.Info("starting manager") if err := mgr.Start(ctrl.SetupSignalHandler()); err != nil { diff --git a/kubernetes/gateway-operator/internal/controller/subscriptionplan_controller.go b/kubernetes/gateway-operator/internal/controller/subscriptionplan_controller.go index bd62d2e780..2fa8870fa6 100644 --- a/kubernetes/gateway-operator/internal/controller/subscriptionplan_controller.go +++ b/kubernetes/gateway-operator/internal/controller/subscriptionplan_controller.go @@ -18,6 +18,9 @@ package controller import ( "context" + "errors" + "fmt" + "net/http" "time" "go.uber.org/zap" @@ -97,15 +100,6 @@ func (a *subscriptionPlanAdapter) Deploy(ctx context.Context, _ client.Client, g cr := obj.(*apiv1.SubscriptionPlan) if cr.Status.Id == "" { - // Recover when the plan exists in the gateway but status.id was never - // persisted (optimistic-lock / ordering races). Listing by planName - // avoids skipping forever in the "already Programmed" reconcile path. - if recoverID, err := gatewayclient.FindSubscriptionPlanIDByPlanName(ctx, gatewayEndpoint, cr.Spec.PlanName, authFn); err != nil { - return DeployResult{}, err - } else if recoverID != "" { - return DeployResult{Id: recoverID}, nil - } - payload := gatewayclient.SubscriptionPlanCreatePayload{ PlanName: cr.Spec.PlanName, BillingPlan: cr.Spec.BillingPlan, @@ -120,6 +114,24 @@ func (a *subscriptionPlanAdapter) Deploy(ctx context.Context, _ client.Client, g } resp, err := gatewayclient.CreateSubscriptionPlan(ctx, gatewayEndpoint, payload, authFn) if err != nil { + var nr *gatewayclient.NonRetryableError + if errors.As(err, &nr) && nr.StatusCode == http.StatusConflict { + // The gateway itself detected a planName collision. Recover the + // existing plan's id only now, after the server has confirmed a + // real conflict — not proactively by name, since planName is not + // guaranteed unique across namespaces/tenants sharing a gateway. + recoveredID, recErr := gatewayclient.FindSubscriptionPlanIDByPlanName(ctx, gatewayEndpoint, cr.Spec.PlanName, authFn) + if recErr != nil { + return DeployResult{}, recErr + } + if recoveredID != "" { + return DeployResult{Id: recoveredID}, nil + } + return DeployResult{}, &gatewayclient.RetryableError{ + StatusCode: http.StatusConflict, + Err: fmt.Errorf("subscription plan create conflicted but existing id is not yet discoverable; retrying: %w", err), + } + } return DeployResult{}, err } return DeployResult{Id: resp.Id}, nil diff --git a/kubernetes/helm/operator-helm-chart/Chart.yaml b/kubernetes/helm/operator-helm-chart/Chart.yaml index 7b6d567bef..a9c4f2a4e5 100644 --- a/kubernetes/helm/operator-helm-chart/Chart.yaml +++ b/kubernetes/helm/operator-helm-chart/Chart.yaml @@ -2,5 +2,5 @@ apiVersion: v2 name: gateway-operator description: Helm chart to install the Gateway Operator type: application -version: 0.9.0 +version: 0.10.0 appVersion: "0.8.0" \ No newline at end of file diff --git a/kubernetes/helm/operator-helm-chart/templates/crd-manager-rbac.yaml b/kubernetes/helm/operator-helm-chart/templates/crd-manager-rbac.yaml new file mode 100644 index 0000000000..414df975e6 --- /dev/null +++ b/kubernetes/helm/operator-helm-chart/templates/crd-manager-rbac.yaml @@ -0,0 +1,34 @@ +{{/* +CustomResourceDefinitions are cluster-scoped, so the apply-crds hook Job +needs this regardless of whether .Values.watchNamespaces restricts the +operator's own manager-role to a namespaced Role (see role.yaml/clusterrole.yaml). +*/}} +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: {{ include "gateway-operator.fullname" . }}-crd-manager-role + labels: + app.kubernetes.io/name: {{ include "gateway-operator.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +rules: + - apiGroups: ["apiextensions.k8s.io"] + resources: ["customresourcedefinitions"] + verbs: ["get", "list", "watch", "create", "update", "patch"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: {{ include "gateway-operator.fullname" . }}-crd-manager-rolebinding + labels: + app.kubernetes.io/name: {{ include "gateway-operator.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: {{ include "gateway-operator.fullname" . }}-crd-manager-role +subjects: + - kind: ServiceAccount + name: {{ .Values.serviceAccount.name }} + namespace: {{ .Release.Namespace }} diff --git a/kubernetes/helm/operator-helm-chart/templates/deployment.yaml b/kubernetes/helm/operator-helm-chart/templates/deployment.yaml index a15c4f2eb6..0f8a9ba943 100644 --- a/kubernetes/helm/operator-helm-chart/templates/deployment.yaml +++ b/kubernetes/helm/operator-helm-chart/templates/deployment.yaml @@ -34,12 +34,6 @@ spec: - name: manager image: {{ include "gateway-operator.image" . | quote }} imagePullPolicy: "{{ .Values.image.pullPolicy }}" - {{- if .Values.webhook.enabled }} - ports: - - name: webhook-server - containerPort: {{ .Values.webhook.port }} - protocol: TCP - {{- end }} {{ if .Values.debug.enabled }} # run under delve in headless mode for remote debugging command: @@ -73,10 +67,6 @@ spec: value: /tmp/helm/config - name: HELM_DATA_HOME value: /tmp/helm/data - {{- if not .Values.webhook.enabled }} - - name: ENABLE_WEBHOOKS - value: "false" - {{- end }} {{ if .Values.debug.enabled }} securityContext: capabilities: @@ -115,11 +105,6 @@ spec: subPath: gateway_values.yaml - name: tmp-volume mountPath: /tmp - {{- if .Values.webhook.enabled }} - - name: webhook-certs - mountPath: /etc/gateway-operator/webhook-certs - readOnly: true - {{- end }} volumes: - name: config configMap: @@ -128,9 +113,4 @@ spec: configMap: name: {{ include "gateway-operator.fullname" . }}-gateway-values - name: tmp-volume - emptyDir: {} - {{- if .Values.webhook.enabled }} - - name: webhook-certs - secret: - secretName: {{ include "gateway-operator.fullname" . }}-webhook-cert - {{- end }} \ No newline at end of file + emptyDir: {} \ No newline at end of file diff --git a/kubernetes/helm/operator-helm-chart/templates/operator-crds-apply-job.yaml b/kubernetes/helm/operator-helm-chart/templates/operator-crds-apply-job.yaml new file mode 100644 index 0000000000..fef56baa0f --- /dev/null +++ b/kubernetes/helm/operator-helm-chart/templates/operator-crds-apply-job.yaml @@ -0,0 +1,49 @@ +{{/* +Applies the CRDs staged in the operator-crds ConfigMap directly via kubectl, +bypassing Helm's own resource-ownership tracking (see the comment in +operator-crds.yaml for why). Runs before every install and upgrade so +existing clusters — including ones whose CRDs came from an older chart +version's crds/ directory — always end up with the current CRD content. +*/}} +apiVersion: batch/v1 +kind: Job +metadata: + name: "{{ include "gateway-operator.fullname" . }}-apply-crds" + namespace: {{ .Release.Namespace }} + labels: + app.kubernetes.io/name: {{ include "gateway-operator.name" . }} + app.kubernetes.io/instance: {{ .Release.Name }} + app.kubernetes.io/managed-by: {{ .Release.Service }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "1" + "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded +spec: + template: + metadata: + name: "{{ include "gateway-operator.fullname" . }}-apply-crds" + spec: + serviceAccountName: {{ .Values.serviceAccount.name }} + restartPolicy: Never + containers: + - name: apply-crds + image: "{{ .Values.cleanupJob.image.repository }}:{{ .Values.cleanupJob.image.tag }}" + imagePullPolicy: {{ .Values.cleanupJob.image.pullPolicy }} + command: + - /bin/sh + - -c + - | + set -e + echo "Applying gateway-operator CRDs..." + for f in /crds/*.yaml; do + echo " kubectl apply -f $f" + kubectl apply -f "$f" + done + echo "CRDs applied." + volumeMounts: + - name: crds + mountPath: /crds + volumes: + - name: crds + configMap: + name: {{ include "gateway-operator.fullname" . }}-operator-crds diff --git a/kubernetes/helm/operator-helm-chart/templates/operator-crds.yaml b/kubernetes/helm/operator-helm-chart/templates/operator-crds.yaml index 3475063644..a4514d0f3b 100644 --- a/kubernetes/helm/operator-helm-chart/templates/operator-crds.yaml +++ b/kubernetes/helm/operator-helm-chart/templates/operator-crds.yaml @@ -1,75 +1,46 @@ {{/* -Operator CRDs + conversion-webhook serving certificate. +Operator CRDs, staged as a ConfigMap for operator-crds-apply-job.yaml to +kubectl-apply. -The CRDs are served at two versions (v1 storage, v1alpha1 served). When the -conversion webhook is enabled a self-signed CA + serving certificate are -generated here (once, reused across upgrades via lookup), published as a TLS -Secret mounted into the operator pod, and the CA is injected into each CRD's -spec.conversion.webhook.clientConfig.caBundle. +The CRDs are served at two versions (v1 storage, v1alpha1 served) with +conversion strategy None: the v1alpha1 and v1 schemas are field-identical +(the promotion changed only the version label, see api/v1alpha1/conversion.go), +so no real field transformation is needed. If a future change to these types +actually requires per-field conversion, revisit this in favor of a real +conversion webhook (the Hub()/ConvertTo()/ConvertFrom() Go types are already +in place for that — see kubernetes/gateway-operator/api/v1alpha1/conversion.go). -These CRDs live under templates/ (not the Helm crds/ dir) precisely so the -caBundle can be templated in and updated on upgrade. NOTE: an existing install -whose CRDs were previously installed from the chart's crds/ dir must have those -CRDs adopted by Helm (annotate/label with Helm ownership) before upgrading, or -reinstalled — Helm will not overwrite CRDs it does not own. +This ConfigMap (and the Job that applies it) exist instead of rendering the +CRDs directly as ordinary Helm-tracked resources, and instead of Helm's +built-in crds/ directory, because: + - crds/ is only applied on `helm install`, never updated on `helm upgrade`, + so an existing install would never receive the new v1 version. + - Rendering the CRDs as normal templated resources would fail on both + fresh installs and upgrades for any CRD that already exists from an + older chart's crds/ directory, since crds/-installed objects never carry + Helm's ownership annotations ("resource already exists and is not + managed by this release"). +kubectl apply (in operator-crds-apply-job.yaml) doesn't check Helm's +ownership bookkeeping at all, so it works uniformly for fresh installs and +upgrades regardless of how (or whether) the CRD previously existed. */}} -{{- $fullname := include "gateway-operator.fullname" . -}} -{{- $svcName := printf "%s-webhook-service" $fullname -}} -{{- $ns := .Release.Namespace -}} -{{- $secretName := printf "%s-webhook-cert" $fullname -}} -{{- if .Values.webhook.enabled }} -{{- $cn := printf "%s.%s.svc" $svcName $ns -}} -{{- $altNames := list $cn (printf "%s.%s.svc.cluster.local" $svcName $ns) -}} -{{- $days := int .Values.webhook.certValidityDays -}} -{{- $existing := lookup "v1" "Secret" $ns $secretName -}} -{{- $caCrt := "" -}} -{{- $tlsCrt := "" -}} -{{- $tlsKey := "" -}} -{{- if and $existing $existing.data (index $existing.data "ca.crt") -}} -{{- $caCrt = index $existing.data "ca.crt" -}} -{{- $tlsCrt = index $existing.data "tls.crt" -}} -{{- $tlsKey = index $existing.data "tls.key" -}} -{{- else -}} -{{- $ca := genCA (printf "%s-webhook-ca" $fullname) $days -}} -{{- $cert := genSignedCert $cn nil $altNames $days $ca -}} -{{- $caCrt = b64enc $ca.Cert -}} -{{- $tlsCrt = b64enc $cert.Cert -}} -{{- $tlsKey = b64enc $cert.Key -}} -{{- end }} ---- apiVersion: v1 -kind: Secret +kind: ConfigMap metadata: - name: {{ $secretName }} - namespace: {{ $ns }} + name: {{ include "gateway-operator.fullname" . }}-operator-crds + namespace: {{ .Release.Namespace }} labels: app.kubernetes.io/name: {{ include "gateway-operator.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} -type: kubernetes.io/tls + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "0" + "helm.sh/hook-delete-policy": before-hook-creation data: - tls.crt: {{ $tlsCrt }} - tls.key: {{ $tlsKey }} - ca.crt: {{ $caCrt }} -{{- range $path, $_ := .Files.Glob "files/operator-crds/*.yaml" }} -{{- $crd := $.Files.Get $path | fromYaml }} -{{- $_ := set $crd.spec "conversion" (dict - "strategy" "Webhook" - "webhook" (dict - "conversionReviewVersions" (list "v1") - "clientConfig" (dict - "service" (dict "name" $svcName "namespace" $ns "path" "/convert" "port" (int 443)) - "caBundle" $caCrt))) }} ---- -{{ toYaml $crd }} -{{- end }} -{{- else }} -{{/* Webhook disabled: install CRDs with conversion strategy None. Valid only - because the v1alpha1 and v1 schemas are identical. */}} {{- range $path, $_ := .Files.Glob "files/operator-crds/*.yaml" }} {{- $crd := $.Files.Get $path | fromYaml }} {{- $_ := set $crd.spec "conversion" (dict "strategy" "None") }} ---- -{{ toYaml $crd }} -{{- end }} + {{ base $path }}: | +{{ toYaml $crd | indent 4 }} {{- end }} diff --git a/kubernetes/helm/operator-helm-chart/templates/webhook-service.yaml b/kubernetes/helm/operator-helm-chart/templates/webhook-service.yaml deleted file mode 100644 index 8c607e2eea..0000000000 --- a/kubernetes/helm/operator-helm-chart/templates/webhook-service.yaml +++ /dev/null @@ -1,22 +0,0 @@ -{{- if .Values.webhook.enabled }} -apiVersion: v1 -kind: Service -metadata: - name: {{ include "gateway-operator.fullname" . }}-webhook-service - namespace: {{ .Release.Namespace }} - labels: - app.kubernetes.io/name: {{ include "gateway-operator.name" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - control-plane: controller-manager -spec: - selector: - app.kubernetes.io/name: {{ include "gateway-operator.name" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - control-plane: controller-manager - ports: - - port: 443 - targetPort: {{ .Values.webhook.port }} - protocol: TCP - name: webhook-server -{{- end }} diff --git a/kubernetes/helm/operator-helm-chart/values.yaml b/kubernetes/helm/operator-helm-chart/values.yaml index 824c50957d..9c132a2814 100644 --- a/kubernetes/helm/operator-helm-chart/values.yaml +++ b/kubernetes/helm/operator-helm-chart/values.yaml @@ -30,18 +30,6 @@ image: tag: "0.8.0" pullPolicy: Always # Uses locally loaded image from nerdctl load -# CRD conversion webhook. The operator CRDs are served at v1 (storage) and -# v1alpha1 (served). When enabled, the chart generates a self-signed serving -# certificate (reused across upgrades) and the CRDs use conversion strategy -# Webhook. When disabled, the CRDs use strategy None (valid because the two -# schemas are identical) and the operator runs with ENABLE_WEBHOOKS=false. -webhook: - enabled: true - # Container port the webhook server listens on (controller-runtime default). - port: 9443 - # Validity of the generated self-signed CA and serving certificate, in days. - certValidityDays: 3650 - serviceAccount: create: true name: controller-manager From 6631c49217843b9908ddbb8523fe4fddd0e7db69 Mon Sep 17 00:00:00 2001 From: Dineth Date: Mon, 20 Jul 2026 16:44:27 +0530 Subject: [PATCH 03/12] Fix RBAC hook-ordering bug in apply-crds Job (found by live test) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit crd-manager-rbac.yaml was a plain (non-hook) resource, so on helm upgrade it only applied AFTER pre-install/pre-upgrade hooks ran — the apply-crds Job (a pre-upgrade hook) tried to use a ClusterRoleBinding that didn't exist yet on the very upgrade that introduces it, failing with: customresourcedefinitions.apiextensions.k8s.io "..." is forbidden: User "system:serviceaccount::controller-manager" cannot get resource "customresourcedefinitions" in API group "apiextensions.k8s.io" at the cluster scope Reproduced by installing the pre-PR chart (CRDs in crds/, v1alpha1 only) then helm upgrade --install to this chart, against a real rancher-desktop cluster. Fix: make the ClusterRole/ClusterRoleBinding pre-install,pre-upgrade hooks too, weighted before the ConfigMap (0) and apply-crds Job (1). Re-ran the same install-old/upgrade-to-new repro after the fix: upgrade succeeded, apply-crds Job completed and self-cleaned, all 12 CRDs ended up served at v1+v1alpha1 with conversion strategy None and v1 as storage, and a v1alpha1 SubscriptionPlan CR applied post-upgrade reconciled correctly. --- .../templates/crd-manager-rbac.yaml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/kubernetes/helm/operator-helm-chart/templates/crd-manager-rbac.yaml b/kubernetes/helm/operator-helm-chart/templates/crd-manager-rbac.yaml index 414df975e6..0438b8efdc 100644 --- a/kubernetes/helm/operator-helm-chart/templates/crd-manager-rbac.yaml +++ b/kubernetes/helm/operator-helm-chart/templates/crd-manager-rbac.yaml @@ -2,6 +2,12 @@ CustomResourceDefinitions are cluster-scoped, so the apply-crds hook Job needs this regardless of whether .Values.watchNamespaces restricts the operator's own manager-role to a namespaced Role (see role.yaml/clusterrole.yaml). + +This must itself be a pre-install,pre-upgrade hook (weighted before the +operator-crds ConfigMap and apply-crds Job) — normal, non-hook resources are +only applied AFTER pre-install/pre-upgrade hooks run, so on `helm upgrade` a +plain ClusterRoleBinding here would not exist yet when the hook Job tries to +use it. */}} apiVersion: rbac.authorization.k8s.io/v1 kind: ClusterRole @@ -11,6 +17,9 @@ metadata: app.kubernetes.io/name: {{ include "gateway-operator.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "-1" rules: - apiGroups: ["apiextensions.k8s.io"] resources: ["customresourcedefinitions"] @@ -24,6 +33,9 @@ metadata: app.kubernetes.io/name: {{ include "gateway-operator.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} + annotations: + "helm.sh/hook": pre-install,pre-upgrade + "helm.sh/hook-weight": "-1" roleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole From d777c094fd35cf07c3ef444bed7b446e5f522340 Mon Sep 17 00:00:00 2001 From: Dineth Date: Tue, 21 Jul 2026 08:56:29 +0530 Subject: [PATCH 04/12] refactor: Remove webhook configuration from RestApi and APIGateway CRDs; add schema identity test --- kubernetes/gateway-operator/PROJECT | 6 - .../api/v1alpha1/crd_schema_identity_test.go | 167 ++++++++++++++++++ .../templates/operator-crds-apply-job.yaml | 4 +- 3 files changed, 169 insertions(+), 8 deletions(-) create mode 100644 kubernetes/gateway-operator/api/v1alpha1/crd_schema_identity_test.go diff --git a/kubernetes/gateway-operator/PROJECT b/kubernetes/gateway-operator/PROJECT index 5e369fe476..82102c211e 100644 --- a/kubernetes/gateway-operator/PROJECT +++ b/kubernetes/gateway-operator/PROJECT @@ -16,9 +16,6 @@ resources: kind: RestApi path: github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1 version: v1 - webhooks: - conversion: true - webhookVersion: v1 - api: crdVersion: v1 namespaced: true @@ -34,9 +31,6 @@ resources: kind: APIGateway path: github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1 version: v1 - webhooks: - conversion: true - webhookVersion: v1 - api: crdVersion: v1 namespaced: true diff --git a/kubernetes/gateway-operator/api/v1alpha1/crd_schema_identity_test.go b/kubernetes/gateway-operator/api/v1alpha1/crd_schema_identity_test.go new file mode 100644 index 0000000000..f94f7b90d5 --- /dev/null +++ b/kubernetes/gateway-operator/api/v1alpha1/crd_schema_identity_test.go @@ -0,0 +1,167 @@ +/* +Copyright 2026. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1alpha1 + +import ( + "encoding/json" + "os" + "path/filepath" + "reflect" + "runtime" + "strconv" + "strings" + "testing" + + apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "sigs.k8s.io/yaml" +) + +// TestCRDVersionSchemasIdentical enforces the invariant that every served +// version of each CRD shares an identical OpenAPI schema. +// +// The operator ships its CRDs with spec.conversion.strategy = None (injected in +// kubernetes/helm/operator-helm-chart/templates/operator-crds.yaml). "None" +// performs NO field transformation between versions — the API server only +// relabels apiVersion on read/write. That is safe ONLY while the v1 (storage) +// and v1alpha1 (served) schemas are equivalent; any divergence would silently +// drop or corrupt fields at the storage boundary, with no conversion webhook to +// catch it (see conversion.go — the Hub()/ConvertTo/ConvertFrom scaffolding is +// deliberately not wired to a live webhook while the schemas match). +// +// This guard fails the moment the two versions drift, so an accidental edit to +// one version's Go types (without mirroring it in the other) cannot ship. +// +// When the versions are INTENTIONALLY diverged in the future, this test is the +// signal to switch models: delete it, flip strategy: None -> Webhook, wire +// SetupWebhookWithManager in cmd/main.go, replace the JSON round-trip in +// conversion.go with explicit per-field mapping, and rely on round-trip +// conversion tests instead. +func TestCRDVersionSchemasIdentical(t *testing.T) { + dir := crdBasesDir(t) + paths, err := filepath.Glob(filepath.Join(dir, "*.yaml")) + if err != nil { + t.Fatalf("globbing CRD dir %s: %v", dir, err) + } + if len(paths) == 0 { + t.Fatalf("no CRD YAML files found in %s (run `make manifests`?)", dir) + } + + for _, path := range paths { + path := path + t.Run(filepath.Base(path), func(t *testing.T) { + data, err := os.ReadFile(path) + if err != nil { + t.Fatalf("read %s: %v", path, err) + } + var crd apiextensionsv1.CustomResourceDefinition + if err := yaml.Unmarshal(data, &crd); err != nil { + t.Fatalf("unmarshal %s: %v", path, err) + } + + versions := crd.Spec.Versions + if len(versions) < 2 { + t.Skipf("%s serves a single version; nothing to compare", crd.Name) + } + + ref := storageVersion(versions) + if ref.Schema == nil || ref.Schema.OpenAPIV3Schema == nil { + t.Fatalf("storage version %q of %s has no schema", ref.Name, crd.Name) + } + + for _, v := range versions { + if v.Name == ref.Name { + continue + } + if v.Schema == nil || v.Schema.OpenAPIV3Schema == nil { + t.Fatalf("version %q of %s has no schema", v.Name, crd.Name) + } + if !reflect.DeepEqual(ref.Schema.OpenAPIV3Schema, v.Schema.OpenAPIV3Schema) { + t.Errorf("schema for version %q differs from storage version %q of %s.\n"+ + "conversion strategy None requires identical schemas — mirror the change "+ + "in both api/v1 and api/v1alpha1 (and re-run `make manifests`), or move to a "+ + "real conversion webhook (see this test's doc comment).\n%s", + v.Name, ref.Name, crd.Name, + schemaDiff(ref.Schema.OpenAPIV3Schema, v.Schema.OpenAPIV3Schema)) + } + } + }) + } +} + +// storageVersion returns the version flagged storage:true, falling back to the +// first entry (which should never happen for a well-formed multi-version CRD). +func storageVersion(vs []apiextensionsv1.CustomResourceDefinitionVersion) apiextensionsv1.CustomResourceDefinitionVersion { + for _, v := range vs { + if v.Storage { + return v + } + } + return vs[0] +} + +// crdBasesDir resolves config/crd/bases relative to this test file, so the test +// passes regardless of the working directory `go test` is invoked from. +func crdBasesDir(t *testing.T) string { + t.Helper() + _, thisFile, _, ok := runtime.Caller(0) + if !ok { + t.Fatal("cannot determine test file location") + } + // api/v1alpha1/ -> ../../config/crd/bases + return filepath.Join(filepath.Dir(thisFile), "..", "..", "config", "crd", "bases") +} + +// schemaDiff renders the first divergence between two schemas as indented JSON, +// so a failure points at the offending field instead of dumping the whole tree. +func schemaDiff(a, b any) string { + aj, _ := json.MarshalIndent(a, "", " ") + bj, _ := json.MarshalIndent(b, "", " ") + al := strings.Split(string(aj), "\n") + bl := strings.Split(string(bj), "\n") + + n := min(len(al), len(bl)) + for i := 0; i < n; i++ { + if al[i] != bl[i] { + return renderContext(al, bl, i) + } + } + if len(al) != len(bl) { + return renderContext(al, bl, n) + } + // Equal as JSON but not under reflect.DeepEqual (e.g. nil vs empty slice). + // Both serialize identically, so the drift is not field-content — flag it plainly. + return "(schemas differ only in nil-vs-empty representation; check the Go types)" +} + +func renderContext(al, bl []string, i int) string { + const ctx = 4 + start := i - ctx + if start < 0 { + start = 0 + } + var sb strings.Builder + sb.WriteString("first divergence near line " + strconv.Itoa(i+1) + ":\n") + sb.WriteString("--- storage version\n") + for j := start; j <= i && j < len(al); j++ { + sb.WriteString(" " + al[j] + "\n") + } + sb.WriteString("+++ other version\n") + for j := start; j <= i && j < len(bl); j++ { + sb.WriteString(" " + bl[j] + "\n") + } + return sb.String() +} diff --git a/kubernetes/helm/operator-helm-chart/templates/operator-crds-apply-job.yaml b/kubernetes/helm/operator-helm-chart/templates/operator-crds-apply-job.yaml index fef56baa0f..4472d79486 100644 --- a/kubernetes/helm/operator-helm-chart/templates/operator-crds-apply-job.yaml +++ b/kubernetes/helm/operator-helm-chart/templates/operator-crds-apply-job.yaml @@ -36,8 +36,8 @@ spec: set -e echo "Applying gateway-operator CRDs..." for f in /crds/*.yaml; do - echo " kubectl apply -f $f" - kubectl apply -f "$f" + echo " kubectl apply --server-side -f $f" + kubectl apply --server-side --force-conflicts -f "$f" done echo "CRDs applied." volumeMounts: From 315649fe43517709c401b373b6304a836c2bbeb7 Mon Sep 17 00:00:00 2001 From: Dineth Date: Tue, 21 Jul 2026 09:23:18 +0530 Subject: [PATCH 05/12] fix: Improve subscription plan deployment recovery logic --- .../controller/subscriptionplan_controller.go | 30 ++++++------------- 1 file changed, 9 insertions(+), 21 deletions(-) diff --git a/kubernetes/gateway-operator/internal/controller/subscriptionplan_controller.go b/kubernetes/gateway-operator/internal/controller/subscriptionplan_controller.go index 2fa8870fa6..bd62d2e780 100644 --- a/kubernetes/gateway-operator/internal/controller/subscriptionplan_controller.go +++ b/kubernetes/gateway-operator/internal/controller/subscriptionplan_controller.go @@ -18,9 +18,6 @@ package controller import ( "context" - "errors" - "fmt" - "net/http" "time" "go.uber.org/zap" @@ -100,6 +97,15 @@ func (a *subscriptionPlanAdapter) Deploy(ctx context.Context, _ client.Client, g cr := obj.(*apiv1.SubscriptionPlan) if cr.Status.Id == "" { + // Recover when the plan exists in the gateway but status.id was never + // persisted (optimistic-lock / ordering races). Listing by planName + // avoids skipping forever in the "already Programmed" reconcile path. + if recoverID, err := gatewayclient.FindSubscriptionPlanIDByPlanName(ctx, gatewayEndpoint, cr.Spec.PlanName, authFn); err != nil { + return DeployResult{}, err + } else if recoverID != "" { + return DeployResult{Id: recoverID}, nil + } + payload := gatewayclient.SubscriptionPlanCreatePayload{ PlanName: cr.Spec.PlanName, BillingPlan: cr.Spec.BillingPlan, @@ -114,24 +120,6 @@ func (a *subscriptionPlanAdapter) Deploy(ctx context.Context, _ client.Client, g } resp, err := gatewayclient.CreateSubscriptionPlan(ctx, gatewayEndpoint, payload, authFn) if err != nil { - var nr *gatewayclient.NonRetryableError - if errors.As(err, &nr) && nr.StatusCode == http.StatusConflict { - // The gateway itself detected a planName collision. Recover the - // existing plan's id only now, after the server has confirmed a - // real conflict — not proactively by name, since planName is not - // guaranteed unique across namespaces/tenants sharing a gateway. - recoveredID, recErr := gatewayclient.FindSubscriptionPlanIDByPlanName(ctx, gatewayEndpoint, cr.Spec.PlanName, authFn) - if recErr != nil { - return DeployResult{}, recErr - } - if recoveredID != "" { - return DeployResult{Id: recoveredID}, nil - } - return DeployResult{}, &gatewayclient.RetryableError{ - StatusCode: http.StatusConflict, - Err: fmt.Errorf("subscription plan create conflicted but existing id is not yet discoverable; retrying: %w", err), - } - } return DeployResult{}, err } return DeployResult{Id: resp.Id}, nil From 2fc0b0c999d5d3327d3c5aa40abf892c9c6213ba Mon Sep 17 00:00:00 2001 From: Dineth Date: Tue, 21 Jul 2026 09:55:28 +0530 Subject: [PATCH 06/12] Revert --- kubernetes/gateway-operator/cmd/main.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/kubernetes/gateway-operator/cmd/main.go b/kubernetes/gateway-operator/cmd/main.go index 6b6c49199e..941a9fa1a8 100644 --- a/kubernetes/gateway-operator/cmd/main.go +++ b/kubernetes/gateway-operator/cmd/main.go @@ -34,6 +34,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/healthz" "sigs.k8s.io/controller-runtime/pkg/log/zap" metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" + "sigs.k8s.io/controller-runtime/pkg/webhook" gatewayv1 "sigs.k8s.io/gateway-api/apis/v1" gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" @@ -126,6 +127,10 @@ func main() { tlsOpts = append(tlsOpts, disableHTTP2) } + webhookServer := webhook.NewServer(webhook.Options{ + TLSOpts: tlsOpts, + }) + // Parse WATCH_NAMESPACES env var watchNamespaces := os.Getenv("WATCH_NAMESPACES") var defaultNamespaces map[string]cache.Config @@ -150,6 +155,7 @@ func main() { SecureServing: secureMetrics, TLSOpts: tlsOpts, }, + WebhookServer: webhookServer, HealthProbeBindAddress: probeAddr, LeaderElection: enableLeaderElection, LeaderElectionID: "a5e4ae5b.gateway.api-platform.wso2.com", From 46dc75161ae981917b3e9dfee20ff940b9bcfa90 Mon Sep 17 00:00:00 2001 From: Dineth Date: Tue, 21 Jul 2026 11:21:38 +0530 Subject: [PATCH 07/12] Enhance gateway configuration with registry credentials and reconciliation settings --- .../gateway-operator/config/config.yaml | 31 +++++++++++++++---- .../templates/configmap.yaml | 15 +++++++-- .../helm/operator-helm-chart/values.yaml | 22 +++++++++++-- 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/kubernetes/gateway-operator/config/config.yaml b/kubernetes/gateway-operator/config/config.yaml index 1554635466..d69d4ec194 100644 --- a/kubernetes/gateway-operator/config/config.yaml +++ b/kubernetes/gateway-operator/config/config.yaml @@ -28,9 +28,32 @@ gateway: # Use plain HTTP instead of HTTPS for OCI registries # Useful for local/test registries without TLS support - # IMPORTANT: Should be false in production environments + # IMPORTANT: Should be false in production environments plain_http: false - + + # Credentials for pulling the gateway Helm chart from a private OCI registry. + # Omit entirely for anonymous pulls. + # registry_credentials_secret: + # name: "registry-creds" + # namespace: "gateway-system" + # username_key: "username" + # password_key: "password" + +# Kubernetes Gateway API (gateway.networking.k8s.io) configuration +gateway_api: + # gatewayClassName values this operator manages; only matching Gateway/HTTPRoute + # resources are reconciled. Override with GATEWAY_API_GATEWAY_CLASS_NAMES (comma-separated). + gateway_class_names: + - wso2-api-platform + + # Cluster DNS suffix for in-cluster Service URLs (..svc.:). + # Override with CLUSTER_DOMAIN. + cluster_domain: "cluster.local" + + # Published verbatim as the Gateway status address for NodePort-backed gateways in local + # environments (e.g. set to "127.0.0.1" for kind / Rancher Desktop). Leave empty on real + # clusters. Override with GATEWAY_API_NODEPORT_ADDRESS_OVERRIDE. + # nodeport_address_override: "127.0.0.1" # Reconciliation behavior configuration reconciliation: @@ -52,9 +75,5 @@ logging: # Log level (debug, info, warn, error) # Can be overridden with LOG_LEVEL environment variable level: "info" - # Enable development mode (boolean). Replaces the previous `format` field. - # Deprecated: Use format instead - development: true # Log format: "json" or "text" - # Default is "text" in development, "json" in production format: "text" diff --git a/kubernetes/helm/operator-helm-chart/templates/configmap.yaml b/kubernetes/helm/operator-helm-chart/templates/configmap.yaml index 41199a2b63..7a8b839950 100644 --- a/kubernetes/helm/operator-helm-chart/templates/configmap.yaml +++ b/kubernetes/helm/operator-helm-chart/templates/configmap.yaml @@ -18,10 +18,21 @@ data: helm_values_file_path: {{ .Values.gateway.helm.valuesFilePath | quote }} insecure_registry: {{ .Values.gateway.helm.insecureRegistry | default false }} plain_http: {{ .Values.gateway.helm.plainHTTP | default false }} +{{- with .Values.gateway.helm.registryCredentialsSecret }} +{{- if .name }} + registry_credentials_secret: + name: {{ .name | quote }} + namespace: {{ .namespace | default $.Release.Namespace | quote }} + username_key: {{ .usernameKey | default "username" | quote }} + password_key: {{ .passwordKey | default "password" | quote }} +{{- end }} +{{- end }} reconciliation: - enabled: {{ .Values.reconciliation.enabled | default true }} - interval: {{ .Values.reconciliation.interval | default 300 }} + sync_period: {{ .Values.reconciliation.syncPeriod | default "10m" | quote }} max_concurrent_reconciles: {{ .Values.reconciliation.maxConcurrentReconciles | default 1 }} + max_retry_attempts: {{ .Values.reconciliation.maxRetryAttempts | default 10 }} + initial_backoff: {{ .Values.reconciliation.initialBackoff | default "1s" | quote }} + max_backoff_duration: {{ .Values.reconciliation.maxBackoffDuration | default "60s" | quote }} logging: level: {{ .Values.logging.level | quote }} format: {{ .Values.logging.format | quote }} diff --git a/kubernetes/helm/operator-helm-chart/values.yaml b/kubernetes/helm/operator-helm-chart/values.yaml index 9c132a2814..1c98ef0543 100644 --- a/kubernetes/helm/operator-helm-chart/values.yaml +++ b/kubernetes/helm/operator-helm-chart/values.yaml @@ -76,6 +76,17 @@ gateway: insecureRegistry: false # Use plain HTTP instead of HTTPS for OCI registries (for local/test registries) plainHTTP: false + # Credentials for pulling the gateway Helm chart from a private OCI registry. + # Rendered into operator config as gateway.registry_credentials_secret ONLY when + # name is set; leave name empty for anonymous pulls. + registryCredentialsSecret: + name: "" + # Namespace of the credentials Secret. Defaults to the operator's release + # namespace when left empty. + namespace: "" + # Keys within the Secret holding the registry username and password. + usernameKey: username + passwordKey: password # Gateway chart values that will be used when deploying gateways # Users can override these values during helm install/upgrade values: @@ -637,10 +648,17 @@ gateway: affinity: {} reconciliation: - enabled: true - interval: 300 + # Minimum frequency at which watched resources are re-reconciled (Go duration). + # Passed through as reconciliation.sync_period. + syncPeriod: 10m # Passed through to operator config.yaml as reconciliation.max_concurrent_reconciles (must be >= 1). maxConcurrentReconciles: 1 + # Max retry attempts for gateway operations → reconciliation.max_retry_attempts (must be >= 1). + maxRetryAttempts: 10 + # Initial retry backoff (Go duration) → reconciliation.initial_backoff. + initialBackoff: 1s + # Maximum exponential backoff (Go duration) → reconciliation.max_backoff_duration. + maxBackoffDuration: 60s logging: level: "info" format: "json" From b8c482ab010c2210de1a73a84840b05aed401033 Mon Sep 17 00:00:00 2001 From: Dineth Date: Tue, 21 Jul 2026 13:36:08 +0530 Subject: [PATCH 08/12] Update Helm chart documentation and configurations for APIGateway and RestApi CRDs; enhance RBAC and cleanup job definitions --- kubernetes/helm/operator-helm-chart/README.md | 279 ++++++++++-------- .../operator-helm-chart/templates/NOTES.txt | 41 ++- .../templates/cleanupo-finalizer-job.yaml | 2 +- .../templates/crd-manager-rbac.yaml | 58 +++- .../templates/operator-crds-apply-job.yaml | 2 +- 5 files changed, 240 insertions(+), 142 deletions(-) diff --git a/kubernetes/helm/operator-helm-chart/README.md b/kubernetes/helm/operator-helm-chart/README.md index a2d5a89f94..c124f5e942 100644 --- a/kubernetes/helm/operator-helm-chart/README.md +++ b/kubernetes/helm/operator-helm-chart/README.md @@ -1,43 +1,46 @@ # API Platform Gateway Operator Helm Chart -This Helm chart deploys the API Platform Gateway Operator, a Kubernetes operator that manages the lifecycle of API Gateway instances and API configurations. +This Helm chart deploys the API Platform Gateway Operator, a Kubernetes operator that manages the lifecycle of API Gateway instances and the APIs deployed onto them. ## Overview The Gateway Operator is responsible for: -- Managing GatewayConfiguration custom resources -- Managing APIConfiguration custom resources -- Automatically deploying and configuring gateway instances +- Managing `APIGateway` custom resources (gateway instances) +- Managing `RestApi` and the other API-management custom resources (ApiKey, APIPolicy, Certificate, LlmProvider, LlmProviderTemplate, LlmProxy, ManagedSecret, Mcp, Subscription, SubscriptionPlan) +- Automatically deploying and configuring gateway instances (via the gateway Helm chart) - Reconciling gateway state with desired configuration -- Integrating with the control plane API +- Optionally reconciling Kubernetes Gateway API resources (Gateway, HTTPRoute) for managed gateway classes + +All operator CRDs live in the API group **`gateway.api-platform.wso2.com`**, served at `v1alpha1` and `v1` (v1 is the storage version; the two schemas are identical and bridged with conversion `strategy: None`). ## Prerequisites - Kubernetes 1.19+ - Helm 3.0+ -- cert-manager v1.0+ (optional, for TLS certificate management) +- cert-manager v1.0+ (optional, for gateway TLS certificate management) ## Installation ### Basic Installation ```bash -helm install apip-operator ./operator-helm-chart +helm install apip-operator ./operator-helm-chart --namespace gateway-operator-system --create-namespace ``` ### Install with Custom Values ```bash helm install apip-operator ./operator-helm-chart \ - --set image.tag=v1.0.0 \ + --namespace gateway-operator-system --create-namespace \ + --set image.tag=0.8.0 \ --set gateway.controlPlaneHost=http://my-control-plane:3001 ``` ### Install from OCI Registry ```bash -helm install apip-operator oci://registry-1.docker.io/yourorg/api-platform-operator \ - --version 0.0.1 +helm install apip-operator oci://ghcr.io/wso2/api-platform/helm-charts/gateway-operator \ + --version ``` ## Configuration @@ -47,8 +50,9 @@ helm install apip-operator oci://registry-1.docker.io/yourorg/api-platform-opera | Parameter | Description | Default | |-----------|-------------|---------| | `replicaCount` | Number of operator replicas | `1` | -| `image.repository` | Operator image repository | `tharsanan/api-platform/gateway-controller` | -| `image.tag` | Operator image tag | `latest` | +| `watchNamespaces` | Namespaces to watch (cluster-wide if empty) | `[]` | +| `image.repository` | Operator image repository | `ghcr.io/wso2/api-platform/gateway-operator` | +| `image.tag` | Operator image tag | `0.8.0` | | `image.pullPolicy` | Image pull policy | `Always` | | `serviceAccount.create` | Create service account | `true` | | `serviceAccount.name` | Service account name | `controller-manager` | @@ -60,39 +64,40 @@ helm install apip-operator oci://registry-1.docker.io/yourorg/api-platform-opera | Parameter | Description | Default | |-----------|-------------|---------| | `gateway.controlPlaneHost` | Control plane API endpoint | `http://platform-api:3001` | -| `gateway.helm.chartName` | Gateway Helm chart OCI or repo reference (ignored if `chartPath` is set) | `oci://...` | -| `gateway.helm.chartVersion` | Gateway chart version (for remote pulls; also used in upgrade signatures) | `1.0.0` | +| `gateway.helm.chartName` | Gateway Helm chart OCI or repo reference (ignored if `chartPath` is set) | `oci://ghcr.io/wso2/api-platform/helm-charts/gateway` | +| `gateway.helm.chartVersion` | Gateway chart version (for remote pulls; also used in upgrade signatures) | `1.1.0` | | `gateway.helm.chartPath` | Local chart dir or `.tgz` path **inside the operator pod**; when non-empty, remote chart lookup (`chartName`/`chartVersion`) and registry auth are ignored | `""` | | `gateway.helm.valuesFilePath` | Path to gateway values file | `/config/gateway_values.yaml` | +| `gateway.helm.insecureRegistry` | Skip TLS verification for OCI registries (still HTTPS) | `false` | +| `gateway.helm.plainHTTP` | Use plain HTTP for OCI registries | `false` | +| `gateway.helm.registryCredentialsSecret.name` | Secret holding private-registry credentials for the gateway chart pull (empty = anonymous) | `""` | + +### Gateway API (Kubernetes Gateway API) Configuration -### Gateway Default Values +| Parameter | Description | Default | +|-----------|-------------|---------| +| `gatewayApi.installStandardCRDs` | Install the standard-channel Gateway API CRDs | `true` | +| `gatewayApi.managedGatewayClassNames` | `gatewayClassName` values this operator reconciles | `[wso2-api-platform]` | +| `gatewayApi.clusterDomain` | Cluster DNS suffix for in-cluster Service URLs | `cluster.local` | -The operator can deploy gateway instances with default values. These are defined under `gateway.values` and include: +### Gateway Default Values (`gateway.values`) -#### Controller Configuration -- Image: `tharsanan/api-platform/gateway-controller:v1.0.0-m4` -- Service ports: REST (9090), xDS (18000), Policy (18001) -- TLS support with cert-manager integration -- Persistence with PVC support (100Mi default) +The operator deploys gateway instances with the values under `gateway.values`, which mirror the gateway Helm chart's own `values.yaml` — see `kubernetes/helm/gateway-helm-chart/values.yaml` for the authoritative, fully-documented set. The two main components are: -#### Router Configuration -- Image: `tharsanan/api-platform/gateway-router:v1.0.0-m4` -- Service ports: HTTP (8080), HTTPS (8443), Admin (9901) -- Envoy-based routing -- Health probes on admin port +- **`gateway.values.gateway.controller`** — control plane of the gateway. Service type `ClusterIP` by default; ports `rest: 9090`, `xds: 18000`, `policy: 18001`, `admin: 9092`, `metrics: 9091`. Supports TLS (see below), storage, persistence, and `deployment.replicaCount`. +- **`gateway.values.gateway.gatewayRuntime`** — the data plane (Envoy-based router + policy engine). Service type `LoadBalancer` by default; ports `http: 8080`, `https: 8443`, plus admin/metrics ports. Has its own `deployment.replicaCount`. -#### Policy Engine Configuration -- Image: `tharsanan/api-platform/policy-engine:v1.0.0-m4` -- Service port: External processor (9001) -- xDS-based configuration -- Admin interface support +Component container image tags come from the gateway chart; do not hardcode them here. ### Reconciliation Settings | Parameter | Description | Default | |-----------|-------------|---------| -| `reconciliation.enabled` | Enable periodic reconciliation | `true` | -| `reconciliation.interval` | Reconciliation interval in seconds | `300` | +| `reconciliation.syncPeriod` | Minimum frequency at which watched resources are re-reconciled (Go duration) | `10m` | +| `reconciliation.maxConcurrentReconciles` | Maximum concurrent reconciles (must be ≥ 1) | `1` | +| `reconciliation.maxRetryAttempts` | Maximum retry attempts for gateway operations | `10` | +| `reconciliation.initialBackoff` | Initial retry backoff (Go duration) | `1s` | +| `reconciliation.maxBackoffDuration` | Maximum exponential backoff (Go duration) | `60s` | ### Logging Configuration @@ -105,39 +110,56 @@ The operator can deploy gateway instances with default values. These are defined | Parameter | Description | Default | |-----------|-------------|---------| -| `securityContext.runAsNonRoot` | Run as non-root user | `false` | -| `securityContext.runAsUser` | User ID to run as | `null` | +| `securityContext.runAsNonRoot` | Run as non-root user | `true` | +| `securityContext.runAsUser` | User ID to run as | `10001` | ## Custom Resource Definitions (CRDs) -The chart installs two CRDs: +The chart delivers all operator CRDs (group `gateway.api-platform.wso2.com`, versions `v1alpha1` and `v1`). They are **not** installed via Helm's `crds/` directory — that directory is install-only and never upgraded. Instead they are staged in a ConfigMap (`operator-crds.yaml`) and applied by a `pre-install,pre-upgrade` hook Job (`operator-crds-apply-job.yaml`) using `kubectl apply --server-side`, so they are updated on every install *and* upgrade. + +The two most commonly used kinds: -### 1. GatewayConfiguration +### 1. APIGateway -Defines a gateway instance with all its components (controller, router, policy engine). +Defines a gateway instance. `spec.apiSelector` is required; the gateway topology (replicas, service types, images, TLS, …) is supplied through a referenced ConfigMap via `spec.configRef`. ```yaml -apiVersion: api.api-platform.wso2.com/v1alpha1 -kind: GatewayConfiguration +apiVersion: gateway.api-platform.wso2.com/v1alpha1 +kind: APIGateway metadata: name: my-gateway namespace: default spec: - # Gateway specification + apiSelector: + scope: Cluster # accept APIs from any namespace + infrastructure: + replicas: 1 + storage: + type: sqlite + # controlPlane: { host: "...", tls: { enabled: true } } + # configRef: { name: my-gateway-values } # ConfigMap with gateway Helm values ``` -### 2. APIConfiguration +### 2. RestApi -Defines an API that will be deployed to gateway instances. +Defines an API deployed onto matching gateways. ```yaml -apiVersion: api.api-platform.wso2.com/v1alpha1 -kind: APIConfiguration +apiVersion: gateway.api-platform.wso2.com/v1alpha1 +kind: RestApi metadata: name: my-api namespace: default spec: - # API specification + displayName: my-api + version: v1.0 + context: /my-api + upstream: + main: + url: https://httpbin.org/anything + operations: # required + - method: GET + path: / ``` ## Usage @@ -146,7 +168,7 @@ spec: ```bash helm install apip-operator ./operator-helm-chart \ - --namespace api-platform \ + --namespace gateway-operator-system \ --create-namespace ``` @@ -154,32 +176,52 @@ helm install apip-operator ./operator-helm-chart \ ```bash # Check operator deployment -kubectl get deployment controller-manager -n api-platform +kubectl get deployment -n gateway-operator-system -l app.kubernetes.io/name=gateway-operator # Check operator pods -kubectl get pods -n api-platform -l control-plane=controller-manager +kubectl get pods -n gateway-operator-system -l app.kubernetes.io/name=gateway-operator # View operator logs -kubectl logs -f deployment/controller-manager -n api-platform +kubectl logs -f deployment/apip-operator-gateway-operator -n gateway-operator-system ``` ### Create a Gateway Instance +To control gateway topology (separate controller / data-plane replica counts, a LoadBalancer data plane, etc.), supply gateway Helm values through a ConfigMap referenced by `spec.configRef`: + ```bash kubectl apply -f - < +kubectl logs deployment/apip-operator-gateway-operator -n gateway-operator-system | grep -i error +kubectl describe apigateway ``` ### CRDs Not Installing -Verify CRDs are installed: +CRDs are applied by the `apply-crds` hook Job, not from a `crds/` directory. Verify: ```bash -kubectl get crd | grep api-platform.wso2.com -``` +# Are the CRDs present? +kubectl get crd | grep gateway.api-platform.wso2.com -Manually install CRDs if needed: -```bash -kubectl apply -f crds/ +# Did the apply-crds hook Job run? (it self-deletes on success) +helm get hooks apip-operator -n gateway-operator-system +kubectl get events -n gateway-operator-system --sort-by='.lastTimestamp' | grep apply-crds ``` +A common failure is missing RBAC/ServiceAccount ordering — the bootstrap ServiceAccount and ClusterRole are themselves pre-install hooks weighted ahead of the Job (see `crd-manager-rbac.yaml`). ### Leader Election Issues If running multiple replicas, check leader election: ```bash -kubectl logs deployment/controller-manager -n api-platform | grep leader +kubectl logs deployment/apip-operator-gateway-operator -n gateway-operator-system | grep leader ``` ## Architecture The operator follows the Kubernetes operator pattern: -1. **Controller Manager**: Main operator process that watches CRDs +1. **Controller Manager**: Main operator process that watches the CRDs 2. **Reconciliation Loop**: Continuously ensures actual state matches desired state -3. **Helm Integration**: Uses Helm to deploy gateway instances -4. **Control Plane Integration**: Syncs with platform API for centralized management +3. **Helm Integration**: Uses Helm to deploy gateway instances from the gateway chart +4. **Control Plane Integration**: Syncs with the platform API for centralized management ## Components -- **ClusterRole/ClusterRoleBinding**: Grants necessary RBAC permissions -- **Leader Election Role/RoleBinding**: Manages leader election for HA -- **ServiceAccount**: Identity for the operator -- **Deployment**: Runs the operator controller manager -- **ConfigMap**: Stores operator configuration and gateway values -- **Finalizer Job**: Cleanup job for operator deletion +- **Bootstrap ServiceAccount + ClusterRole/Binding** (`crd-manager-rbac.yaml`): hook-scoped identity used by the CRD-lifecycle Jobs +- **operator-crds ConfigMap + apply-crds Job**: deliver and apply the CRDs on install/upgrade +- **ClusterRole/ClusterRoleBinding & Role/RoleBinding**: operator runtime RBAC +- **Leader Election Role/RoleBinding**: manages leader election for HA +- **ServiceAccount**: runtime identity for the operator +- **Deployment**: runs the operator controller manager +- **ConfigMap**: stores operator configuration and gateway values +- **Finalizer Job**: cleanup job run on operator deletion ## Development ### Local Testing -Run the operator locally: ```bash cd kubernetes/gateway-operator make run ``` -### Building Custom Image +### Building a Custom Image ```bash cd kubernetes/gateway-operator @@ -424,7 +473,7 @@ make test For issues and questions: - GitHub Issues: https://github.com/wso2/api-platform -- Documentation: See `/kubernetes/gateway-operator/` directory +- Documentation: See the `/kubernetes/gateway-operator/` directory ## License diff --git a/kubernetes/helm/operator-helm-chart/templates/NOTES.txt b/kubernetes/helm/operator-helm-chart/templates/NOTES.txt index ae2b24e4d8..6902b15299 100644 --- a/kubernetes/helm/operator-helm-chart/templates/NOTES.txt +++ b/kubernetes/helm/operator-helm-chart/templates/NOTES.txt @@ -23,7 +23,7 @@ Operator Details: {{- end }} Custom Resource Definitions: - - From chart crds/: APIGateway, RestApi (gateway.api-platform.wso2.com/v1alpha1) + - Applied by the apply-crds hook Job: APIGateway, RestApi and related management CRDs (group gateway.api-platform.wso2.com, served v1alpha1 + v1) {{- if .Values.gatewayApi.installStandardCRDs }} - Gateway API standard v1.3.0 (GatewayClass, Gateway, HTTPRoute, GRPCRoute, ReferenceGrant) — included because gatewayApi.installStandardCRDs is true {{- else }} @@ -34,11 +34,8 @@ Gateway Configuration: - Control Plane: {{ .Values.gateway.controlPlaneHost }} - Gateway Chart: {{ .Values.gateway.helm.chartName }} - Chart Version: {{ .Values.gateway.helm.chartVersion }} -{{- if .Values.reconciliation.enabled }} - - Reconciliation Enabled: Yes (Interval: {{ .Values.reconciliation.interval }}s) -{{- else }} - - Reconciliation Enabled: No -{{- end }} + - Reconciliation Sync Period: {{ .Values.reconciliation.syncPeriod }} + - Max Concurrent Reconciles: {{ .Values.reconciliation.maxConcurrentReconciles }} Next Steps: @@ -49,31 +46,43 @@ Next Steps: 2. Check operator logs: $ kubectl logs -f deployment/{{ include "gateway-operator.fullname" . }} -n {{ .Release.Namespace }} -3. Create a GatewayConfiguration to deploy a gateway instance: +3. Create an APIGateway to deploy a gateway instance: $ kubectl apply -f - < Date: Tue, 21 Jul 2026 15:07:19 +0530 Subject: [PATCH 09/12] Add Custom Resource Definitions for Subscription and SubscriptionPlan - Introduced CRDs for Subscription and SubscriptionPlan under the group gateway.api-platform.wso2.com. - Each CRD includes detailed specifications, status fields, and validation rules. - Updated NOTES.txt to reflect the installation method of CRDs. - Modified cleanup finalizer job to use a configurable service account name. - Removed deprecated RBAC configurations and CRD apply job templates to streamline the chart. --- .../api/v1alpha1/crd_schema_identity_test.go | 7 +- kubernetes/helm/operator-helm-chart/README.md | 22 +++-- ...way.api-platform.wso2.com_apigateways.yaml | 0 ...gateway.api-platform.wso2.com_apikeys.yaml | 0 ...way.api-platform.wso2.com_apipolicies.yaml | 0 ...ay.api-platform.wso2.com_certificates.yaml | 0 ...ay.api-platform.wso2.com_llmproviders.yaml | 0 ...latform.wso2.com_llmprovidertemplates.yaml | 0 ...eway.api-platform.wso2.com_llmproxies.yaml | 0 ....api-platform.wso2.com_managedsecrets.yaml | 0 .../gateway.api-platform.wso2.com_mcps.yaml | 0 ...ateway.api-platform.wso2.com_restapis.yaml | 0 ...i-platform.wso2.com_subscriptionplans.yaml | 0 ...y.api-platform.wso2.com_subscriptions.yaml | 0 .../operator-helm-chart/templates/NOTES.txt | 2 +- .../templates/cleanupo-finalizer-job.yaml | 2 +- .../templates/crd-manager-rbac.yaml | 86 ------------------- .../templates/operator-crds-apply-job.yaml | 49 ----------- .../templates/operator-crds.yaml | 46 ---------- 19 files changed, 16 insertions(+), 198 deletions(-) rename kubernetes/helm/operator-helm-chart/{files/operator-crds => crds}/gateway.api-platform.wso2.com_apigateways.yaml (100%) rename kubernetes/helm/operator-helm-chart/{files/operator-crds => crds}/gateway.api-platform.wso2.com_apikeys.yaml (100%) rename kubernetes/helm/operator-helm-chart/{files/operator-crds => crds}/gateway.api-platform.wso2.com_apipolicies.yaml (100%) rename kubernetes/helm/operator-helm-chart/{files/operator-crds => crds}/gateway.api-platform.wso2.com_certificates.yaml (100%) rename kubernetes/helm/operator-helm-chart/{files/operator-crds => crds}/gateway.api-platform.wso2.com_llmproviders.yaml (100%) rename kubernetes/helm/operator-helm-chart/{files/operator-crds => crds}/gateway.api-platform.wso2.com_llmprovidertemplates.yaml (100%) rename kubernetes/helm/operator-helm-chart/{files/operator-crds => crds}/gateway.api-platform.wso2.com_llmproxies.yaml (100%) rename kubernetes/helm/operator-helm-chart/{files/operator-crds => crds}/gateway.api-platform.wso2.com_managedsecrets.yaml (100%) rename kubernetes/helm/operator-helm-chart/{files/operator-crds => crds}/gateway.api-platform.wso2.com_mcps.yaml (100%) rename kubernetes/helm/operator-helm-chart/{files/operator-crds => crds}/gateway.api-platform.wso2.com_restapis.yaml (100%) rename kubernetes/helm/operator-helm-chart/{files/operator-crds => crds}/gateway.api-platform.wso2.com_subscriptionplans.yaml (100%) rename kubernetes/helm/operator-helm-chart/{files/operator-crds => crds}/gateway.api-platform.wso2.com_subscriptions.yaml (100%) delete mode 100644 kubernetes/helm/operator-helm-chart/templates/crd-manager-rbac.yaml delete mode 100644 kubernetes/helm/operator-helm-chart/templates/operator-crds-apply-job.yaml delete mode 100644 kubernetes/helm/operator-helm-chart/templates/operator-crds.yaml diff --git a/kubernetes/gateway-operator/api/v1alpha1/crd_schema_identity_test.go b/kubernetes/gateway-operator/api/v1alpha1/crd_schema_identity_test.go index f94f7b90d5..6b2c7ee9c5 100644 --- a/kubernetes/gateway-operator/api/v1alpha1/crd_schema_identity_test.go +++ b/kubernetes/gateway-operator/api/v1alpha1/crd_schema_identity_test.go @@ -33,9 +33,10 @@ import ( // TestCRDVersionSchemasIdentical enforces the invariant that every served // version of each CRD shares an identical OpenAPI schema. // -// The operator ships its CRDs with spec.conversion.strategy = None (injected in -// kubernetes/helm/operator-helm-chart/templates/operator-crds.yaml). "None" -// performs NO field transformation between versions — the API server only +// The operator ships its CRDs (kubernetes/helm/operator-helm-chart/crds/) serving +// v1 (storage) and v1alpha1 (served) with conversion strategy None — a multi-version +// CRD with no explicit spec.conversion block defaults to None at the API server. +// "None" performs NO field transformation between versions — the API server only // relabels apiVersion on read/write. That is safe ONLY while the v1 (storage) // and v1alpha1 (served) schemas are equivalent; any divergence would silently // drop or corrupt fields at the storage boundary, with no conversion webhook to diff --git a/kubernetes/helm/operator-helm-chart/README.md b/kubernetes/helm/operator-helm-chart/README.md index c124f5e942..a5939998b7 100644 --- a/kubernetes/helm/operator-helm-chart/README.md +++ b/kubernetes/helm/operator-helm-chart/README.md @@ -115,7 +115,11 @@ Component container image tags come from the gateway chart; do not hardcode them ## Custom Resource Definitions (CRDs) -The chart delivers all operator CRDs (group `gateway.api-platform.wso2.com`, versions `v1alpha1` and `v1`). They are **not** installed via Helm's `crds/` directory — that directory is install-only and never upgraded. Instead they are staged in a ConfigMap (`operator-crds.yaml`) and applied by a `pre-install,pre-upgrade` hook Job (`operator-crds-apply-job.yaml`) using `kubectl apply --server-side`, so they are updated on every install *and* upgrade. +The chart ships all operator CRDs (group `gateway.api-platform.wso2.com`, served at `v1alpha1` and `v1`, with `v1` as the storage version) in the Helm-native `crds/` directory. Helm installs everything under `crds/` automatically on `helm install`. + +> **Important — CRDs are install-only.** Helm applies `crds/` only when a CRD does not already exist, and **never updates or deletes** CRDs on `helm upgrade`, `helm uninstall`, or a re-`helm install` on a cluster where they already exist. This operator **requires the `v1` version to be served**, so: +> - **Fresh clusters** (no pre-existing `gateway.api-platform.wso2.com` CRDs) get the correct v1+v1alpha1 CRDs and work out of the box. +> - **Clusters that already have older (v1alpha1-only) CRDs** will NOT be upgraded by Helm. To move them to v1, delete the old CRDs first (`kubectl get crd -o name | grep gateway.api-platform.wso2.com | xargs kubectl delete`) then reinstall, or apply the updated CRDs manually with `kubectl apply -f crds/`. The two most commonly used kinds: @@ -364,7 +368,7 @@ helm upgrade apip-operator ./operator-helm-chart \ --reuse-values ``` -The `pre-install,pre-upgrade` apply-crds hook Job re-applies the CRDs on every upgrade, so existing installs receive CRD schema changes automatically. +> **Note:** CRDs in `crds/` are **not** re-applied on `helm upgrade` (a Helm limitation). If a chart upgrade includes CRD schema changes, apply the updated CRDs manually with `kubectl apply -f crds/`. Because the operator requires the `v1` version to be served, do this **before** rolling out an operator image that expects it. ### Upgrade with New Values @@ -382,7 +386,7 @@ helm upgrade apip-operator ./operator-helm-chart \ helm uninstall apip-operator --namespace gateway-operator-system ``` -**Note:** This does not delete the CRDs (they are applied out-of-band by the hook Job, not tracked by the Helm release). To delete them manually: +**Note:** This does not delete the CRDs (Helm never removes CRDs installed from `crds/`). To delete them manually: ```bash kubectl get crd -o name | grep gateway.api-platform.wso2.com | xargs -r kubectl delete @@ -408,16 +412,11 @@ kubectl describe apigateway ### CRDs Not Installing -CRDs are applied by the `apply-crds` hook Job, not from a `crds/` directory. Verify: +CRDs are installed from the chart's `crds/` directory on `helm install`. Verify: ```bash -# Are the CRDs present? kubectl get crd | grep gateway.api-platform.wso2.com - -# Did the apply-crds hook Job run? (it self-deletes on success) -helm get hooks apip-operator -n gateway-operator-system -kubectl get events -n gateway-operator-system --sort-by='.lastTimestamp' | grep apply-crds ``` -A common failure is missing RBAC/ServiceAccount ordering — the bootstrap ServiceAccount and ClusterRole are themselves pre-install hooks weighted ahead of the Job (see `crd-manager-rbac.yaml`). +If they are missing on a fresh install, ensure you did not pass `--skip-crds`. If they are present but **stale** (e.g. only `v1alpha1`), Helm will not update them on upgrade or reinstall — delete and reinstall, or run `kubectl apply -f crds/` (the operator requires the `v1` version to be served). ### Leader Election Issues @@ -437,8 +436,7 @@ The operator follows the Kubernetes operator pattern: ## Components -- **Bootstrap ServiceAccount + ClusterRole/Binding** (`crd-manager-rbac.yaml`): hook-scoped identity used by the CRD-lifecycle Jobs -- **operator-crds ConfigMap + apply-crds Job**: deliver and apply the CRDs on install/upgrade +- **`crds/` directory**: operator CRDs, installed by Helm on fresh install - **ClusterRole/ClusterRoleBinding & Role/RoleBinding**: operator runtime RBAC - **Leader Election Role/RoleBinding**: manages leader election for HA - **ServiceAccount**: runtime identity for the operator diff --git a/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_apigateways.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_apigateways.yaml similarity index 100% rename from kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_apigateways.yaml rename to kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_apigateways.yaml diff --git a/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_apikeys.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_apikeys.yaml similarity index 100% rename from kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_apikeys.yaml rename to kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_apikeys.yaml diff --git a/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_apipolicies.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_apipolicies.yaml similarity index 100% rename from kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_apipolicies.yaml rename to kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_apipolicies.yaml diff --git a/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_certificates.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_certificates.yaml similarity index 100% rename from kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_certificates.yaml rename to kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_certificates.yaml diff --git a/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_llmproviders.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmproviders.yaml similarity index 100% rename from kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_llmproviders.yaml rename to kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmproviders.yaml diff --git a/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_llmprovidertemplates.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmprovidertemplates.yaml similarity index 100% rename from kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_llmprovidertemplates.yaml rename to kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmprovidertemplates.yaml diff --git a/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_llmproxies.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmproxies.yaml similarity index 100% rename from kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_llmproxies.yaml rename to kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmproxies.yaml diff --git a/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_managedsecrets.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_managedsecrets.yaml similarity index 100% rename from kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_managedsecrets.yaml rename to kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_managedsecrets.yaml diff --git a/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_mcps.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_mcps.yaml similarity index 100% rename from kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_mcps.yaml rename to kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_mcps.yaml diff --git a/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_restapis.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_restapis.yaml similarity index 100% rename from kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_restapis.yaml rename to kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_restapis.yaml diff --git a/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_subscriptionplans.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_subscriptionplans.yaml similarity index 100% rename from kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_subscriptionplans.yaml rename to kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_subscriptionplans.yaml diff --git a/kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_subscriptions.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_subscriptions.yaml similarity index 100% rename from kubernetes/helm/operator-helm-chart/files/operator-crds/gateway.api-platform.wso2.com_subscriptions.yaml rename to kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_subscriptions.yaml diff --git a/kubernetes/helm/operator-helm-chart/templates/NOTES.txt b/kubernetes/helm/operator-helm-chart/templates/NOTES.txt index 6902b15299..110751e486 100644 --- a/kubernetes/helm/operator-helm-chart/templates/NOTES.txt +++ b/kubernetes/helm/operator-helm-chart/templates/NOTES.txt @@ -23,7 +23,7 @@ Operator Details: {{- end }} Custom Resource Definitions: - - Applied by the apply-crds hook Job: APIGateway, RestApi and related management CRDs (group gateway.api-platform.wso2.com, served v1alpha1 + v1) + - Installed from the chart crds/ directory (fresh install only): APIGateway, RestApi and related management CRDs (group gateway.api-platform.wso2.com, served v1alpha1 + v1) {{- if .Values.gatewayApi.installStandardCRDs }} - Gateway API standard v1.3.0 (GatewayClass, Gateway, HTTPRoute, GRPCRoute, ReferenceGrant) — included because gatewayApi.installStandardCRDs is true {{- else }} diff --git a/kubernetes/helm/operator-helm-chart/templates/cleanupo-finalizer-job.yaml b/kubernetes/helm/operator-helm-chart/templates/cleanupo-finalizer-job.yaml index 6ed0e411b8..c64f59605b 100644 --- a/kubernetes/helm/operator-helm-chart/templates/cleanupo-finalizer-job.yaml +++ b/kubernetes/helm/operator-helm-chart/templates/cleanupo-finalizer-job.yaml @@ -11,7 +11,7 @@ spec: metadata: name: "{{ .Release.Name }}-cleanup-finalizers" spec: - serviceAccountName: {{ include "gateway-operator.fullname" . }}-crd-manager + serviceAccountName: {{ .Values.serviceAccount.name }} restartPolicy: Never containers: - name: cleanup diff --git a/kubernetes/helm/operator-helm-chart/templates/crd-manager-rbac.yaml b/kubernetes/helm/operator-helm-chart/templates/crd-manager-rbac.yaml deleted file mode 100644 index a16e2bbf39..0000000000 --- a/kubernetes/helm/operator-helm-chart/templates/crd-manager-rbac.yaml +++ /dev/null @@ -1,86 +0,0 @@ -{{/* -Bootstrap identity + RBAC for the CRD-lifecycle hook Jobs (operator-crds-apply-job -and cleanupo-finalizer-job). - -These Jobs run as Helm hooks, i.e. BEFORE the main release phase, so they cannot use -the operator's runtime ServiceAccount (serviceaccount.yaml): Helm only creates that SA -in the main phase, so on a fresh install it does not yet exist when the hook pods are -admitted, and the pod is rejected with "serviceaccount not found". Reusing it also can't -be fixed by hook-ifying it — that SA is a release-tracked resource, so converting it to a -hook would make Helm prune it on the first upgrade from any existing install. - -This dedicated ServiceAccount and its cluster-scoped RBAC are therefore themselves -pre-install,pre-upgrade hooks, weighted ahead of the resources that consume them: - -2 this ServiceAccount - -1 the ClusterRole + ClusterRoleBinding below - 0 the operator-crds ConfigMap (operator-crds.yaml) - 1 the apply-crds Job (operator-crds-apply-job.yaml) -The before-hook-creation delete policy makes them idempotent across repeat upgrades -(a plain hook Create would otherwise fail with AlreadyExists on the second upgrade). -They persist between install and uninstall, so the pre-delete cleanupo-finalizer-job -can still use this identity at teardown. - -CustomResourceDefinitions are cluster-scoped, so this RBAC is required regardless of -whether .Values.watchNamespaces restricts the operator's own manager-role to a -namespaced Role (see role.yaml/clusterrole.yaml). -*/}} -apiVersion: v1 -kind: ServiceAccount -metadata: - name: {{ include "gateway-operator.fullname" . }}-crd-manager - namespace: {{ .Release.Namespace }} - labels: - app.kubernetes.io/name: {{ include "gateway-operator.name" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - annotations: - "helm.sh/hook": pre-install,pre-upgrade - "helm.sh/hook-weight": "-2" - "helm.sh/hook-delete-policy": before-hook-creation ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRole -metadata: - name: {{ include "gateway-operator.fullname" . }}-crd-manager-role - labels: - app.kubernetes.io/name: {{ include "gateway-operator.name" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - annotations: - "helm.sh/hook": pre-install,pre-upgrade - "helm.sh/hook-weight": "-1" - "helm.sh/hook-delete-policy": before-hook-creation -rules: - # apply-crds Job: manage the operator's CustomResourceDefinitions. - - apiGroups: ["apiextensions.k8s.io"] - resources: ["customresourcedefinitions"] - verbs: ["get", "list", "watch", "create", "update", "patch"] - # cleanupo-finalizer-job (pre-delete): enumerate namespaces and strip finalizers - # from leftover APIGateway/RestApi CRs so the resources can be garbage-collected. - - apiGroups: [""] - resources: ["namespaces"] - verbs: ["get", "list"] - - apiGroups: ["gateway.api-platform.wso2.com"] - resources: ["apigateways", "restapis"] - verbs: ["get", "list", "patch", "update"] ---- -apiVersion: rbac.authorization.k8s.io/v1 -kind: ClusterRoleBinding -metadata: - name: {{ include "gateway-operator.fullname" . }}-crd-manager-rolebinding - labels: - app.kubernetes.io/name: {{ include "gateway-operator.name" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - annotations: - "helm.sh/hook": pre-install,pre-upgrade - "helm.sh/hook-weight": "-1" - "helm.sh/hook-delete-policy": before-hook-creation -roleRef: - apiGroup: rbac.authorization.k8s.io - kind: ClusterRole - name: {{ include "gateway-operator.fullname" . }}-crd-manager-role -subjects: - - kind: ServiceAccount - name: {{ include "gateway-operator.fullname" . }}-crd-manager - namespace: {{ .Release.Namespace }} diff --git a/kubernetes/helm/operator-helm-chart/templates/operator-crds-apply-job.yaml b/kubernetes/helm/operator-helm-chart/templates/operator-crds-apply-job.yaml deleted file mode 100644 index bfc14c9de2..0000000000 --- a/kubernetes/helm/operator-helm-chart/templates/operator-crds-apply-job.yaml +++ /dev/null @@ -1,49 +0,0 @@ -{{/* -Applies the CRDs staged in the operator-crds ConfigMap directly via kubectl, -bypassing Helm's own resource-ownership tracking (see the comment in -operator-crds.yaml for why). Runs before every install and upgrade so -existing clusters — including ones whose CRDs came from an older chart -version's crds/ directory — always end up with the current CRD content. -*/}} -apiVersion: batch/v1 -kind: Job -metadata: - name: "{{ include "gateway-operator.fullname" . }}-apply-crds" - namespace: {{ .Release.Namespace }} - labels: - app.kubernetes.io/name: {{ include "gateway-operator.name" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - annotations: - "helm.sh/hook": pre-install,pre-upgrade - "helm.sh/hook-weight": "1" - "helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded -spec: - template: - metadata: - name: "{{ include "gateway-operator.fullname" . }}-apply-crds" - spec: - serviceAccountName: {{ include "gateway-operator.fullname" . }}-crd-manager - restartPolicy: Never - containers: - - name: apply-crds - image: "{{ .Values.cleanupJob.image.repository }}:{{ .Values.cleanupJob.image.tag }}" - imagePullPolicy: {{ .Values.cleanupJob.image.pullPolicy }} - command: - - /bin/sh - - -c - - | - set -e - echo "Applying gateway-operator CRDs..." - for f in /crds/*.yaml; do - echo " kubectl apply --server-side -f $f" - kubectl apply --server-side --force-conflicts -f "$f" - done - echo "CRDs applied." - volumeMounts: - - name: crds - mountPath: /crds - volumes: - - name: crds - configMap: - name: {{ include "gateway-operator.fullname" . }}-operator-crds diff --git a/kubernetes/helm/operator-helm-chart/templates/operator-crds.yaml b/kubernetes/helm/operator-helm-chart/templates/operator-crds.yaml deleted file mode 100644 index a4514d0f3b..0000000000 --- a/kubernetes/helm/operator-helm-chart/templates/operator-crds.yaml +++ /dev/null @@ -1,46 +0,0 @@ -{{/* -Operator CRDs, staged as a ConfigMap for operator-crds-apply-job.yaml to -kubectl-apply. - -The CRDs are served at two versions (v1 storage, v1alpha1 served) with -conversion strategy None: the v1alpha1 and v1 schemas are field-identical -(the promotion changed only the version label, see api/v1alpha1/conversion.go), -so no real field transformation is needed. If a future change to these types -actually requires per-field conversion, revisit this in favor of a real -conversion webhook (the Hub()/ConvertTo()/ConvertFrom() Go types are already -in place for that — see kubernetes/gateway-operator/api/v1alpha1/conversion.go). - -This ConfigMap (and the Job that applies it) exist instead of rendering the -CRDs directly as ordinary Helm-tracked resources, and instead of Helm's -built-in crds/ directory, because: - - crds/ is only applied on `helm install`, never updated on `helm upgrade`, - so an existing install would never receive the new v1 version. - - Rendering the CRDs as normal templated resources would fail on both - fresh installs and upgrades for any CRD that already exists from an - older chart's crds/ directory, since crds/-installed objects never carry - Helm's ownership annotations ("resource already exists and is not - managed by this release"). -kubectl apply (in operator-crds-apply-job.yaml) doesn't check Helm's -ownership bookkeeping at all, so it works uniformly for fresh installs and -upgrades regardless of how (or whether) the CRD previously existed. -*/}} -apiVersion: v1 -kind: ConfigMap -metadata: - name: {{ include "gateway-operator.fullname" . }}-operator-crds - namespace: {{ .Release.Namespace }} - labels: - app.kubernetes.io/name: {{ include "gateway-operator.name" . }} - app.kubernetes.io/instance: {{ .Release.Name }} - app.kubernetes.io/managed-by: {{ .Release.Service }} - annotations: - "helm.sh/hook": pre-install,pre-upgrade - "helm.sh/hook-weight": "0" - "helm.sh/hook-delete-policy": before-hook-creation -data: -{{- range $path, $_ := .Files.Glob "files/operator-crds/*.yaml" }} -{{- $crd := $.Files.Get $path | fromYaml }} -{{- $_ := set $crd.spec "conversion" (dict "strategy" "None") }} - {{ base $path }}: | -{{ toYaml $crd | indent 4 }} -{{- end }} From 874cbe587d72a4c7da5a56077ef52900b34967f9 Mon Sep 17 00:00:00 2001 From: Dineth Date: Tue, 21 Jul 2026 15:10:11 +0530 Subject: [PATCH 10/12] bump app version --- kubernetes/helm/operator-helm-chart/Chart.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kubernetes/helm/operator-helm-chart/Chart.yaml b/kubernetes/helm/operator-helm-chart/Chart.yaml index a9c4f2a4e5..906c30ee8d 100644 --- a/kubernetes/helm/operator-helm-chart/Chart.yaml +++ b/kubernetes/helm/operator-helm-chart/Chart.yaml @@ -3,4 +3,4 @@ name: gateway-operator description: Helm chart to install the Gateway Operator type: application version: 0.10.0 -appVersion: "0.8.0" \ No newline at end of file +appVersion: "0.10.0" \ No newline at end of file From 42f641cfd2744e4e7e7065b63175c43c56ee1911 Mon Sep 17 00:00:00 2001 From: Dineth Date: Tue, 21 Jul 2026 15:37:36 +0530 Subject: [PATCH 11/12] Update Gateway Operator to version 0.10.0 in Helm chart and documentation --- kubernetes/gateway-operator/README.md | 2 +- kubernetes/helm/operator-helm-chart/README.md | 16 ++++++++-------- .../helm/operator-helm-chart/templates/NOTES.txt | 4 ++-- kubernetes/helm/operator-helm-chart/values.yaml | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/kubernetes/gateway-operator/README.md b/kubernetes/gateway-operator/README.md index 1cd0192ba1..b17633ae6e 100644 --- a/kubernetes/gateway-operator/README.md +++ b/kubernetes/gateway-operator/README.md @@ -35,7 +35,7 @@ helm upgrade --install \ ## 2. Install Gateway Operator ```sh -helm install my-gateway-operator oci://ghcr.io/wso2/api-platform/helm-charts/gateway-operator --version 0.8.0 +helm install my-gateway-operator oci://ghcr.io/wso2/api-platform/helm-charts/gateway-operator --version 0.10.0 ``` --- diff --git a/kubernetes/helm/operator-helm-chart/README.md b/kubernetes/helm/operator-helm-chart/README.md index a5939998b7..fa78dcdece 100644 --- a/kubernetes/helm/operator-helm-chart/README.md +++ b/kubernetes/helm/operator-helm-chart/README.md @@ -32,7 +32,7 @@ helm install apip-operator ./operator-helm-chart --namespace gateway-operator-sy ```bash helm install apip-operator ./operator-helm-chart \ --namespace gateway-operator-system --create-namespace \ - --set image.tag=0.8.0 \ + --set image.tag=0.10.0 \ --set gateway.controlPlaneHost=http://my-control-plane:3001 ``` @@ -52,7 +52,7 @@ helm install apip-operator oci://ghcr.io/wso2/api-platform/helm-charts/gateway-o | `replicaCount` | Number of operator replicas | `1` | | `watchNamespaces` | Namespaces to watch (cluster-wide if empty) | `[]` | | `image.repository` | Operator image repository | `ghcr.io/wso2/api-platform/gateway-operator` | -| `image.tag` | Operator image tag | `0.8.0` | +| `image.tag` | Operator image tag | `0.10.0` | | `image.pullPolicy` | Image pull policy | `Always` | | `serviceAccount.create` | Create service account | `true` | | `serviceAccount.name` | Service account name | `controller-manager` | @@ -128,7 +128,7 @@ The two most commonly used kinds: Defines a gateway instance. `spec.apiSelector` is required; the gateway topology (replicas, service types, images, TLS, …) is supplied through a referenced ConfigMap via `spec.configRef`. ```yaml -apiVersion: gateway.api-platform.wso2.com/v1alpha1 +apiVersion: gateway.api-platform.wso2.com/v1 kind: APIGateway metadata: name: my-gateway @@ -149,7 +149,7 @@ spec: Defines an API deployed onto matching gateways. ```yaml -apiVersion: gateway.api-platform.wso2.com/v1alpha1 +apiVersion: gateway.api-platform.wso2.com/v1 kind: RestApi metadata: name: my-api @@ -195,7 +195,7 @@ To control gateway topology (separate controller / data-plane replica counts, a ```bash kubectl apply -f - < Date: Tue, 21 Jul 2026 17:22:39 +0530 Subject: [PATCH 12/12] Update API version to v1 in APIGateway and RestApi samples --- .../gateway-operator/config/samples/api_v1_apigateway.yaml | 6 +++--- .../gateway-operator/config/samples/api_v1_restapi.yaml | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/kubernetes/gateway-operator/config/samples/api_v1_apigateway.yaml b/kubernetes/gateway-operator/config/samples/api_v1_apigateway.yaml index a836635730..51fae93f4c 100644 --- a/kubernetes/gateway-operator/config/samples/api_v1_apigateway.yaml +++ b/kubernetes/gateway-operator/config/samples/api_v1_apigateway.yaml @@ -1,7 +1,7 @@ --- # Example 1: Cluster-scoped APIGateway # This apigateway accepts APIs from ANY namespace -apiVersion: gateway.api-platform.wso2.com/v1alpha1 +apiVersion: gateway.api-platform.wso2.com/v1 kind: APIGateway metadata: name: cluster-gateway @@ -349,7 +349,7 @@ data: controller: image: repository: ghcr.io/wso2/api-platform/gateway-controller - tag: "1.0.0" + tag: "1.2.0-alpha2" pullPolicy: Always imagePullSecrets: [] service: @@ -484,7 +484,7 @@ data: gatewayRuntime: image: repository: ghcr.io/wso2/api-platform/gateway-runtime - tag: "1.0.0" + tag: "1.2.0-alpha2" pullPolicy: Always imagePullSecrets: [] service: diff --git a/kubernetes/gateway-operator/config/samples/api_v1_restapi.yaml b/kubernetes/gateway-operator/config/samples/api_v1_restapi.yaml index 29286a9dbf..bc76b35516 100644 --- a/kubernetes/gateway-operator/config/samples/api_v1_restapi.yaml +++ b/kubernetes/gateway-operator/config/samples/api_v1_restapi.yaml @@ -1,6 +1,6 @@ --- # Example 1: API with explicit gateway references (multiple gateways) -apiVersion: gateway.api-platform.wso2.com/v1alpha1 +apiVersion: gateway.api-platform.wso2.com/v1 kind: RestApi metadata: name: api-with-gateway-refs @@ -41,7 +41,7 @@ spec: --- # Example 1: API with explicit gateway references (multiple gateways) -apiVersion: gateway.api-platform.wso2.com/v1alpha1 +apiVersion: gateway.api-platform.wso2.com/v1 kind: RestApi metadata: name: api-with-gateway-refs-1 @@ -77,7 +77,7 @@ spec: # Example 3: API routing through a reusable upstreamDefinition with a per-upstream connect timeout. # The upstream references the definition by name (url XOR ref); the connect timeout bounds TCP # connection establishment to the backend. -apiVersion: gateway.api-platform.wso2.com/v1alpha1 +apiVersion: gateway.api-platform.wso2.com/v1 kind: RestApi metadata: name: api-with-upstream-definition