diff --git a/kubernetes/gateway-operator/PROJECT b/kubernetes/gateway-operator/PROJECT index 5380ec5106..82102c211e 100644 --- a/kubernetes/gateway-operator/PROJECT +++ b/kubernetes/gateway-operator/PROJECT @@ -14,6 +14,13 @@ resources: controller: true domain: gateway.api-platform.wso2.com kind: RestApi + path: github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1 + version: 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 +29,13 @@ resources: controller: true domain: gateway.api-platform.wso2.com kind: APIGateway + path: github.com/wso2/api-platform/kubernetes/gateway-operator/api/v1 + version: 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/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/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/api/v1alpha1/crd_schema_identity_test.go b/kubernetes/gateway-operator/api/v1alpha1/crd_schema_identity_test.go new file mode 100644 index 0000000000..6b2c7ee9c5 --- /dev/null +++ b/kubernetes/gateway-operator/api/v1alpha1/crd_schema_identity_test.go @@ -0,0 +1,168 @@ +/* +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 (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 +// 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/gateway-operator/cmd/main.go b/kubernetes/gateway-operator/cmd/main.go index d0f83aa312..941a9fa1a8 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 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/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/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 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/Chart.yaml b/kubernetes/helm/operator-helm-chart/Chart.yaml index 7b6d567bef..906c30ee8d 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 -appVersion: "0.8.0" \ No newline at end of file +version: 0.10.0 +appVersion: "0.10.0" \ No newline at end of file diff --git a/kubernetes/helm/operator-helm-chart/README.md b/kubernetes/helm/operator-helm-chart/README.md index a2d5a89f94..fa78dcdece 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.10.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.10.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,60 @@ 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 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: -### 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/v1 +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/v1 +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 +172,7 @@ spec: ```bash helm install apip-operator ./operator-helm-chart \ - --namespace api-platform \ + --namespace gateway-operator-system \ --create-namespace ``` @@ -154,32 +180,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 - < **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 ```bash helm upgrade apip-operator ./operator-helm-chart \ - --namespace api-platform \ - --set image.tag=v2.0.0 + --namespace gateway-operator-system \ + --set image.tag=0.11.0 ``` ## Uninstallation @@ -323,90 +383,77 @@ helm upgrade apip-operator ./operator-helm-chart \ ### Uninstall the Release ```bash -helm uninstall apip-operator --namespace api-platform +helm uninstall apip-operator --namespace gateway-operator-system ``` -**Note:** This will not delete CRDs. To delete CRDs manually: +**Note:** This does not delete the CRDs (Helm never removes CRDs installed from `crds/`). To delete them manually: ```bash -kubectl delete crd gatewayconfiguration.api.api-platform.wso2.com -kubectl delete crd apiconfiguration.api.api-platform.wso2.com +kubectl get crd -o name | grep gateway.api-platform.wso2.com | xargs -r kubectl delete ``` ## Troubleshooting ### Operator Not Starting -Check operator logs: -```bash -kubectl logs deployment/controller-manager -n api-platform -``` - -Check events: +Check operator logs and events: ```bash -kubectl get events -n api-platform --sort-by='.lastTimestamp' +kubectl logs deployment/apip-operator-gateway-operator -n gateway-operator-system +kubectl get events -n gateway-operator-system --sort-by='.lastTimestamp' ``` ### Gateway Not Deploying -Check operator logs for reconciliation errors: +Check operator logs for reconciliation errors, then describe the resource: ```bash -kubectl logs deployment/controller-manager -n api-platform | grep -i error -``` - -Describe the gateway configuration: -```bash -kubectl describe gatewayconfiguration +kubectl logs deployment/apip-operator-gateway-operator -n gateway-operator-system | grep -i error +kubectl describe apigateway ``` ### CRDs Not Installing -Verify CRDs are installed: -```bash -kubectl get crd | grep api-platform.wso2.com -``` - -Manually install CRDs if needed: +CRDs are installed from the chart's `crds/` directory on `helm install`. Verify: ```bash -kubectl apply -f crds/ +kubectl get crd | grep gateway.api-platform.wso2.com ``` +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 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 +- **`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 +- **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 +471,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/crds/gateway.api-platform.wso2.com_apigateways.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_apigateways.yaml index 97d6234633..a289afe7d2 100644 --- 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 @@ -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: @@ -762,8 +2133,8 @@ spec: 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 + 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 @@ -1145,7 +2516,7 @@ spec: 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 + This field depends on the DynamicResourceAllocation feature gate. This field is immutable. It can only be set for containers. @@ -1219,9 +2590,10 @@ spec: operator: description: |- Operator represents a key's relationship to the value. - Valid operators are Exists and Equal. Defaults to Equal. + 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: |- @@ -1381,6 +2753,6 @@ spec: type: object type: object served: true - storage: 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/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/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/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/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/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/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/crds/gateway.api-platform.wso2.com_llmproviders.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmproviders.yaml index 3cc7e1366c..72fb9c33fb 100644 --- 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 @@ -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. @@ -253,8 +253,9 @@ spec: 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. + 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: |- @@ -263,8 +264,9 @@ spec: pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ type: string name: - description: Name Unique identifier for this upstream definition - (referenced by upstream.ref). + 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\-_]+$ @@ -283,13 +285,11 @@ spec: description: Upstreams List of backend targets with optional weights for load balancing. items: - description: UpstreamTarget is a single backend target within + description: WeightedUpstream 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\-._~:/?#\[\]@!$&'()*+,;=%]+$ + description: Url Backend URL (host and port; no path) type: string weight: description: |- @@ -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/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_llmprovidertemplates.yaml b/kubernetes/helm/operator-helm-chart/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/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/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/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/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/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/crds/gateway.api-platform.wso2.com_mcps.yaml b/kubernetes/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_mcps.yaml index 096fac435a..922c91fba6 100644 --- 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 @@ -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. @@ -277,8 +277,9 @@ spec: 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. + 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: |- @@ -287,8 +288,9 @@ spec: pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ type: string name: - description: Name Unique identifier for this upstream definition - (referenced by upstream.ref). + 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\-_]+$ @@ -307,13 +309,11 @@ spec: description: Upstreams List of backend targets with optional weights for load balancing. items: - description: UpstreamTarget is a single backend target within + description: WeightedUpstream 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\-._~:/?#\[\]@!$&'()*+,;=%]+$ + description: Url Backend URL (host and port; no path) type: string weight: description: |- @@ -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/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 index 00e7fd4d24..5f24ae37a1 100644 --- 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 @@ -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 @@ -53,10 +53,76 @@ spec: operations: description: Operations List of HTTP operations/routes items: - description: Operation defines model for Operation. + 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 + description: Method HTTP method (simple form; ignored when Match + is set). enum: - GET - POST @@ -68,6 +134,7 @@ spec: 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: @@ -113,10 +180,10 @@ spec: pattern: ^\d+(\.\d+)?(ms|s|m|h)$ type: string type: object - required: - - method - - path 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: @@ -169,6 +236,16 @@ spec: 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. @@ -186,6 +263,16 @@ spec: 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. @@ -205,12 +292,14 @@ spec: upstreamDefinitions: description: |- UpstreamDefinitions is the list of reusable upstream definitions (with optional connect - timeout) that upstream.ref can reference. + 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 - load-balancing targets. Referenced from an upstream via its `ref` field. Shared by RestApi, - LLM Provider, and MCP; mirrors the management-API UpstreamDefinition schema. + 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: |- @@ -219,8 +308,9 @@ spec: pattern: ^/[a-zA-Z0-9\-._~!$&'()*+,;=:@%/]*[^/]$ type: string name: - description: Name Unique identifier for this upstream definition - (referenced by upstream.ref). + 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\-_]+$ @@ -239,13 +329,11 @@ spec: description: Upstreams List of backend targets with optional weights for load balancing. items: - description: UpstreamTarget is a single backend target within + description: WeightedUpstream 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\-._~:/?#\[\]@!$&'()*+,;=%]+$ + description: Url Backend URL (host and port; no path) type: string weight: description: |- @@ -272,7 +360,10 @@ spec: description: Vhosts Custom virtual hosts/domains for the API properties: main: - description: Main Custom virtual host/domain for production traffic + 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 @@ -358,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/helm/operator-helm-chart/crds/gateway.api-platform.wso2.com_subscriptionplans.yaml b/kubernetes/helm/operator-helm-chart/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/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/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/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/NOTES.txt b/kubernetes/helm/operator-helm-chart/templates/NOTES.txt index ae2b24e4d8..24c97c0fb0 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) + - 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 }} @@ -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 - <= 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"