From 50e51b59dfd560c907856951011db4545544e54b Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Sun, 1 Feb 2026 15:14:49 -0800 Subject: [PATCH 1/5] feat(api/gateway): add DirectResponse CRD for static HTTP responses Add a new Gateway API extension CRD called DirectResponse that allows HTTPRoute rules to return static HTTP responses without a backend service. This supports the HTTP-01 ACME challenge workflow for serving challenge tokens directly from Envoy. Changes: - Create api/gateway/v1alpha1/ package with DirectResponse type definition - Implement DirectResponseSpec with status code, content-type, headers, and body - Generate deepcopy and register helpers via k8s.io/code-generator - Update codegen/update.sh to include v1alpha1 in code generation pipeline - Generate versioned client code for gateway.apoxy.dev/v1alpha1 Task: Phase 3 - Tasks 3.1, 3.2, 3.3 (DirectResponse CRD creation) --- api/gateway/v1alpha1/directresponse_types.go | 98 ++++++++++ api/gateway/v1alpha1/doc.go | 7 + api/gateway/v1alpha1/groupversion_info.go | 5 + api/gateway/v1alpha1/zz_generated.deepcopy.go | 183 ++++++++++++++++++ api/gateway/v1alpha1/zz_generated.register.go | 69 +++++++ client/versioned/clientset.go | 13 ++ client/versioned/fake/clientset_generated.go | 7 + client/versioned/fake/register.go | 2 + client/versioned/scheme/register.go | 2 + .../versioned/typed/gateway/v1alpha1/doc.go | 19 ++ .../typed/gateway/v1alpha1/fake/doc.go | 19 ++ .../v1alpha1/fake/fake_gateway_client.go | 34 ++++ .../typed/gateway/v1alpha1/gateway_client.go | 101 ++++++++++ .../gateway/v1alpha1/generated_expansion.go | 18 ++ codegen/update.sh | 6 + 15 files changed, 583 insertions(+) create mode 100644 api/gateway/v1alpha1/directresponse_types.go create mode 100644 api/gateway/v1alpha1/doc.go create mode 100644 api/gateway/v1alpha1/groupversion_info.go create mode 100644 api/gateway/v1alpha1/zz_generated.deepcopy.go create mode 100644 api/gateway/v1alpha1/zz_generated.register.go create mode 100644 client/versioned/typed/gateway/v1alpha1/doc.go create mode 100644 client/versioned/typed/gateway/v1alpha1/fake/doc.go create mode 100644 client/versioned/typed/gateway/v1alpha1/fake/fake_gateway_client.go create mode 100644 client/versioned/typed/gateway/v1alpha1/gateway_client.go create mode 100644 client/versioned/typed/gateway/v1alpha1/generated_expansion.go diff --git a/api/gateway/v1alpha1/directresponse_types.go b/api/gateway/v1alpha1/directresponse_types.go new file mode 100644 index 0000000..b533ab1 --- /dev/null +++ b/api/gateway/v1alpha1/directresponse_types.go @@ -0,0 +1,98 @@ +package v1alpha1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +// BodyType defines how the response body is specified. +// +kubebuilder:validation:Enum=Inline +type BodyType string + +const ( + // BodyTypeInline indicates the body is specified inline as a string. + BodyTypeInline BodyType = "Inline" +) + +// CustomResponseBody defines the body of the direct response. +type CustomResponseBody struct { + // Type specifies how the body is provided. + // Currently only "Inline" is supported. + // +kubebuilder:validation:Required + Type BodyType `json:"type"` + + // Inline is the literal body content when Type is "Inline". + // +optional + Inline *string `json:"inline,omitempty"` +} + +// Header defines a custom HTTP header to include in the response. +type Header struct { + // Name is the header name. + // +kubebuilder:validation:Required + // +kubebuilder:validation:MinLength=1 + Name string `json:"name"` + + // Value is the header value. + // +kubebuilder:validation:Required + Value string `json:"value"` +} + +// DirectResponseSpec defines the desired state of DirectResponse. +type DirectResponseSpec struct { + // StatusCode is the HTTP status code to return. + // Defaults to 200 if not specified. + // +kubebuilder:validation:Minimum=100 + // +kubebuilder:validation:Maximum=599 + // +kubebuilder:default=200 + // +optional + StatusCode *int32 `json:"statusCode,omitempty"` + + // ContentType is the Content-Type header value. + // Defaults to "text/plain" if not specified. + // +kubebuilder:default="text/plain" + // +optional + ContentType *string `json:"contentType,omitempty"` + + // Headers are additional HTTP headers to include in the response. + // +optional + Headers []Header `json:"headers,omitempty"` + + // Body is the response body configuration. + // +optional + Body *CustomResponseBody `json:"body,omitempty"` +} + +// DirectResponseStatus defines the observed state of DirectResponse. +type DirectResponseStatus struct { + // Conditions describe the current conditions of the DirectResponse. + // +optional + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:resource:categories=gateway-api +// +kubebuilder:printcolumn:name="Status Code",type=integer,JSONPath=`.spec.statusCode` +// +kubebuilder:printcolumn:name="Age",type=date,JSONPath=`.metadata.creationTimestamp` +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// DirectResponse is the Schema for the directresponses API. +// It defines a static response that can be returned by an HTTPRoute +// instead of forwarding to a backend. +type DirectResponse struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec DirectResponseSpec `json:"spec,omitempty"` + Status DirectResponseStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// DirectResponseList contains a list of DirectResponse. +type DirectResponseList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []DirectResponse `json:"items"` +} diff --git a/api/gateway/v1alpha1/doc.go b/api/gateway/v1alpha1/doc.go new file mode 100644 index 0000000..86d479f --- /dev/null +++ b/api/gateway/v1alpha1/doc.go @@ -0,0 +1,7 @@ +// +k8s:openapi-gen=true +// +kubebuilder:object:generate=true +// +groupName=gateway.apoxy.dev +// +k8s:deepcopy-gen=package,register + +// Package v1alpha1 contains API Schema definitions for the gateway v1alpha1 API group. +package v1alpha1 diff --git a/api/gateway/v1alpha1/groupversion_info.go b/api/gateway/v1alpha1/groupversion_info.go new file mode 100644 index 0000000..bdfafcc --- /dev/null +++ b/api/gateway/v1alpha1/groupversion_info.go @@ -0,0 +1,5 @@ +package v1alpha1 + +// GroupVersion is group version used to register these objects. +// This is defined and exported by the generated register file (zz_generated.register.go) +// For backward compatibility, we import and re-export it here if needed by other packages. diff --git a/api/gateway/v1alpha1/zz_generated.deepcopy.go b/api/gateway/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 0000000..4ad42da --- /dev/null +++ b/api/gateway/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,183 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2026 Apoxy, Inc. + +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 deepcopy-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomResponseBody) DeepCopyInto(out *CustomResponseBody) { + *out = *in + if in.Inline != nil { + in, out := &in.Inline, &out.Inline + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResponseBody. +func (in *CustomResponseBody) DeepCopy() *CustomResponseBody { + if in == nil { + return nil + } + out := new(CustomResponseBody) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DirectResponse) DeepCopyInto(out *DirectResponse) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DirectResponse. +func (in *DirectResponse) DeepCopy() *DirectResponse { + if in == nil { + return nil + } + out := new(DirectResponse) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DirectResponse) 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 *DirectResponseList) DeepCopyInto(out *DirectResponseList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]DirectResponse, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DirectResponseList. +func (in *DirectResponseList) DeepCopy() *DirectResponseList { + if in == nil { + return nil + } + out := new(DirectResponseList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DirectResponseList) 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 *DirectResponseSpec) DeepCopyInto(out *DirectResponseSpec) { + *out = *in + if in.StatusCode != nil { + in, out := &in.StatusCode, &out.StatusCode + *out = new(int32) + **out = **in + } + if in.ContentType != nil { + in, out := &in.ContentType, &out.ContentType + *out = new(string) + **out = **in + } + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = make([]Header, len(*in)) + copy(*out, *in) + } + if in.Body != nil { + in, out := &in.Body, &out.Body + *out = new(CustomResponseBody) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DirectResponseSpec. +func (in *DirectResponseSpec) DeepCopy() *DirectResponseSpec { + if in == nil { + return nil + } + out := new(DirectResponseSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DirectResponseStatus) DeepCopyInto(out *DirectResponseStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DirectResponseStatus. +func (in *DirectResponseStatus) DeepCopy() *DirectResponseStatus { + if in == nil { + return nil + } + out := new(DirectResponseStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Header) DeepCopyInto(out *Header) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Header. +func (in *Header) DeepCopy() *Header { + if in == nil { + return nil + } + out := new(Header) + in.DeepCopyInto(out) + return out +} diff --git a/api/gateway/v1alpha1/zz_generated.register.go b/api/gateway/v1alpha1/zz_generated.register.go new file mode 100644 index 0000000..9dea177 --- /dev/null +++ b/api/gateway/v1alpha1/zz_generated.register.go @@ -0,0 +1,69 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2026 Apoxy, Inc. + +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 register-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" +) + +// GroupName specifies the group name used to register the objects. +const GroupName = "gateway.apoxy.dev" + +// GroupVersion specifies the group and the version used to register the objects. +var GroupVersion = v1.GroupVersion{Group: GroupName, Version: "v1alpha1"} + +// SchemeGroupVersion is group version used to register these objects +// Deprecated: use GroupVersion instead. +var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} + +// Resource takes an unqualified resource and returns a Group qualified GroupResource +func Resource(resource string) schema.GroupResource { + return SchemeGroupVersion.WithResource(resource).GroupResource() +} + +var ( + // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. + SchemeBuilder runtime.SchemeBuilder + localSchemeBuilder = &SchemeBuilder + // Deprecated: use Install instead + AddToScheme = localSchemeBuilder.AddToScheme + Install = localSchemeBuilder.AddToScheme +) + +func init() { + // We only register manually written functions here. The registration of the + // generated functions takes place in the generated files. The separation + // makes the code compile even when the generated files are missing. + localSchemeBuilder.Register(addKnownTypes) +} + +// Adds the list of known types to Scheme. +func addKnownTypes(scheme *runtime.Scheme) error { + scheme.AddKnownTypes(SchemeGroupVersion, + &DirectResponse{}, + &DirectResponseList{}, + ) + // AddToGroupVersion allows the serialization of client types like ListOptions. + v1.AddToGroupVersion(scheme, SchemeGroupVersion) + return nil +} diff --git a/client/versioned/clientset.go b/client/versioned/clientset.go index a1c6fb1..56329c7 100644 --- a/client/versioned/clientset.go +++ b/client/versioned/clientset.go @@ -27,6 +27,7 @@ import ( extensionsv1alpha1 "github.com/apoxy-dev/apoxy/client/versioned/typed/extensions/v1alpha1" extensionsv1alpha2 "github.com/apoxy-dev/apoxy/client/versioned/typed/extensions/v1alpha2" gatewayv1 "github.com/apoxy-dev/apoxy/client/versioned/typed/gateway/v1" + gatewayv1alpha1 "github.com/apoxy-dev/apoxy/client/versioned/typed/gateway/v1alpha1" gatewayv1alpha2 "github.com/apoxy-dev/apoxy/client/versioned/typed/gateway/v1alpha2" policyv1alpha1 "github.com/apoxy-dev/apoxy/client/versioned/typed/policy/v1alpha1" discovery "k8s.io/client-go/discovery" @@ -42,6 +43,7 @@ type Interface interface { ExtensionsV1alpha1() extensionsv1alpha1.ExtensionsV1alpha1Interface ExtensionsV1alpha2() extensionsv1alpha2.ExtensionsV1alpha2Interface GatewayV1() gatewayv1.GatewayV1Interface + GatewayV1alpha1() gatewayv1alpha1.GatewayV1alpha1Interface GatewayV1alpha2() gatewayv1alpha2.GatewayV1alpha2Interface PolicyV1alpha1() policyv1alpha1.PolicyV1alpha1Interface } @@ -55,6 +57,7 @@ type Clientset struct { extensionsV1alpha1 *extensionsv1alpha1.ExtensionsV1alpha1Client extensionsV1alpha2 *extensionsv1alpha2.ExtensionsV1alpha2Client gatewayV1 *gatewayv1.GatewayV1Client + gatewayV1alpha1 *gatewayv1alpha1.GatewayV1alpha1Client gatewayV1alpha2 *gatewayv1alpha2.GatewayV1alpha2Client policyV1alpha1 *policyv1alpha1.PolicyV1alpha1Client } @@ -89,6 +92,11 @@ func (c *Clientset) GatewayV1() gatewayv1.GatewayV1Interface { return c.gatewayV1 } +// GatewayV1alpha1 retrieves the GatewayV1alpha1Client +func (c *Clientset) GatewayV1alpha1() gatewayv1alpha1.GatewayV1alpha1Interface { + return c.gatewayV1alpha1 +} + // GatewayV1alpha2 retrieves the GatewayV1alpha2Client func (c *Clientset) GatewayV1alpha2() gatewayv1alpha2.GatewayV1alpha2Interface { return c.gatewayV1alpha2 @@ -167,6 +175,10 @@ func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, if err != nil { return nil, err } + cs.gatewayV1alpha1, err = gatewayv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) + if err != nil { + return nil, err + } cs.gatewayV1alpha2, err = gatewayv1alpha2.NewForConfigAndClient(&configShallowCopy, httpClient) if err != nil { return nil, err @@ -202,6 +214,7 @@ func New(c rest.Interface) *Clientset { cs.extensionsV1alpha1 = extensionsv1alpha1.New(c) cs.extensionsV1alpha2 = extensionsv1alpha2.New(c) cs.gatewayV1 = gatewayv1.New(c) + cs.gatewayV1alpha1 = gatewayv1alpha1.New(c) cs.gatewayV1alpha2 = gatewayv1alpha2.New(c) cs.policyV1alpha1 = policyv1alpha1.New(c) diff --git a/client/versioned/fake/clientset_generated.go b/client/versioned/fake/clientset_generated.go index 515e2f1..080938a 100644 --- a/client/versioned/fake/clientset_generated.go +++ b/client/versioned/fake/clientset_generated.go @@ -31,6 +31,8 @@ import ( fakeextensionsv1alpha2 "github.com/apoxy-dev/apoxy/client/versioned/typed/extensions/v1alpha2/fake" gatewayv1 "github.com/apoxy-dev/apoxy/client/versioned/typed/gateway/v1" fakegatewayv1 "github.com/apoxy-dev/apoxy/client/versioned/typed/gateway/v1/fake" + gatewayv1alpha1 "github.com/apoxy-dev/apoxy/client/versioned/typed/gateway/v1alpha1" + fakegatewayv1alpha1 "github.com/apoxy-dev/apoxy/client/versioned/typed/gateway/v1alpha1/fake" gatewayv1alpha2 "github.com/apoxy-dev/apoxy/client/versioned/typed/gateway/v1alpha2" fakegatewayv1alpha2 "github.com/apoxy-dev/apoxy/client/versioned/typed/gateway/v1alpha2/fake" policyv1alpha1 "github.com/apoxy-dev/apoxy/client/versioned/typed/policy/v1alpha1" @@ -126,6 +128,11 @@ func (c *Clientset) GatewayV1() gatewayv1.GatewayV1Interface { return &fakegatewayv1.FakeGatewayV1{Fake: &c.Fake} } +// GatewayV1alpha1 retrieves the GatewayV1alpha1Client +func (c *Clientset) GatewayV1alpha1() gatewayv1alpha1.GatewayV1alpha1Interface { + return &fakegatewayv1alpha1.FakeGatewayV1alpha1{Fake: &c.Fake} +} + // GatewayV1alpha2 retrieves the GatewayV1alpha2Client func (c *Clientset) GatewayV1alpha2() gatewayv1alpha2.GatewayV1alpha2Interface { return &fakegatewayv1alpha2.FakeGatewayV1alpha2{Fake: &c.Fake} diff --git a/client/versioned/fake/register.go b/client/versioned/fake/register.go index 897c32a..29bd240 100644 --- a/client/versioned/fake/register.go +++ b/client/versioned/fake/register.go @@ -24,6 +24,7 @@ import ( extensionsv1alpha1 "github.com/apoxy-dev/apoxy/api/extensions/v1alpha1" extensionsv1alpha2 "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2" gatewayv1 "github.com/apoxy-dev/apoxy/api/gateway/v1" + gatewayv1alpha1 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha1" gatewayv1alpha2 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha2" policyv1alpha1 "github.com/apoxy-dev/apoxy/api/policy/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -43,6 +44,7 @@ var localSchemeBuilder = runtime.SchemeBuilder{ extensionsv1alpha1.AddToScheme, extensionsv1alpha2.AddToScheme, gatewayv1.AddToScheme, + gatewayv1alpha1.AddToScheme, gatewayv1alpha2.AddToScheme, policyv1alpha1.AddToScheme, } diff --git a/client/versioned/scheme/register.go b/client/versioned/scheme/register.go index c1c5f20..c910642 100644 --- a/client/versioned/scheme/register.go +++ b/client/versioned/scheme/register.go @@ -24,6 +24,7 @@ import ( extensionsv1alpha1 "github.com/apoxy-dev/apoxy/api/extensions/v1alpha1" extensionsv1alpha2 "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2" gatewayv1 "github.com/apoxy-dev/apoxy/api/gateway/v1" + gatewayv1alpha1 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha1" gatewayv1alpha2 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha2" policyv1alpha1 "github.com/apoxy-dev/apoxy/api/policy/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -43,6 +44,7 @@ var localSchemeBuilder = runtime.SchemeBuilder{ extensionsv1alpha1.AddToScheme, extensionsv1alpha2.AddToScheme, gatewayv1.AddToScheme, + gatewayv1alpha1.AddToScheme, gatewayv1alpha2.AddToScheme, policyv1alpha1.AddToScheme, } diff --git a/client/versioned/typed/gateway/v1alpha1/doc.go b/client/versioned/typed/gateway/v1alpha1/doc.go new file mode 100644 index 0000000..288f055 --- /dev/null +++ b/client/versioned/typed/gateway/v1alpha1/doc.go @@ -0,0 +1,19 @@ +/* +Copyright 2026 Apoxy, Inc. + +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 client-gen. DO NOT EDIT. + +// This package has the automatically generated typed clients. +package v1alpha1 diff --git a/client/versioned/typed/gateway/v1alpha1/fake/doc.go b/client/versioned/typed/gateway/v1alpha1/fake/doc.go new file mode 100644 index 0000000..f35cadb --- /dev/null +++ b/client/versioned/typed/gateway/v1alpha1/fake/doc.go @@ -0,0 +1,19 @@ +/* +Copyright 2026 Apoxy, Inc. + +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 client-gen. DO NOT EDIT. + +// Package fake has the automatically generated clients. +package fake diff --git a/client/versioned/typed/gateway/v1alpha1/fake/fake_gateway_client.go b/client/versioned/typed/gateway/v1alpha1/fake/fake_gateway_client.go new file mode 100644 index 0000000..a7d521f --- /dev/null +++ b/client/versioned/typed/gateway/v1alpha1/fake/fake_gateway_client.go @@ -0,0 +1,34 @@ +/* +Copyright 2026 Apoxy, Inc. + +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 client-gen. DO NOT EDIT. + +package fake + +import ( + rest "k8s.io/client-go/rest" + testing "k8s.io/client-go/testing" +) + +type FakeGatewayV1alpha1 struct { + *testing.Fake +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *FakeGatewayV1alpha1) RESTClient() rest.Interface { + var ret *rest.RESTClient + return ret +} diff --git a/client/versioned/typed/gateway/v1alpha1/gateway_client.go b/client/versioned/typed/gateway/v1alpha1/gateway_client.go new file mode 100644 index 0000000..a50d044 --- /dev/null +++ b/client/versioned/typed/gateway/v1alpha1/gateway_client.go @@ -0,0 +1,101 @@ +/* +Copyright 2026 Apoxy, Inc. + +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 client-gen. DO NOT EDIT. + +package v1alpha1 + +import ( + http "net/http" + + gatewayv1alpha1 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha1" + scheme "github.com/apoxy-dev/apoxy/client/versioned/scheme" + rest "k8s.io/client-go/rest" +) + +type GatewayV1alpha1Interface interface { + RESTClient() rest.Interface +} + +// GatewayV1alpha1Client is used to interact with features provided by the gateway.apoxy.dev group. +type GatewayV1alpha1Client struct { + restClient rest.Interface +} + +// NewForConfig creates a new GatewayV1alpha1Client for the given config. +// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), +// where httpClient was generated with rest.HTTPClientFor(c). +func NewForConfig(c *rest.Config) (*GatewayV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + httpClient, err := rest.HTTPClientFor(&config) + if err != nil { + return nil, err + } + return NewForConfigAndClient(&config, httpClient) +} + +// NewForConfigAndClient creates a new GatewayV1alpha1Client for the given config and http client. +// Note the http client provided takes precedence over the configured transport values. +func NewForConfigAndClient(c *rest.Config, h *http.Client) (*GatewayV1alpha1Client, error) { + config := *c + if err := setConfigDefaults(&config); err != nil { + return nil, err + } + client, err := rest.RESTClientForConfigAndClient(&config, h) + if err != nil { + return nil, err + } + return &GatewayV1alpha1Client{client}, nil +} + +// NewForConfigOrDie creates a new GatewayV1alpha1Client for the given config and +// panics if there is an error in the config. +func NewForConfigOrDie(c *rest.Config) *GatewayV1alpha1Client { + client, err := NewForConfig(c) + if err != nil { + panic(err) + } + return client +} + +// New creates a new GatewayV1alpha1Client for the given RESTClient. +func New(c rest.Interface) *GatewayV1alpha1Client { + return &GatewayV1alpha1Client{c} +} + +func setConfigDefaults(config *rest.Config) error { + gv := gatewayv1alpha1.SchemeGroupVersion + config.GroupVersion = &gv + config.APIPath = "/apis" + config.NegotiatedSerializer = rest.CodecFactoryForGeneratedClient(scheme.Scheme, scheme.Codecs).WithoutConversion() + + if config.UserAgent == "" { + config.UserAgent = rest.DefaultKubernetesUserAgent() + } + + return nil +} + +// RESTClient returns a RESTClient that is used to communicate +// with API server by this client implementation. +func (c *GatewayV1alpha1Client) RESTClient() rest.Interface { + if c == nil { + return nil + } + return c.restClient +} diff --git a/client/versioned/typed/gateway/v1alpha1/generated_expansion.go b/client/versioned/typed/gateway/v1alpha1/generated_expansion.go new file mode 100644 index 0000000..8447fa0 --- /dev/null +++ b/client/versioned/typed/gateway/v1alpha1/generated_expansion.go @@ -0,0 +1,18 @@ +/* +Copyright 2026 Apoxy, Inc. + +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 client-gen. DO NOT EDIT. + +package v1alpha1 diff --git a/codegen/update.sh b/codegen/update.sh index 26f2629..449af39 100755 --- a/codegen/update.sh +++ b/codegen/update.sh @@ -22,6 +22,7 @@ go run "k8s.io/code-generator/cmd/deepcopy-gen@${CODEGEN_VERSION}" \ ./api/extensions/v1alpha1 \ ./api/extensions/v1alpha2 \ ./api/gateway/v1 \ + ./api/gateway/v1alpha1 \ ./api/gateway/v1alpha2 \ ./pkg/gateway/gatewayapi \ ./pkg/gateway/ir \ @@ -39,6 +40,7 @@ go run "k8s.io/code-generator/cmd/register-gen@${CODEGEN_VERSION}" \ ./api/extensions/v1alpha1 \ ./api/extensions/v1alpha2 \ ./api/gateway/v1 \ + ./api/gateway/v1alpha1 \ ./api/gateway/v1alpha2 \ ./pkg/gateway/gatewayapi \ ./pkg/gateway/ir @@ -70,6 +72,7 @@ go run "k8s.io/code-generator/cmd/client-gen@${CODEGEN_VERSION}" \ --input "./api/extensions/v1alpha1" \ --input "./api/extensions/v1alpha2" \ --input "./api/gateway/v1" \ + --input "./api/gateway/v1alpha1" \ --input "./api/gateway/v1alpha2" \ --input "./api/policy/v1alpha1" @@ -85,6 +88,7 @@ go run "k8s.io/code-generator/cmd/lister-gen@${CODEGEN_VERSION}" \ ./api/extensions/v1alpha1 \ ./api/extensions/v1alpha2 \ ./api/gateway/v1 \ + ./api/gateway/v1alpha1 \ ./api/gateway/v1alpha2 \ ./api/policy/v1alpha1 @@ -101,6 +105,7 @@ go run "k8s.io/code-generator/cmd/informer-gen@${CODEGEN_VERSION}" \ ./api/extensions/v1alpha1 \ ./api/extensions/v1alpha2 \ ./api/gateway/v1 \ + ./api/gateway/v1alpha1 \ ./api/gateway/v1alpha2 \ ./api/policy/v1alpha1 @@ -127,5 +132,6 @@ go run "k8s.io/kube-openapi/cmd/openapi-gen@master" \ ./api/extensions/v1alpha1 \ ./api/extensions/v1alpha2 \ ./api/gateway/v1 \ + ./api/gateway/v1alpha1 \ ./api/gateway/v1alpha2 \ ./api/policy/v1alpha1 From ab8ed6a5f1329afe11bfca88c33b49ad96adf418 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Sun, 1 Feb 2026 15:40:42 -0800 Subject: [PATCH 2/5] feat(gateway): wire up DirectResponse CRD for HTTPRoute filters This commit implements the gateway API layer integration for DirectResponse CRD: 1. Added DirectResponses field to Resources struct in pkg/gateway/gatewayapi/resource.go 2. Added gatewayv1alpha1 import to resource.go and gateway.go 3. Updated processExtensionRefHTTPFilter in filters.go to handle DirectResponse filter types - Converts DirectResponse spec to IR DirectResponse struct - Handles status code and body from the CRD spec 4. Added DirectResponse collection logic in reconcileHTTPRoutes in pkg/apiserver/gateway/gateway.go - Detects DirectResponse filters in HTTPRoute rules - Fetches DirectResponse objects from the cluster - Populates res.DirectResponses for use by the translator 5. Regenerated deepcopy methods for Resources struct This enables HTTPRoute filters to reference DirectResponse resources for static HTTP responses. Related to Phase 3 task 3.4, 3.5, 3.6, 3.7 --- pkg/apiserver/gateway/gateway.go | 49 ++++++++++++++----- pkg/gateway/gatewayapi/filters.go | 28 +++++++++++ pkg/gateway/gatewayapi/resource.go | 2 + .../gatewayapi/zz_generated.deepcopy.go | 29 +++++++---- 4 files changed, 87 insertions(+), 21 deletions(-) diff --git a/pkg/apiserver/gateway/gateway.go b/pkg/apiserver/gateway/gateway.go index 84680a6..64eeb98 100644 --- a/pkg/apiserver/gateway/gateway.go +++ b/pkg/apiserver/gateway/gateway.go @@ -31,6 +31,7 @@ import ( corev1alpha2 "github.com/apoxy-dev/apoxy/api/core/v1alpha2" extensionsv1alpha2 "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2" gatewayv1 "github.com/apoxy-dev/apoxy/api/gateway/v1" + gatewayv1alpha1 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha1" gatewayv1alpha2 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha2" ) @@ -378,19 +379,43 @@ func (r *GatewayReconciler) reconcileHTTPRoutes( if filter.ExtensionRef.Group == "" { filter.ExtensionRef.Group = "extensions.apoxy.dev" } - key := extensionRefKey{ - Name: string(filter.ExtensionRef.Name), - GroupKind: schema.GroupKind{ - Group: string(filter.ExtensionRef.Group), - Kind: string(filter.ExtensionRef.Kind), - }, - } - if ref, ok := extRefs[key]; ok { - log.Info("Found extension reference", - "name", ref.GetName(), "gvk", ref.GroupVersionKind()) - res.ExtensionRefFilters = append(res.ExtensionRefFilters, *ref) + // Handle DirectResponse specially + if string(filter.ExtensionRef.Group) == "gateway.apoxy.dev" && string(filter.ExtensionRef.Kind) == "DirectResponse" { + log.Info("Processing DirectResponse filter reference", + "name", filter.ExtensionRef.Name, "group", filter.ExtensionRef.Group) + // Fetch the DirectResponse object + dr := &gatewayv1alpha1.DirectResponse{} + if err := r.Get(ctx, types.NamespacedName{Name: string(filter.ExtensionRef.Name)}, dr); err != nil { + log.Info("Unable to find DirectResponse reference", "name", filter.ExtensionRef.Name) + } else { + // Check if it's already in the list to avoid duplicates + alreadyExists := false + for _, existingDr := range res.DirectResponses { + if existingDr.Name == dr.Name { + alreadyExists = true + break + } + } + if !alreadyExists { + res.DirectResponses = append(res.DirectResponses, dr) + } + } } else { - log.Info("Unable to find extension reference", "name", key.Name, "group", key.GroupKind.Group, "kind", key.GroupKind.Kind) + // Handle other extension refs + key := extensionRefKey{ + Name: string(filter.ExtensionRef.Name), + GroupKind: schema.GroupKind{ + Group: string(filter.ExtensionRef.Group), + Kind: string(filter.ExtensionRef.Kind), + }, + } + if ref, ok := extRefs[key]; ok { + log.Info("Found extension reference", + "name", ref.GetName(), "gvk", ref.GroupVersionKind()) + res.ExtensionRefFilters = append(res.ExtensionRefFilters, *ref) + } else { + log.Info("Unable to find extension reference", "name", key.Name, "group", key.GroupKind.Group, "kind", key.GroupKind.Kind) + } } } } diff --git a/pkg/gateway/gatewayapi/filters.go b/pkg/gateway/gatewayapi/filters.go index a603779..f87506a 100644 --- a/pkg/gateway/gatewayapi/filters.go +++ b/pkg/gateway/gatewayapi/filters.go @@ -661,6 +661,34 @@ func (t *Translator) processExtensionRefHTTPFilter(extFilter *gwapiv1.LocalObjec return } + // Handle DirectResponse specially - convert to IR DirectResponse + if string(extFilter.Group) == "gateway.apoxy.dev" && string(extFilter.Kind) == "DirectResponse" { + for _, dr := range resources.DirectResponses { + if dr.Name == string(extFilter.Name) { + // Convert to IR DirectResponse + statusCode := uint32(200) + if dr.Spec.StatusCode != nil { + statusCode = uint32(*dr.Spec.StatusCode) + } + + var body *string + if dr.Spec.Body != nil && dr.Spec.Body.Inline != nil { + body = dr.Spec.Body.Inline + } + + filterContext.DirectResponse = &ir.DirectResponse{ + StatusCode: statusCode, + Body: body, + } + return + } + } + // DirectResponse not found + errMsg := fmt.Sprintf("DirectResponse %s not found", extFilter.Name) + t.processUnresolvedHTTPFilter(errMsg, filterContext) + return + } + // This list of resources will be empty unless an extension is loaded (and introduces resources) for _, res := range resources.ExtensionRefFilters { log.Debugf("Checking if resource gvk=%v name=%s matches filter %+v", res.GroupVersionKind(), res.GetName(), *extFilter) diff --git a/pkg/gateway/gatewayapi/resource.go b/pkg/gateway/gatewayapi/resource.go index 4ad509b..15ca0b7 100644 --- a/pkg/gateway/gatewayapi/resource.go +++ b/pkg/gateway/gatewayapi/resource.go @@ -22,6 +22,7 @@ import ( corev1alpha2 "github.com/apoxy-dev/apoxy/api/core/v1alpha2" extensionsv1alpha2 "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2" + gatewayv1alpha1 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha1" ) const ( @@ -64,6 +65,7 @@ type Resources struct { EdgeFunctionRevisions []*extensionsv1alpha2.EdgeFunctionRevision `json:"edgeFunctionFilters,omitempty" yaml:"edgeFunctionFilters,omitempty"` Backends []*corev1alpha2.Backend `json:"backends,omitempty" yaml:"backends,omitempty"` Proxies []*corev1alpha2.Proxy `json:"proxies,omitempty" yaml:"proxies,omitempty"` + DirectResponses []*gatewayv1alpha1.DirectResponse `json:"directResponses,omitempty" yaml:"directResponses,omitempty"` } func NewResources() *Resources { diff --git a/pkg/gateway/gatewayapi/zz_generated.deepcopy.go b/pkg/gateway/gatewayapi/zz_generated.deepcopy.go index e6c2591..c378496 100644 --- a/pkg/gateway/gatewayapi/zz_generated.deepcopy.go +++ b/pkg/gateway/gatewayapi/zz_generated.deepcopy.go @@ -1,8 +1,7 @@ //go:build !ignore_autogenerated -// +build !ignore_autogenerated /* -Copyright 2026 Apoxy, Inc. +Copyright Apoxy, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16,20 +15,22 @@ 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 deepcopy-gen. DO NOT EDIT. + +// Code generated by controller-gen. DO NOT EDIT. package gatewayapi import ( corev1alpha2 "github.com/apoxy-dev/apoxy/api/core/v1alpha2" extensionsv1alpha2 "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2" + gatewayv1alpha1 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha1" corev1 "k8s.io/api/core/v1" discoveryv1 "k8s.io/api/discovery/v1" - unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - v1 "sigs.k8s.io/gateway-api/apis/v1" - v1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" - v1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" - v1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "sigs.k8s.io/gateway-api/apis/v1" + "sigs.k8s.io/gateway-api/apis/v1alpha2" + "sigs.k8s.io/gateway-api/apis/v1beta1" + "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -234,7 +235,17 @@ func (in *Resources) DeepCopyInto(out *Resources) { } } } - return + if in.DirectResponses != nil { + in, out := &in.DirectResponses, &out.DirectResponses + *out = make([]*gatewayv1alpha1.DirectResponse, len(*in)) + for i := range *in { + if (*in)[i] != nil { + in, out := &(*in)[i], &(*out)[i] + *out = new(gatewayv1alpha1.DirectResponse) + (*in).DeepCopyInto(*out) + } + } + } } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. From c684a55690b91058275aded42c83297c001132ed Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Sun, 1 Feb 2026 22:37:27 -0800 Subject: [PATCH 3/5] handle DirectResponses in gateway api --- pkg/apiserver/gateway/gateway.go | 7 ++++- pkg/gateway/gatewayapi/filters.go | 16 +++++++++-- pkg/gateway/gatewayapi/resource.go | 1 + pkg/gateway/ir/xds.go | 4 +++ pkg/gateway/xds/translator/route.go | 43 +++++++++++++++++++++++++++++ 5 files changed, 68 insertions(+), 3 deletions(-) diff --git a/pkg/apiserver/gateway/gateway.go b/pkg/apiserver/gateway/gateway.go index 64eeb98..41faab0 100644 --- a/pkg/apiserver/gateway/gateway.go +++ b/pkg/apiserver/gateway/gateway.go @@ -386,7 +386,7 @@ func (r *GatewayReconciler) reconcileHTTPRoutes( // Fetch the DirectResponse object dr := &gatewayv1alpha1.DirectResponse{} if err := r.Get(ctx, types.NamespacedName{Name: string(filter.ExtensionRef.Name)}, dr); err != nil { - log.Info("Unable to find DirectResponse reference", "name", filter.ExtensionRef.Name) + log.Error(err, "Failed to get DirectResponse reference", "name", filter.ExtensionRef.Name) } else { // Check if it's already in the list to avoid duplicates alreadyExists := false @@ -884,6 +884,11 @@ func (r *GatewayReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manag &extensionsv1alpha2.EdgeFunction{}, handler.EnqueueRequestsFromMapFunc(r.enqueueClass), builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), + ). + Watches( + &gatewayv1alpha1.DirectResponse{}, + handler.EnqueueRequestsFromMapFunc(r.enqueueClass), + builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), ) if r.watchK8s { diff --git a/pkg/gateway/gatewayapi/filters.go b/pkg/gateway/gatewayapi/filters.go index f87506a..1d7bd81 100644 --- a/pkg/gateway/gatewayapi/filters.go +++ b/pkg/gateway/gatewayapi/filters.go @@ -676,9 +676,21 @@ func (t *Translator) processExtensionRefHTTPFilter(extFilter *gwapiv1.LocalObjec body = dr.Spec.Body.Inline } + // Convert headers from CRD to IR format + var headers []ir.AddHeader + for _, h := range dr.Spec.Headers { + headers = append(headers, ir.AddHeader{ + Name: h.Name, + Value: h.Value, + Append: false, // Direct response headers are set, not appended + }) + } + filterContext.DirectResponse = &ir.DirectResponse{ - StatusCode: statusCode, - Body: body, + StatusCode: statusCode, + Body: body, + ContentType: dr.Spec.ContentType, + Headers: headers, } return } diff --git a/pkg/gateway/gatewayapi/resource.go b/pkg/gateway/gatewayapi/resource.go index 15ca0b7..48a8a6f 100644 --- a/pkg/gateway/gatewayapi/resource.go +++ b/pkg/gateway/gatewayapi/resource.go @@ -81,6 +81,7 @@ func NewResources() *Resources { ReferenceGrants: []*gwapiv1b1.ReferenceGrant{}, Namespaces: []*v1.Namespace{}, ExtensionRefFilters: []unstructured.Unstructured{}, + DirectResponses: []*gatewayv1alpha1.DirectResponse{}, } } diff --git a/pkg/gateway/ir/xds.go b/pkg/gateway/ir/xds.go index 31a740f..2822c98 100644 --- a/pkg/gateway/ir/xds.go +++ b/pkg/gateway/ir/xds.go @@ -979,6 +979,10 @@ type DirectResponse struct { Body *string `json:"body,omitempty" yaml:"body,omitempty"` // StatusCode will be used for the direct response's status code. StatusCode uint32 `json:"statusCode" yaml:"statusCode"` + // ContentType specifies the Content-Type header value for the response. + ContentType *string `json:"contentType,omitempty" yaml:"contentType,omitempty"` + // Headers are additional HTTP headers to include in the response. + Headers []AddHeader `json:"headers,omitempty" yaml:"headers,omitempty"` } // Validate the fields within the DirectResponse structure diff --git a/pkg/gateway/xds/translator/route.go b/pkg/gateway/xds/translator/route.go index 17320b0..410755f 100644 --- a/pkg/gateway/xds/translator/route.go +++ b/pkg/gateway/xds/translator/route.go @@ -51,6 +51,11 @@ func buildXdsRoute(httpRoute *ir.HTTPRoute) (*routev3.Route, error) { switch { case httpRoute.DirectResponse != nil: router.Action = &routev3.Route_DirectResponse{DirectResponse: buildXdsDirectResponseAction(httpRoute.DirectResponse)} + // Add response headers for DirectResponse (ContentType and custom headers) + directResponseHeaders := buildXdsDirectResponseHeaders(httpRoute.DirectResponse) + if len(directResponseHeaders) > 0 { + router.ResponseHeadersToAdd = append(router.ResponseHeadersToAdd, directResponseHeaders...) + } case httpRoute.Redirect != nil: router.Action = &routev3.Route_Redirect{Redirect: buildXdsRedirectAction(httpRoute)} case httpRoute.URLRewrite != nil: @@ -432,6 +437,44 @@ func buildXdsDirectResponseAction(res *ir.DirectResponse) *routev3.DirectRespons return routeAction } +// buildXdsDirectResponseHeaders builds response headers for DirectResponse including ContentType and custom headers. +func buildXdsDirectResponseHeaders(res *ir.DirectResponse) []*corev3.HeaderValueOption { + var headers []*corev3.HeaderValueOption + + // Add Content-Type header if specified + if res.ContentType != nil { + headers = append(headers, &corev3.HeaderValueOption{ + Header: &corev3.HeaderValue{ + Key: "Content-Type", + Value: *res.ContentType, + }, + AppendAction: corev3.HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD, + }) + } + + // Add custom headers + for _, h := range res.Headers { + appendAction := corev3.HeaderValueOption_OVERWRITE_IF_EXISTS_OR_ADD + if h.Append { + appendAction = corev3.HeaderValueOption_APPEND_IF_EXISTS_OR_ADD + } + header := &corev3.HeaderValueOption{ + Header: &corev3.HeaderValue{ + Key: h.Name, + Value: h.Value, + }, + AppendAction: appendAction, + } + // Allow empty headers to be set + if h.Value == "" { + header.KeepEmptyValue = true + } + headers = append(headers, header) + } + + return headers +} + func buildXdsRequestMirrorPolicies(mirrorDestinations []*ir.RouteDestination) []*routev3.RouteAction_RequestMirrorPolicy { var mirrorPolicies []*routev3.RouteAction_RequestMirrorPolicy From aa6eb76d21fe52984814ca449c26edacda5e956c Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Mon, 2 Feb 2026 10:31:46 -0800 Subject: [PATCH 4/5] DirectResponse is an extension --- .../v1alpha2}/directresponse_types.go | 2 +- .../v1alpha2/zz_generated.deepcopy.go | 157 ++++++++++++ .../v1alpha2/zz_generated.register.go | 2 + api/gateway/v1alpha1/doc.go | 7 - api/gateway/v1alpha1/groupversion_info.go | 5 - api/gateway/v1alpha1/zz_generated.deepcopy.go | 183 -------------- api/gateway/v1alpha1/zz_generated.register.go | 69 ----- api/generated/zz_generated.openapi.go | 239 ++++++++++++++++++ client/versioned/clientset.go | 13 - client/versioned/fake/clientset_generated.go | 7 - client/versioned/fake/register.go | 2 - client/versioned/scheme/register.go | 2 - .../versioned/typed/gateway/v1alpha1/doc.go | 19 -- .../typed/gateway/v1alpha1/fake/doc.go | 19 -- .../v1alpha1/fake/fake_gateway_client.go | 34 --- .../typed/gateway/v1alpha1/gateway_client.go | 101 -------- .../gateway/v1alpha1/generated_expansion.go | 18 -- codegen/update.sh | 6 - pkg/apiserver/gateway/gateway.go | 7 +- pkg/gateway/gatewayapi/filters.go | 2 +- pkg/gateway/gatewayapi/resource.go | 5 +- .../gatewayapi/zz_generated.deepcopy.go | 22 +- pkg/gateway/ir/zz_generated.deepcopy.go | 10 + 23 files changed, 426 insertions(+), 505 deletions(-) rename api/{gateway/v1alpha1 => extensions/v1alpha2}/directresponse_types.go (99%) delete mode 100644 api/gateway/v1alpha1/doc.go delete mode 100644 api/gateway/v1alpha1/groupversion_info.go delete mode 100644 api/gateway/v1alpha1/zz_generated.deepcopy.go delete mode 100644 api/gateway/v1alpha1/zz_generated.register.go delete mode 100644 client/versioned/typed/gateway/v1alpha1/doc.go delete mode 100644 client/versioned/typed/gateway/v1alpha1/fake/doc.go delete mode 100644 client/versioned/typed/gateway/v1alpha1/fake/fake_gateway_client.go delete mode 100644 client/versioned/typed/gateway/v1alpha1/gateway_client.go delete mode 100644 client/versioned/typed/gateway/v1alpha1/generated_expansion.go diff --git a/api/gateway/v1alpha1/directresponse_types.go b/api/extensions/v1alpha2/directresponse_types.go similarity index 99% rename from api/gateway/v1alpha1/directresponse_types.go rename to api/extensions/v1alpha2/directresponse_types.go index b533ab1..3510568 100644 --- a/api/gateway/v1alpha1/directresponse_types.go +++ b/api/extensions/v1alpha2/directresponse_types.go @@ -1,4 +1,4 @@ -package v1alpha1 +package v1alpha2 import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/api/extensions/v1alpha2/zz_generated.deepcopy.go b/api/extensions/v1alpha2/zz_generated.deepcopy.go index 2dca2ea..0ed9304 100644 --- a/api/extensions/v1alpha2/zz_generated.deepcopy.go +++ b/api/extensions/v1alpha2/zz_generated.deepcopy.go @@ -25,6 +25,147 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CustomResponseBody) DeepCopyInto(out *CustomResponseBody) { + *out = *in + if in.Inline != nil { + in, out := &in.Inline, &out.Inline + *out = new(string) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResponseBody. +func (in *CustomResponseBody) DeepCopy() *CustomResponseBody { + if in == nil { + return nil + } + out := new(CustomResponseBody) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DirectResponse) DeepCopyInto(out *DirectResponse) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DirectResponse. +func (in *DirectResponse) DeepCopy() *DirectResponse { + if in == nil { + return nil + } + out := new(DirectResponse) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DirectResponse) 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 *DirectResponseList) DeepCopyInto(out *DirectResponseList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]DirectResponse, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DirectResponseList. +func (in *DirectResponseList) DeepCopy() *DirectResponseList { + if in == nil { + return nil + } + out := new(DirectResponseList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *DirectResponseList) 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 *DirectResponseSpec) DeepCopyInto(out *DirectResponseSpec) { + *out = *in + if in.StatusCode != nil { + in, out := &in.StatusCode, &out.StatusCode + *out = new(int32) + **out = **in + } + if in.ContentType != nil { + in, out := &in.ContentType, &out.ContentType + *out = new(string) + **out = **in + } + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = make([]Header, len(*in)) + copy(*out, *in) + } + if in.Body != nil { + in, out := &in.Body, &out.Body + *out = new(CustomResponseBody) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DirectResponseSpec. +func (in *DirectResponseSpec) DeepCopy() *DirectResponseSpec { + if in == nil { + return nil + } + out := new(DirectResponseSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *DirectResponseStatus) DeepCopyInto(out *DirectResponseStatus) { + *out = *in + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DirectResponseStatus. +func (in *DirectResponseStatus) DeepCopy() *DirectResponseStatus { + if in == nil { + return nil + } + out := new(DirectResponseStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EdgeFunction) DeepCopyInto(out *EdgeFunction) { *out = *in @@ -347,6 +488,22 @@ func (in *GoPluginSource) DeepCopy() *GoPluginSource { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Header) DeepCopyInto(out *Header) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Header. +func (in *Header) DeepCopy() *Header { + if in == nil { + return nil + } + out := new(Header) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *JavaScriptAssetsSource) DeepCopyInto(out *JavaScriptAssetsSource) { *out = *in diff --git a/api/extensions/v1alpha2/zz_generated.register.go b/api/extensions/v1alpha2/zz_generated.register.go index b851ee5..fbb4619 100644 --- a/api/extensions/v1alpha2/zz_generated.register.go +++ b/api/extensions/v1alpha2/zz_generated.register.go @@ -60,6 +60,8 @@ func init() { // Adds the list of known types to Scheme. func addKnownTypes(scheme *runtime.Scheme) error { scheme.AddKnownTypes(SchemeGroupVersion, + &DirectResponse{}, + &DirectResponseList{}, &EdgeFunction{}, &EdgeFunctionList{}, &EdgeFunctionRevision{}, diff --git a/api/gateway/v1alpha1/doc.go b/api/gateway/v1alpha1/doc.go deleted file mode 100644 index 86d479f..0000000 --- a/api/gateway/v1alpha1/doc.go +++ /dev/null @@ -1,7 +0,0 @@ -// +k8s:openapi-gen=true -// +kubebuilder:object:generate=true -// +groupName=gateway.apoxy.dev -// +k8s:deepcopy-gen=package,register - -// Package v1alpha1 contains API Schema definitions for the gateway v1alpha1 API group. -package v1alpha1 diff --git a/api/gateway/v1alpha1/groupversion_info.go b/api/gateway/v1alpha1/groupversion_info.go deleted file mode 100644 index bdfafcc..0000000 --- a/api/gateway/v1alpha1/groupversion_info.go +++ /dev/null @@ -1,5 +0,0 @@ -package v1alpha1 - -// GroupVersion is group version used to register these objects. -// This is defined and exported by the generated register file (zz_generated.register.go) -// For backward compatibility, we import and re-export it here if needed by other packages. diff --git a/api/gateway/v1alpha1/zz_generated.deepcopy.go b/api/gateway/v1alpha1/zz_generated.deepcopy.go deleted file mode 100644 index 4ad42da..0000000 --- a/api/gateway/v1alpha1/zz_generated.deepcopy.go +++ /dev/null @@ -1,183 +0,0 @@ -//go:build !ignore_autogenerated -// +build !ignore_autogenerated - -/* -Copyright 2026 Apoxy, Inc. - -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 deepcopy-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - runtime "k8s.io/apimachinery/pkg/runtime" -) - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *CustomResponseBody) DeepCopyInto(out *CustomResponseBody) { - *out = *in - if in.Inline != nil { - in, out := &in.Inline, &out.Inline - *out = new(string) - **out = **in - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CustomResponseBody. -func (in *CustomResponseBody) DeepCopy() *CustomResponseBody { - if in == nil { - return nil - } - out := new(CustomResponseBody) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DirectResponse) DeepCopyInto(out *DirectResponse) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) - in.Spec.DeepCopyInto(&out.Spec) - in.Status.DeepCopyInto(&out.Status) - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DirectResponse. -func (in *DirectResponse) DeepCopy() *DirectResponse { - if in == nil { - return nil - } - out := new(DirectResponse) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *DirectResponse) 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 *DirectResponseList) DeepCopyInto(out *DirectResponseList) { - *out = *in - out.TypeMeta = in.TypeMeta - in.ListMeta.DeepCopyInto(&out.ListMeta) - if in.Items != nil { - in, out := &in.Items, &out.Items - *out = make([]DirectResponse, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DirectResponseList. -func (in *DirectResponseList) DeepCopy() *DirectResponseList { - if in == nil { - return nil - } - out := new(DirectResponseList) - in.DeepCopyInto(out) - return out -} - -// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. -func (in *DirectResponseList) 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 *DirectResponseSpec) DeepCopyInto(out *DirectResponseSpec) { - *out = *in - if in.StatusCode != nil { - in, out := &in.StatusCode, &out.StatusCode - *out = new(int32) - **out = **in - } - if in.ContentType != nil { - in, out := &in.ContentType, &out.ContentType - *out = new(string) - **out = **in - } - if in.Headers != nil { - in, out := &in.Headers, &out.Headers - *out = make([]Header, len(*in)) - copy(*out, *in) - } - if in.Body != nil { - in, out := &in.Body, &out.Body - *out = new(CustomResponseBody) - (*in).DeepCopyInto(*out) - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DirectResponseSpec. -func (in *DirectResponseSpec) DeepCopy() *DirectResponseSpec { - if in == nil { - return nil - } - out := new(DirectResponseSpec) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *DirectResponseStatus) DeepCopyInto(out *DirectResponseStatus) { - *out = *in - if in.Conditions != nil { - in, out := &in.Conditions, &out.Conditions - *out = make([]v1.Condition, len(*in)) - for i := range *in { - (*in)[i].DeepCopyInto(&(*out)[i]) - } - } - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new DirectResponseStatus. -func (in *DirectResponseStatus) DeepCopy() *DirectResponseStatus { - if in == nil { - return nil - } - out := new(DirectResponseStatus) - in.DeepCopyInto(out) - return out -} - -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Header) DeepCopyInto(out *Header) { - *out = *in - return -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Header. -func (in *Header) DeepCopy() *Header { - if in == nil { - return nil - } - out := new(Header) - in.DeepCopyInto(out) - return out -} diff --git a/api/gateway/v1alpha1/zz_generated.register.go b/api/gateway/v1alpha1/zz_generated.register.go deleted file mode 100644 index 9dea177..0000000 --- a/api/gateway/v1alpha1/zz_generated.register.go +++ /dev/null @@ -1,69 +0,0 @@ -//go:build !ignore_autogenerated -// +build !ignore_autogenerated - -/* -Copyright 2026 Apoxy, Inc. - -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 register-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - v1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/runtime" - "k8s.io/apimachinery/pkg/runtime/schema" -) - -// GroupName specifies the group name used to register the objects. -const GroupName = "gateway.apoxy.dev" - -// GroupVersion specifies the group and the version used to register the objects. -var GroupVersion = v1.GroupVersion{Group: GroupName, Version: "v1alpha1"} - -// SchemeGroupVersion is group version used to register these objects -// Deprecated: use GroupVersion instead. -var SchemeGroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha1"} - -// Resource takes an unqualified resource and returns a Group qualified GroupResource -func Resource(resource string) schema.GroupResource { - return SchemeGroupVersion.WithResource(resource).GroupResource() -} - -var ( - // localSchemeBuilder and AddToScheme will stay in k8s.io/kubernetes. - SchemeBuilder runtime.SchemeBuilder - localSchemeBuilder = &SchemeBuilder - // Deprecated: use Install instead - AddToScheme = localSchemeBuilder.AddToScheme - Install = localSchemeBuilder.AddToScheme -) - -func init() { - // We only register manually written functions here. The registration of the - // generated functions takes place in the generated files. The separation - // makes the code compile even when the generated files are missing. - localSchemeBuilder.Register(addKnownTypes) -} - -// Adds the list of known types to Scheme. -func addKnownTypes(scheme *runtime.Scheme) error { - scheme.AddKnownTypes(SchemeGroupVersion, - &DirectResponse{}, - &DirectResponseList{}, - ) - // AddToGroupVersion allows the serialization of client types like ListOptions. - v1.AddToGroupVersion(scheme, SchemeGroupVersion) - return nil -} diff --git a/api/generated/zz_generated.openapi.go b/api/generated/zz_generated.openapi.go index 1bd112f..2f6bbe6 100644 --- a/api/generated/zz_generated.openapi.go +++ b/api/generated/zz_generated.openapi.go @@ -173,6 +173,11 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/apoxy-dev/apoxy/api/extensions/v1alpha1.RuntimeCapabilities": schema_apoxy_api_extensions_v1alpha1_RuntimeCapabilities(ref), "github.com/apoxy-dev/apoxy/api/extensions/v1alpha1.SourceFile": schema_apoxy_api_extensions_v1alpha1_SourceFile(ref), "github.com/apoxy-dev/apoxy/api/extensions/v1alpha1.WasmSource": schema_apoxy_api_extensions_v1alpha1_WasmSource(ref), + "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.CustomResponseBody": schema_apoxy_api_extensions_v1alpha2_CustomResponseBody(ref), + "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.DirectResponse": schema_apoxy_api_extensions_v1alpha2_DirectResponse(ref), + "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.DirectResponseList": schema_apoxy_api_extensions_v1alpha2_DirectResponseList(ref), + "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.DirectResponseSpec": schema_apoxy_api_extensions_v1alpha2_DirectResponseSpec(ref), + "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.DirectResponseStatus": schema_apoxy_api_extensions_v1alpha2_DirectResponseStatus(ref), "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.EdgeFunction": schema_apoxy_api_extensions_v1alpha2_EdgeFunction(ref), "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.EdgeFunctionCodeSource": schema_apoxy_api_extensions_v1alpha2_EdgeFunctionCodeSource(ref), "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.EdgeFunctionList": schema_apoxy_api_extensions_v1alpha2_EdgeFunctionList(ref), @@ -185,6 +190,7 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.EdgeFunctionStatus": schema_apoxy_api_extensions_v1alpha2_EdgeFunctionStatus(ref), "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.EnvVar": schema_apoxy_api_extensions_v1alpha2_EnvVar(ref), "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.GoPluginSource": schema_apoxy_api_extensions_v1alpha2_GoPluginSource(ref), + "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.Header": schema_apoxy_api_extensions_v1alpha2_Header(ref), "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.JavaScriptAssetsSource": schema_apoxy_api_extensions_v1alpha2_JavaScriptAssetsSource(ref), "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.JavaScriptGitSource": schema_apoxy_api_extensions_v1alpha2_JavaScriptGitSource(ref), "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.JavaScriptNpmSource": schema_apoxy_api_extensions_v1alpha2_JavaScriptNpmSource(ref), @@ -6559,6 +6565,209 @@ func schema_apoxy_api_extensions_v1alpha1_WasmSource(ref common.ReferenceCallbac } } +func schema_apoxy_api_extensions_v1alpha2_CustomResponseBody(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "CustomResponseBody defines the body of the direct response.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "type": { + SchemaProps: spec.SchemaProps{ + Description: "Type specifies how the body is provided. Currently only \"Inline\" is supported.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "inline": { + SchemaProps: spec.SchemaProps{ + Description: "Inline is the literal body content when Type is \"Inline\".", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"type"}, + }, + }, + } +} + +func schema_apoxy_api_extensions_v1alpha2_DirectResponse(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "DirectResponse is the Schema for the directresponses API. It defines a static response that can be returned by an HTTPRoute instead of forwarding to a backend.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"), + }, + }, + "spec": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.DirectResponseSpec"), + }, + }, + "status": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.DirectResponseStatus"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.DirectResponseSpec", "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.DirectResponseStatus", "k8s.io/apimachinery/pkg/apis/meta/v1.ObjectMeta"}, + } +} + +func schema_apoxy_api_extensions_v1alpha2_DirectResponseList(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "DirectResponseList contains a list of DirectResponse.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "kind": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "apiVersion": { + SchemaProps: spec.SchemaProps{ + 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{"string"}, + Format: "", + }, + }, + "metadata": { + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"), + }, + }, + "items": { + SchemaProps: spec.SchemaProps{ + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.DirectResponse"), + }, + }, + }, + }, + }, + }, + Required: []string{"items"}, + }, + }, + Dependencies: []string{ + "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.DirectResponse", "k8s.io/apimachinery/pkg/apis/meta/v1.ListMeta"}, + } +} + +func schema_apoxy_api_extensions_v1alpha2_DirectResponseSpec(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "DirectResponseSpec defines the desired state of DirectResponse.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "statusCode": { + SchemaProps: spec.SchemaProps{ + Description: "StatusCode is the HTTP status code to return. Defaults to 200 if not specified.", + Type: []string{"integer"}, + Format: "int32", + }, + }, + "contentType": { + SchemaProps: spec.SchemaProps{ + Description: "ContentType is the Content-Type header value. Defaults to \"text/plain\" if not specified.", + Type: []string{"string"}, + Format: "", + }, + }, + "headers": { + SchemaProps: spec.SchemaProps{ + Description: "Headers are additional HTTP headers to include in the response.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.Header"), + }, + }, + }, + }, + }, + "body": { + SchemaProps: spec.SchemaProps{ + Description: "Body is the response body configuration.", + Ref: ref("github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.CustomResponseBody"), + }, + }, + }, + }, + }, + Dependencies: []string{ + "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.CustomResponseBody", "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2.Header"}, + } +} + +func schema_apoxy_api_extensions_v1alpha2_DirectResponseStatus(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "DirectResponseStatus defines the observed state of DirectResponse.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "conditions": { + SchemaProps: spec.SchemaProps{ + Description: "Conditions describe the current conditions of the DirectResponse.", + Type: []string{"array"}, + Items: &spec.SchemaOrArray{ + Schema: &spec.Schema{ + SchemaProps: spec.SchemaProps{ + Default: map[string]interface{}{}, + Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.Condition"), + }, + }, + }, + }, + }, + }, + }, + }, + Dependencies: []string{ + "k8s.io/apimachinery/pkg/apis/meta/v1.Condition"}, + } +} + func schema_apoxy_api_extensions_v1alpha2_EdgeFunction(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ @@ -7035,6 +7244,36 @@ func schema_apoxy_api_extensions_v1alpha2_GoPluginSource(ref common.ReferenceCal } } +func schema_apoxy_api_extensions_v1alpha2_Header(ref common.ReferenceCallback) common.OpenAPIDefinition { + return common.OpenAPIDefinition{ + Schema: spec.Schema{ + SchemaProps: spec.SchemaProps{ + Description: "Header defines a custom HTTP header to include in the response.", + Type: []string{"object"}, + Properties: map[string]spec.Schema{ + "name": { + SchemaProps: spec.SchemaProps{ + Description: "Name is the header name.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + "value": { + SchemaProps: spec.SchemaProps{ + Description: "Value is the header value.", + Default: "", + Type: []string{"string"}, + Format: "", + }, + }, + }, + Required: []string{"name", "value"}, + }, + }, + } +} + func schema_apoxy_api_extensions_v1alpha2_JavaScriptAssetsSource(ref common.ReferenceCallback) common.OpenAPIDefinition { return common.OpenAPIDefinition{ Schema: spec.Schema{ diff --git a/client/versioned/clientset.go b/client/versioned/clientset.go index 56329c7..a1c6fb1 100644 --- a/client/versioned/clientset.go +++ b/client/versioned/clientset.go @@ -27,7 +27,6 @@ import ( extensionsv1alpha1 "github.com/apoxy-dev/apoxy/client/versioned/typed/extensions/v1alpha1" extensionsv1alpha2 "github.com/apoxy-dev/apoxy/client/versioned/typed/extensions/v1alpha2" gatewayv1 "github.com/apoxy-dev/apoxy/client/versioned/typed/gateway/v1" - gatewayv1alpha1 "github.com/apoxy-dev/apoxy/client/versioned/typed/gateway/v1alpha1" gatewayv1alpha2 "github.com/apoxy-dev/apoxy/client/versioned/typed/gateway/v1alpha2" policyv1alpha1 "github.com/apoxy-dev/apoxy/client/versioned/typed/policy/v1alpha1" discovery "k8s.io/client-go/discovery" @@ -43,7 +42,6 @@ type Interface interface { ExtensionsV1alpha1() extensionsv1alpha1.ExtensionsV1alpha1Interface ExtensionsV1alpha2() extensionsv1alpha2.ExtensionsV1alpha2Interface GatewayV1() gatewayv1.GatewayV1Interface - GatewayV1alpha1() gatewayv1alpha1.GatewayV1alpha1Interface GatewayV1alpha2() gatewayv1alpha2.GatewayV1alpha2Interface PolicyV1alpha1() policyv1alpha1.PolicyV1alpha1Interface } @@ -57,7 +55,6 @@ type Clientset struct { extensionsV1alpha1 *extensionsv1alpha1.ExtensionsV1alpha1Client extensionsV1alpha2 *extensionsv1alpha2.ExtensionsV1alpha2Client gatewayV1 *gatewayv1.GatewayV1Client - gatewayV1alpha1 *gatewayv1alpha1.GatewayV1alpha1Client gatewayV1alpha2 *gatewayv1alpha2.GatewayV1alpha2Client policyV1alpha1 *policyv1alpha1.PolicyV1alpha1Client } @@ -92,11 +89,6 @@ func (c *Clientset) GatewayV1() gatewayv1.GatewayV1Interface { return c.gatewayV1 } -// GatewayV1alpha1 retrieves the GatewayV1alpha1Client -func (c *Clientset) GatewayV1alpha1() gatewayv1alpha1.GatewayV1alpha1Interface { - return c.gatewayV1alpha1 -} - // GatewayV1alpha2 retrieves the GatewayV1alpha2Client func (c *Clientset) GatewayV1alpha2() gatewayv1alpha2.GatewayV1alpha2Interface { return c.gatewayV1alpha2 @@ -175,10 +167,6 @@ func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, if err != nil { return nil, err } - cs.gatewayV1alpha1, err = gatewayv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient) - if err != nil { - return nil, err - } cs.gatewayV1alpha2, err = gatewayv1alpha2.NewForConfigAndClient(&configShallowCopy, httpClient) if err != nil { return nil, err @@ -214,7 +202,6 @@ func New(c rest.Interface) *Clientset { cs.extensionsV1alpha1 = extensionsv1alpha1.New(c) cs.extensionsV1alpha2 = extensionsv1alpha2.New(c) cs.gatewayV1 = gatewayv1.New(c) - cs.gatewayV1alpha1 = gatewayv1alpha1.New(c) cs.gatewayV1alpha2 = gatewayv1alpha2.New(c) cs.policyV1alpha1 = policyv1alpha1.New(c) diff --git a/client/versioned/fake/clientset_generated.go b/client/versioned/fake/clientset_generated.go index 080938a..515e2f1 100644 --- a/client/versioned/fake/clientset_generated.go +++ b/client/versioned/fake/clientset_generated.go @@ -31,8 +31,6 @@ import ( fakeextensionsv1alpha2 "github.com/apoxy-dev/apoxy/client/versioned/typed/extensions/v1alpha2/fake" gatewayv1 "github.com/apoxy-dev/apoxy/client/versioned/typed/gateway/v1" fakegatewayv1 "github.com/apoxy-dev/apoxy/client/versioned/typed/gateway/v1/fake" - gatewayv1alpha1 "github.com/apoxy-dev/apoxy/client/versioned/typed/gateway/v1alpha1" - fakegatewayv1alpha1 "github.com/apoxy-dev/apoxy/client/versioned/typed/gateway/v1alpha1/fake" gatewayv1alpha2 "github.com/apoxy-dev/apoxy/client/versioned/typed/gateway/v1alpha2" fakegatewayv1alpha2 "github.com/apoxy-dev/apoxy/client/versioned/typed/gateway/v1alpha2/fake" policyv1alpha1 "github.com/apoxy-dev/apoxy/client/versioned/typed/policy/v1alpha1" @@ -128,11 +126,6 @@ func (c *Clientset) GatewayV1() gatewayv1.GatewayV1Interface { return &fakegatewayv1.FakeGatewayV1{Fake: &c.Fake} } -// GatewayV1alpha1 retrieves the GatewayV1alpha1Client -func (c *Clientset) GatewayV1alpha1() gatewayv1alpha1.GatewayV1alpha1Interface { - return &fakegatewayv1alpha1.FakeGatewayV1alpha1{Fake: &c.Fake} -} - // GatewayV1alpha2 retrieves the GatewayV1alpha2Client func (c *Clientset) GatewayV1alpha2() gatewayv1alpha2.GatewayV1alpha2Interface { return &fakegatewayv1alpha2.FakeGatewayV1alpha2{Fake: &c.Fake} diff --git a/client/versioned/fake/register.go b/client/versioned/fake/register.go index 29bd240..897c32a 100644 --- a/client/versioned/fake/register.go +++ b/client/versioned/fake/register.go @@ -24,7 +24,6 @@ import ( extensionsv1alpha1 "github.com/apoxy-dev/apoxy/api/extensions/v1alpha1" extensionsv1alpha2 "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2" gatewayv1 "github.com/apoxy-dev/apoxy/api/gateway/v1" - gatewayv1alpha1 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha1" gatewayv1alpha2 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha2" policyv1alpha1 "github.com/apoxy-dev/apoxy/api/policy/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -44,7 +43,6 @@ var localSchemeBuilder = runtime.SchemeBuilder{ extensionsv1alpha1.AddToScheme, extensionsv1alpha2.AddToScheme, gatewayv1.AddToScheme, - gatewayv1alpha1.AddToScheme, gatewayv1alpha2.AddToScheme, policyv1alpha1.AddToScheme, } diff --git a/client/versioned/scheme/register.go b/client/versioned/scheme/register.go index c910642..c1c5f20 100644 --- a/client/versioned/scheme/register.go +++ b/client/versioned/scheme/register.go @@ -24,7 +24,6 @@ import ( extensionsv1alpha1 "github.com/apoxy-dev/apoxy/api/extensions/v1alpha1" extensionsv1alpha2 "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2" gatewayv1 "github.com/apoxy-dev/apoxy/api/gateway/v1" - gatewayv1alpha1 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha1" gatewayv1alpha2 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha2" policyv1alpha1 "github.com/apoxy-dev/apoxy/api/policy/v1alpha1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -44,7 +43,6 @@ var localSchemeBuilder = runtime.SchemeBuilder{ extensionsv1alpha1.AddToScheme, extensionsv1alpha2.AddToScheme, gatewayv1.AddToScheme, - gatewayv1alpha1.AddToScheme, gatewayv1alpha2.AddToScheme, policyv1alpha1.AddToScheme, } diff --git a/client/versioned/typed/gateway/v1alpha1/doc.go b/client/versioned/typed/gateway/v1alpha1/doc.go deleted file mode 100644 index 288f055..0000000 --- a/client/versioned/typed/gateway/v1alpha1/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2026 Apoxy, Inc. - -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 client-gen. DO NOT EDIT. - -// This package has the automatically generated typed clients. -package v1alpha1 diff --git a/client/versioned/typed/gateway/v1alpha1/fake/doc.go b/client/versioned/typed/gateway/v1alpha1/fake/doc.go deleted file mode 100644 index f35cadb..0000000 --- a/client/versioned/typed/gateway/v1alpha1/fake/doc.go +++ /dev/null @@ -1,19 +0,0 @@ -/* -Copyright 2026 Apoxy, Inc. - -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 client-gen. DO NOT EDIT. - -// Package fake has the automatically generated clients. -package fake diff --git a/client/versioned/typed/gateway/v1alpha1/fake/fake_gateway_client.go b/client/versioned/typed/gateway/v1alpha1/fake/fake_gateway_client.go deleted file mode 100644 index a7d521f..0000000 --- a/client/versioned/typed/gateway/v1alpha1/fake/fake_gateway_client.go +++ /dev/null @@ -1,34 +0,0 @@ -/* -Copyright 2026 Apoxy, Inc. - -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 client-gen. DO NOT EDIT. - -package fake - -import ( - rest "k8s.io/client-go/rest" - testing "k8s.io/client-go/testing" -) - -type FakeGatewayV1alpha1 struct { - *testing.Fake -} - -// RESTClient returns a RESTClient that is used to communicate -// with API server by this client implementation. -func (c *FakeGatewayV1alpha1) RESTClient() rest.Interface { - var ret *rest.RESTClient - return ret -} diff --git a/client/versioned/typed/gateway/v1alpha1/gateway_client.go b/client/versioned/typed/gateway/v1alpha1/gateway_client.go deleted file mode 100644 index a50d044..0000000 --- a/client/versioned/typed/gateway/v1alpha1/gateway_client.go +++ /dev/null @@ -1,101 +0,0 @@ -/* -Copyright 2026 Apoxy, Inc. - -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 client-gen. DO NOT EDIT. - -package v1alpha1 - -import ( - http "net/http" - - gatewayv1alpha1 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha1" - scheme "github.com/apoxy-dev/apoxy/client/versioned/scheme" - rest "k8s.io/client-go/rest" -) - -type GatewayV1alpha1Interface interface { - RESTClient() rest.Interface -} - -// GatewayV1alpha1Client is used to interact with features provided by the gateway.apoxy.dev group. -type GatewayV1alpha1Client struct { - restClient rest.Interface -} - -// NewForConfig creates a new GatewayV1alpha1Client for the given config. -// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), -// where httpClient was generated with rest.HTTPClientFor(c). -func NewForConfig(c *rest.Config) (*GatewayV1alpha1Client, error) { - config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } - httpClient, err := rest.HTTPClientFor(&config) - if err != nil { - return nil, err - } - return NewForConfigAndClient(&config, httpClient) -} - -// NewForConfigAndClient creates a new GatewayV1alpha1Client for the given config and http client. -// Note the http client provided takes precedence over the configured transport values. -func NewForConfigAndClient(c *rest.Config, h *http.Client) (*GatewayV1alpha1Client, error) { - config := *c - if err := setConfigDefaults(&config); err != nil { - return nil, err - } - client, err := rest.RESTClientForConfigAndClient(&config, h) - if err != nil { - return nil, err - } - return &GatewayV1alpha1Client{client}, nil -} - -// NewForConfigOrDie creates a new GatewayV1alpha1Client for the given config and -// panics if there is an error in the config. -func NewForConfigOrDie(c *rest.Config) *GatewayV1alpha1Client { - client, err := NewForConfig(c) - if err != nil { - panic(err) - } - return client -} - -// New creates a new GatewayV1alpha1Client for the given RESTClient. -func New(c rest.Interface) *GatewayV1alpha1Client { - return &GatewayV1alpha1Client{c} -} - -func setConfigDefaults(config *rest.Config) error { - gv := gatewayv1alpha1.SchemeGroupVersion - config.GroupVersion = &gv - config.APIPath = "/apis" - config.NegotiatedSerializer = rest.CodecFactoryForGeneratedClient(scheme.Scheme, scheme.Codecs).WithoutConversion() - - if config.UserAgent == "" { - config.UserAgent = rest.DefaultKubernetesUserAgent() - } - - return nil -} - -// RESTClient returns a RESTClient that is used to communicate -// with API server by this client implementation. -func (c *GatewayV1alpha1Client) RESTClient() rest.Interface { - if c == nil { - return nil - } - return c.restClient -} diff --git a/client/versioned/typed/gateway/v1alpha1/generated_expansion.go b/client/versioned/typed/gateway/v1alpha1/generated_expansion.go deleted file mode 100644 index 8447fa0..0000000 --- a/client/versioned/typed/gateway/v1alpha1/generated_expansion.go +++ /dev/null @@ -1,18 +0,0 @@ -/* -Copyright 2026 Apoxy, Inc. - -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 client-gen. DO NOT EDIT. - -package v1alpha1 diff --git a/codegen/update.sh b/codegen/update.sh index 449af39..26f2629 100755 --- a/codegen/update.sh +++ b/codegen/update.sh @@ -22,7 +22,6 @@ go run "k8s.io/code-generator/cmd/deepcopy-gen@${CODEGEN_VERSION}" \ ./api/extensions/v1alpha1 \ ./api/extensions/v1alpha2 \ ./api/gateway/v1 \ - ./api/gateway/v1alpha1 \ ./api/gateway/v1alpha2 \ ./pkg/gateway/gatewayapi \ ./pkg/gateway/ir \ @@ -40,7 +39,6 @@ go run "k8s.io/code-generator/cmd/register-gen@${CODEGEN_VERSION}" \ ./api/extensions/v1alpha1 \ ./api/extensions/v1alpha2 \ ./api/gateway/v1 \ - ./api/gateway/v1alpha1 \ ./api/gateway/v1alpha2 \ ./pkg/gateway/gatewayapi \ ./pkg/gateway/ir @@ -72,7 +70,6 @@ go run "k8s.io/code-generator/cmd/client-gen@${CODEGEN_VERSION}" \ --input "./api/extensions/v1alpha1" \ --input "./api/extensions/v1alpha2" \ --input "./api/gateway/v1" \ - --input "./api/gateway/v1alpha1" \ --input "./api/gateway/v1alpha2" \ --input "./api/policy/v1alpha1" @@ -88,7 +85,6 @@ go run "k8s.io/code-generator/cmd/lister-gen@${CODEGEN_VERSION}" \ ./api/extensions/v1alpha1 \ ./api/extensions/v1alpha2 \ ./api/gateway/v1 \ - ./api/gateway/v1alpha1 \ ./api/gateway/v1alpha2 \ ./api/policy/v1alpha1 @@ -105,7 +101,6 @@ go run "k8s.io/code-generator/cmd/informer-gen@${CODEGEN_VERSION}" \ ./api/extensions/v1alpha1 \ ./api/extensions/v1alpha2 \ ./api/gateway/v1 \ - ./api/gateway/v1alpha1 \ ./api/gateway/v1alpha2 \ ./api/policy/v1alpha1 @@ -132,6 +127,5 @@ go run "k8s.io/kube-openapi/cmd/openapi-gen@master" \ ./api/extensions/v1alpha1 \ ./api/extensions/v1alpha2 \ ./api/gateway/v1 \ - ./api/gateway/v1alpha1 \ ./api/gateway/v1alpha2 \ ./api/policy/v1alpha1 diff --git a/pkg/apiserver/gateway/gateway.go b/pkg/apiserver/gateway/gateway.go index 41faab0..01ab508 100644 --- a/pkg/apiserver/gateway/gateway.go +++ b/pkg/apiserver/gateway/gateway.go @@ -31,7 +31,6 @@ import ( corev1alpha2 "github.com/apoxy-dev/apoxy/api/core/v1alpha2" extensionsv1alpha2 "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2" gatewayv1 "github.com/apoxy-dev/apoxy/api/gateway/v1" - gatewayv1alpha1 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha1" gatewayv1alpha2 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha2" ) @@ -380,11 +379,11 @@ func (r *GatewayReconciler) reconcileHTTPRoutes( filter.ExtensionRef.Group = "extensions.apoxy.dev" } // Handle DirectResponse specially - if string(filter.ExtensionRef.Group) == "gateway.apoxy.dev" && string(filter.ExtensionRef.Kind) == "DirectResponse" { + if string(filter.ExtensionRef.Group) == "extensions.apoxy.dev" && string(filter.ExtensionRef.Kind) == "DirectResponse" { log.Info("Processing DirectResponse filter reference", "name", filter.ExtensionRef.Name, "group", filter.ExtensionRef.Group) // Fetch the DirectResponse object - dr := &gatewayv1alpha1.DirectResponse{} + dr := &extensionsv1alpha2.DirectResponse{} if err := r.Get(ctx, types.NamespacedName{Name: string(filter.ExtensionRef.Name)}, dr); err != nil { log.Error(err, "Failed to get DirectResponse reference", "name", filter.ExtensionRef.Name) } else { @@ -886,7 +885,7 @@ func (r *GatewayReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Manag builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), ). Watches( - &gatewayv1alpha1.DirectResponse{}, + &extensionsv1alpha2.DirectResponse{}, handler.EnqueueRequestsFromMapFunc(r.enqueueClass), builder.WithPredicates(predicate.ResourceVersionChangedPredicate{}), ) diff --git a/pkg/gateway/gatewayapi/filters.go b/pkg/gateway/gatewayapi/filters.go index 1d7bd81..2df9770 100644 --- a/pkg/gateway/gatewayapi/filters.go +++ b/pkg/gateway/gatewayapi/filters.go @@ -662,7 +662,7 @@ func (t *Translator) processExtensionRefHTTPFilter(extFilter *gwapiv1.LocalObjec } // Handle DirectResponse specially - convert to IR DirectResponse - if string(extFilter.Group) == "gateway.apoxy.dev" && string(extFilter.Kind) == "DirectResponse" { + if string(extFilter.Group) == "extensions.apoxy.dev" && string(extFilter.Kind) == "DirectResponse" { for _, dr := range resources.DirectResponses { if dr.Name == string(extFilter.Name) { // Convert to IR DirectResponse diff --git a/pkg/gateway/gatewayapi/resource.go b/pkg/gateway/gatewayapi/resource.go index 48a8a6f..e612505 100644 --- a/pkg/gateway/gatewayapi/resource.go +++ b/pkg/gateway/gatewayapi/resource.go @@ -22,7 +22,6 @@ import ( corev1alpha2 "github.com/apoxy-dev/apoxy/api/core/v1alpha2" extensionsv1alpha2 "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2" - gatewayv1alpha1 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha1" ) const ( @@ -65,7 +64,7 @@ type Resources struct { EdgeFunctionRevisions []*extensionsv1alpha2.EdgeFunctionRevision `json:"edgeFunctionFilters,omitempty" yaml:"edgeFunctionFilters,omitempty"` Backends []*corev1alpha2.Backend `json:"backends,omitempty" yaml:"backends,omitempty"` Proxies []*corev1alpha2.Proxy `json:"proxies,omitempty" yaml:"proxies,omitempty"` - DirectResponses []*gatewayv1alpha1.DirectResponse `json:"directResponses,omitempty" yaml:"directResponses,omitempty"` + DirectResponses []*extensionsv1alpha2.DirectResponse `json:"directResponses,omitempty" yaml:"directResponses,omitempty"` } func NewResources() *Resources { @@ -81,7 +80,7 @@ func NewResources() *Resources { ReferenceGrants: []*gwapiv1b1.ReferenceGrant{}, Namespaces: []*v1.Namespace{}, ExtensionRefFilters: []unstructured.Unstructured{}, - DirectResponses: []*gatewayv1alpha1.DirectResponse{}, + DirectResponses: []*extensionsv1alpha2.DirectResponse{}, } } diff --git a/pkg/gateway/gatewayapi/zz_generated.deepcopy.go b/pkg/gateway/gatewayapi/zz_generated.deepcopy.go index c378496..46b2f17 100644 --- a/pkg/gateway/gatewayapi/zz_generated.deepcopy.go +++ b/pkg/gateway/gatewayapi/zz_generated.deepcopy.go @@ -1,7 +1,8 @@ //go:build !ignore_autogenerated +// +build !ignore_autogenerated /* -Copyright Apoxy, Inc. +Copyright 2026 Apoxy, Inc. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -15,22 +16,20 @@ 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. +// Code generated by deepcopy-gen. DO NOT EDIT. package gatewayapi import ( corev1alpha2 "github.com/apoxy-dev/apoxy/api/core/v1alpha2" extensionsv1alpha2 "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2" - gatewayv1alpha1 "github.com/apoxy-dev/apoxy/api/gateway/v1alpha1" corev1 "k8s.io/api/core/v1" discoveryv1 "k8s.io/api/discovery/v1" - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "sigs.k8s.io/gateway-api/apis/v1" - "sigs.k8s.io/gateway-api/apis/v1alpha2" - "sigs.k8s.io/gateway-api/apis/v1beta1" - "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1" + unstructured "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + v1 "sigs.k8s.io/gateway-api/apis/v1" + v1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2" + v1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1" + v1alpha1 "sigs.k8s.io/mcs-api/pkg/apis/v1alpha1" ) // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. @@ -237,15 +236,16 @@ func (in *Resources) DeepCopyInto(out *Resources) { } if in.DirectResponses != nil { in, out := &in.DirectResponses, &out.DirectResponses - *out = make([]*gatewayv1alpha1.DirectResponse, len(*in)) + *out = make([]*extensionsv1alpha2.DirectResponse, len(*in)) for i := range *in { if (*in)[i] != nil { in, out := &(*in)[i], &(*out)[i] - *out = new(gatewayv1alpha1.DirectResponse) + *out = new(extensionsv1alpha2.DirectResponse) (*in).DeepCopyInto(*out) } } } + return } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Resources. diff --git a/pkg/gateway/ir/zz_generated.deepcopy.go b/pkg/gateway/ir/zz_generated.deepcopy.go index 995829e..0d7c2c8 100644 --- a/pkg/gateway/ir/zz_generated.deepcopy.go +++ b/pkg/gateway/ir/zz_generated.deepcopy.go @@ -479,6 +479,16 @@ func (in *DirectResponse) DeepCopyInto(out *DirectResponse) { *out = new(string) **out = **in } + if in.ContentType != nil { + in, out := &in.ContentType, &out.ContentType + *out = new(string) + **out = **in + } + if in.Headers != nil { + in, out := &in.Headers, &out.Headers + *out = make([]AddHeader, len(*in)) + copy(*out, *in) + } return } From f5f6c7689c6e17dc1c4b44465127533c0250e425 Mon Sep 17 00:00:00 2001 From: Matt Ward Date: Mon, 2 Feb 2026 22:19:49 -0800 Subject: [PATCH 5/5] use extv1alpha.GroupName --- pkg/apiserver/gateway/gateway.go | 4 ++-- pkg/gateway/gatewayapi/filters.go | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pkg/apiserver/gateway/gateway.go b/pkg/apiserver/gateway/gateway.go index 01ab508..e9c1e59 100644 --- a/pkg/apiserver/gateway/gateway.go +++ b/pkg/apiserver/gateway/gateway.go @@ -376,10 +376,10 @@ func (r *GatewayReconciler) reconcileHTTPRoutes( for _, filter := range rule.Filters { if filter.ExtensionRef != nil { if filter.ExtensionRef.Group == "" { - filter.ExtensionRef.Group = "extensions.apoxy.dev" + filter.ExtensionRef.Group = extensionsv1alpha2.GroupName } // Handle DirectResponse specially - if string(filter.ExtensionRef.Group) == "extensions.apoxy.dev" && string(filter.ExtensionRef.Kind) == "DirectResponse" { + if string(filter.ExtensionRef.Group) == extensionsv1alpha2.GroupName && string(filter.ExtensionRef.Kind) == "DirectResponse" { log.Info("Processing DirectResponse filter reference", "name", filter.ExtensionRef.Name, "group", filter.ExtensionRef.Group) // Fetch the DirectResponse object diff --git a/pkg/gateway/gatewayapi/filters.go b/pkg/gateway/gatewayapi/filters.go index 2df9770..ee3b34e 100644 --- a/pkg/gateway/gatewayapi/filters.go +++ b/pkg/gateway/gatewayapi/filters.go @@ -12,6 +12,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" gwapiv1 "sigs.k8s.io/gateway-api/apis/v1" + extensionsv1alpha2 "github.com/apoxy-dev/apoxy/api/extensions/v1alpha2" "github.com/apoxy-dev/apoxy/pkg/gateway/ir" "github.com/apoxy-dev/apoxy/pkg/log" ) @@ -662,7 +663,7 @@ func (t *Translator) processExtensionRefHTTPFilter(extFilter *gwapiv1.LocalObjec } // Handle DirectResponse specially - convert to IR DirectResponse - if string(extFilter.Group) == "extensions.apoxy.dev" && string(extFilter.Kind) == "DirectResponse" { + if string(extFilter.Group) == extensionsv1alpha2.GroupName && string(extFilter.Kind) == "DirectResponse" { for _, dr := range resources.DirectResponses { if dr.Name == string(extFilter.Name) { // Convert to IR DirectResponse