From b5a2f2e4c1039c049e19c350ecb2ceb60b8f19ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Patryk=20Ma=C5=82ek?= Date: Wed, 11 Sep 2024 13:24:33 +0200 Subject: [PATCH] feat(crd): add KongUpstream --- .../v1alpha1/kongupstream_types.go | 179 ++++++++ .../v1alpha1/zz_generated.deepcopy.go | 212 ++++++++++ ...onfiguration.konghq.com_kongupstreams.yaml | 395 ++++++++++++++++++ docs/api-reference.md | 85 ++++ go.mod | 2 +- go.sum | 4 +- .../v1alpha1/configuration_client.go | 5 + .../fake/fake_configuration_client.go | 4 + .../v1alpha1/fake/fake_kongupstream.go | 147 +++++++ .../v1alpha1/generated_expansion.go | 2 + .../configuration/v1alpha1/kongupstream.go | 69 +++ 11 files changed, 1101 insertions(+), 3 deletions(-) create mode 100644 api/configuration/v1alpha1/kongupstream_types.go create mode 100644 config/crd/bases/configuration.konghq.com_kongupstreams.yaml create mode 100644 pkg/clientset/typed/configuration/v1alpha1/fake/fake_kongupstream.go create mode 100644 pkg/clientset/typed/configuration/v1alpha1/kongupstream.go diff --git a/api/configuration/v1alpha1/kongupstream_types.go b/api/configuration/v1alpha1/kongupstream_types.go new file mode 100644 index 00000000..a07f3536 --- /dev/null +++ b/api/configuration/v1alpha1/kongupstream_types.go @@ -0,0 +1,179 @@ +/* +Copyright 2024 Kong, 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. +*/ + +package v1alpha1 + +import ( + sdkkonnectgocomp "github.com/Kong/sdk-konnect-go/models/components" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + konnectv1alpha1 "github.com/kong/kubernetes-configuration/api/konnect/v1alpha1" +) + +// KongUpstream is the schema for Upstream API which defines a Kong Upstream. +// +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +// +kubebuilder:object:root=true +// +kubebuilder:resource:scope=Namespaced +// +kubebuilder:storageversion +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Programmed",description="The Resource is Programmed on Konnect",type=string,JSONPath=`.status.conditions[?(@.type=='Programmed')].status` +// +kubebuilder:validation:XValidation:rule="!has(oldSelf.spec.controlPlaneRef) || has(self.spec.controlPlaneRef)", message="controlPlaneRef is required once set" +// +kubebuilder:validation:XValidation:rule="(!self.status.conditions.exists(c, c.type == 'Programmed' && c.status == 'True')) ? true : oldSelf.spec.controlPlaneRef == self.spec.controlPlaneRef", message="spec.controlPlaneRef is immutable when an entity is already Programmed" +type KongUpstream struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec KongUpstreamSpec `json:"spec"` + + // +kubebuilder:default={conditions: {{type: "Programmed", status: "Unknown", reason:"Pending", message:"Waiting for controller", lastTransitionTime: "1970-01-01T00:00:00Z"}}} + Status KongUpstreamStatus `json:"status,omitempty"` +} + +func (s *KongUpstream) initKonnectStatus() { + s.Status.Konnect = &konnectv1alpha1.KonnectEntityStatusWithControlPlaneRef{} +} + +// GetKonnectStatus returns the Konnect status contained in the KongUpstream status. +func (s *KongUpstream) GetKonnectStatus() *konnectv1alpha1.KonnectEntityStatus { + if s.Status.Konnect == nil { + return nil + } + return &s.Status.Konnect.KonnectEntityStatus +} + +// GetKonnectID returns the Konnect ID in the KongUpstream status. +func (s *KongUpstream) GetKonnectID() string { + if s.Status.Konnect == nil { + return "" + } + return s.Status.Konnect.ID +} + +// SetKonnectID sets the Konnect ID in the KongUpstream status. +func (s *KongUpstream) SetKonnectID(id string) { + if s.Status.Konnect == nil { + s.initKonnectStatus() + } + s.Status.Konnect.ID = id +} + +// GetControlPlaneID returns the ControlPlane ID in the KongUpstream status. +func (s *KongUpstream) GetControlPlaneID() string { + if s.Status.Konnect == nil { + return "" + } + return s.Status.Konnect.ControlPlaneID +} + +// SetControlPlaneID sets the ControlPlane ID in the KongUpstream status. +func (s *KongUpstream) SetControlPlaneID(id string) { + if s.Status.Konnect == nil { + s.initKonnectStatus() + } + s.Status.Konnect.ControlPlaneID = id +} + +// GetTypeName returns the KongUpstream Kind name +func (s KongUpstream) GetTypeName() string { + return "KongUpstream" +} + +// GetConditions returns the Status Conditions +func (s *KongUpstream) GetConditions() []metav1.Condition { + return s.Status.Conditions +} + +// SetConditions sets the Status Conditions +func (s *KongUpstream) SetConditions(conditions []metav1.Condition) { + s.Status.Conditions = conditions +} + +// KongUpstreamSpec defines specification of a Kong Route. +type KongUpstreamSpec struct { + // ControlPlaneRef is a reference to a ControlPlane this KongUpstream is associated with. + // +optional + ControlPlaneRef *ControlPlaneRef `json:"controlPlaneRef,omitempty"` + + KongUpstreamAPISpec `json:",inline"` +} + +// KongUpstreamAPISpec defines specification of a Kong Service. +type KongUpstreamAPISpec struct { + // Which load balancing algorithm to use. + Algorithm *sdkkonnectgocomp.UpstreamAlgorithm `default:"round-robin" json:"algorithm"` + // If set, the certificate to be used as client certificate while TLS handshaking to the upstream server. + ClientCertificate *sdkkonnectgocomp.UpstreamClientCertificate `json:"client_certificate,omitempty"` + // What to use as hashing input if the primary `hash_on` does not return a hash (eg. header is missing, or no Consumer identified). Not available if `hash_on` is set to `cookie`. + HashFallback *sdkkonnectgocomp.HashFallback `default:"none" json:"hash_fallback"` + // The header name to take the value from as hash input. Only required when `hash_fallback` is set to `header`. + HashFallbackHeader *string `json:"hash_fallback_header,omitempty"` + // The name of the query string argument to take the value from as hash input. Only required when `hash_fallback` is set to `query_arg`. + HashFallbackQueryArg *string `json:"hash_fallback_query_arg,omitempty"` + // The name of the route URI capture to take the value from as hash input. Only required when `hash_fallback` is set to `uri_capture`. + HashFallbackURICapture *string `json:"hash_fallback_uri_capture,omitempty"` + // What to use as hashing input. Using `none` results in a weighted-round-robin scheme with no hashing. + HashOn *sdkkonnectgocomp.HashOn `default:"none" json:"hash_on"` + // The cookie name to take the value from as hash input. Only required when `hash_on` or `hash_fallback` is set to `cookie`. If the specified cookie is not in the request, Kong will generate a value and set the cookie in the response. + HashOnCookie *string `json:"hash_on_cookie,omitempty"` + // The cookie path to set in the response headers. Only required when `hash_on` or `hash_fallback` is set to `cookie`. + HashOnCookiePath *string `default:"/" json:"hash_on_cookie_path"` + // The header name to take the value from as hash input. Only required when `hash_on` is set to `header`. + HashOnHeader *string `json:"hash_on_header,omitempty"` + // The name of the query string argument to take the value from as hash input. Only required when `hash_on` is set to `query_arg`. + HashOnQueryArg *string `json:"hash_on_query_arg,omitempty"` + // The name of the route URI capture to take the value from as hash input. Only required when `hash_on` is set to `uri_capture`. + HashOnURICapture *string `json:"hash_on_uri_capture,omitempty"` + Healthchecks *sdkkonnectgocomp.Healthchecks `json:"healthchecks,omitempty"` + // The hostname to be used as `Host` header when proxying requests through Kong. + HostHeader *string `json:"host_header,omitempty"` + // This is a hostname, which must be equal to the `host` of a Service. + Name *string `json:"name,omitempty"` + // The number of slots in the load balancer algorithm. If `algorithm` is set to `round-robin`, this setting determines the maximum number of slots. If `algorithm` is set to `consistent-hashing`, this setting determines the actual number of slots in the algorithm. Accepts an integer in the range `10`-`65536`. + Slots *int64 `default:"10000" json:"slots"` + // An optional set of strings associated with the Upstream for grouping and filtering. + Tags []string `json:"tags,omitempty"` + // If set, the balancer will use SRV hostname(if DNS Answer has SRV record) as the proxy upstream `Host`. + UseSrvName *bool `default:"false" json:"use_srv_name"` +} + +// KongUpstreamStatus represents the current status of the Kong Service resource. +type KongUpstreamStatus struct { + // Konnect contains the Konnect entity status. + // +optional + Konnect *konnectv1alpha1.KonnectEntityStatusWithControlPlaneRef `json:"konnect,omitempty"` + + // Conditions describe the status of the Konnect entity. + // +listType=map + // +listMapKey=type + // +kubebuilder:validation:MinItems=1 + // +kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// +kubebuilder:object:root=true + +// KongUpstreamList contains a list of Kong Services. +type KongUpstreamList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []KongUpstream `json:"items"` +} + +func init() { + SchemeBuilder.Register(&KongUpstream{}, &KongUpstreamList{}) +} diff --git a/api/configuration/v1alpha1/zz_generated.deepcopy.go b/api/configuration/v1alpha1/zz_generated.deepcopy.go index 6f46da56..5247102c 100644 --- a/api/configuration/v1alpha1/zz_generated.deepcopy.go +++ b/api/configuration/v1alpha1/zz_generated.deepcopy.go @@ -907,6 +907,218 @@ func (in *KongServiceStatus) DeepCopy() *KongServiceStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KongUpstream) DeepCopyInto(out *KongUpstream) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KongUpstream. +func (in *KongUpstream) DeepCopy() *KongUpstream { + if in == nil { + return nil + } + out := new(KongUpstream) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KongUpstream) 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 *KongUpstreamAPISpec) DeepCopyInto(out *KongUpstreamAPISpec) { + *out = *in + if in.Algorithm != nil { + in, out := &in.Algorithm, &out.Algorithm + *out = new(components.UpstreamAlgorithm) + **out = **in + } + if in.ClientCertificate != nil { + in, out := &in.ClientCertificate, &out.ClientCertificate + *out = new(components.UpstreamClientCertificate) + (*in).DeepCopyInto(*out) + } + if in.HashFallback != nil { + in, out := &in.HashFallback, &out.HashFallback + *out = new(components.HashFallback) + **out = **in + } + if in.HashFallbackHeader != nil { + in, out := &in.HashFallbackHeader, &out.HashFallbackHeader + *out = new(string) + **out = **in + } + if in.HashFallbackQueryArg != nil { + in, out := &in.HashFallbackQueryArg, &out.HashFallbackQueryArg + *out = new(string) + **out = **in + } + if in.HashFallbackURICapture != nil { + in, out := &in.HashFallbackURICapture, &out.HashFallbackURICapture + *out = new(string) + **out = **in + } + if in.HashOn != nil { + in, out := &in.HashOn, &out.HashOn + *out = new(components.HashOn) + **out = **in + } + if in.HashOnCookie != nil { + in, out := &in.HashOnCookie, &out.HashOnCookie + *out = new(string) + **out = **in + } + if in.HashOnCookiePath != nil { + in, out := &in.HashOnCookiePath, &out.HashOnCookiePath + *out = new(string) + **out = **in + } + if in.HashOnHeader != nil { + in, out := &in.HashOnHeader, &out.HashOnHeader + *out = new(string) + **out = **in + } + if in.HashOnQueryArg != nil { + in, out := &in.HashOnQueryArg, &out.HashOnQueryArg + *out = new(string) + **out = **in + } + if in.HashOnURICapture != nil { + in, out := &in.HashOnURICapture, &out.HashOnURICapture + *out = new(string) + **out = **in + } + if in.Healthchecks != nil { + in, out := &in.Healthchecks, &out.Healthchecks + *out = new(components.Healthchecks) + (*in).DeepCopyInto(*out) + } + if in.HostHeader != nil { + in, out := &in.HostHeader, &out.HostHeader + *out = new(string) + **out = **in + } + if in.Name != nil { + in, out := &in.Name, &out.Name + *out = new(string) + **out = **in + } + if in.Slots != nil { + in, out := &in.Slots, &out.Slots + *out = new(int64) + **out = **in + } + if in.Tags != nil { + in, out := &in.Tags, &out.Tags + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.UseSrvName != nil { + in, out := &in.UseSrvName, &out.UseSrvName + *out = new(bool) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KongUpstreamAPISpec. +func (in *KongUpstreamAPISpec) DeepCopy() *KongUpstreamAPISpec { + if in == nil { + return nil + } + out := new(KongUpstreamAPISpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KongUpstreamList) DeepCopyInto(out *KongUpstreamList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]KongUpstream, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KongUpstreamList. +func (in *KongUpstreamList) DeepCopy() *KongUpstreamList { + if in == nil { + return nil + } + out := new(KongUpstreamList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KongUpstreamList) 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 *KongUpstreamSpec) DeepCopyInto(out *KongUpstreamSpec) { + *out = *in + if in.ControlPlaneRef != nil { + in, out := &in.ControlPlaneRef, &out.ControlPlaneRef + *out = new(ControlPlaneRef) + (*in).DeepCopyInto(*out) + } + in.KongUpstreamAPISpec.DeepCopyInto(&out.KongUpstreamAPISpec) +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KongUpstreamSpec. +func (in *KongUpstreamSpec) DeepCopy() *KongUpstreamSpec { + if in == nil { + return nil + } + out := new(KongUpstreamSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KongUpstreamStatus) DeepCopyInto(out *KongUpstreamStatus) { + *out = *in + if in.Konnect != nil { + in, out := &in.Konnect, &out.Konnect + *out = new(konnectv1alpha1.KonnectEntityStatusWithControlPlaneRef) + **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]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KongUpstreamStatus. +func (in *KongUpstreamStatus) DeepCopy() *KongUpstreamStatus { + if in == nil { + return nil + } + out := new(KongUpstreamStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KongVault) DeepCopyInto(out *KongVault) { *out = *in diff --git a/config/crd/bases/configuration.konghq.com_kongupstreams.yaml b/config/crd/bases/configuration.konghq.com_kongupstreams.yaml new file mode 100644 index 00000000..4d99e748 --- /dev/null +++ b/config/crd/bases/configuration.konghq.com_kongupstreams.yaml @@ -0,0 +1,395 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.16.2 + name: kongupstreams.configuration.konghq.com +spec: + group: configuration.konghq.com + names: + kind: KongUpstream + listKind: KongUpstreamList + plural: kongupstreams + singular: kongupstream + scope: Namespaced + versions: + - additionalPrinterColumns: + - description: The Resource is Programmed on Konnect + jsonPath: .status.conditions[?(@.type=='Programmed')].status + name: Programmed + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: KongUpstream is the schema for Upstream API which defines a Kong + Upstream. + properties: + apiVersion: + description: |- + APIVersion defines the versioned schema of this representation of an object. + Servers should convert recognized schemas to the latest internal value, and + may reject unrecognized values. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources + type: string + kind: + description: |- + Kind is a string value representing the REST resource this object represents. + Servers may infer this from the endpoint the client submits requests to. + Cannot be updated. + In CamelCase. + More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds + type: string + metadata: + type: object + spec: + description: KongUpstreamSpec defines specification of a Kong Route. + properties: + algorithm: + description: Which load balancing algorithm to use. + type: string + client_certificate: + description: If set, the certificate to be used as client certificate + while TLS handshaking to the upstream server. + properties: + id: + type: string + type: object + controlPlaneRef: + description: ControlPlaneRef is a reference to a ControlPlane this + KongUpstream is associated with. + properties: + konnectID: + description: |- + KonnectID is the schema for the KonnectID type. + This field is required when the Type is konnectID. + type: string + konnectNamespacedRef: + description: |- + KonnectNamespacedRef is a reference to a Konnect Control Plane entity inside the cluster. + It contains the name of the Konnect Control Plane. + This field is required when the Type is konnectNamespacedRef. + properties: + name: + description: Name is the name of the Konnect Control Plane. + type: string + required: + - name + type: object + type: + description: |- + Type can be one of: + - konnectID + - konnectNamespacedRef + enum: + - konnectID + - konnectNamespacedRef + type: string + type: object + x-kubernetes-validations: + - message: when type is konnectNamespacedRef, konnectNamespacedRef + must be set + rule: 'self.type == ''konnectNamespacedRef'' ? has(self.konnectNamespacedRef) + : true' + - message: when type is konnectID, konnectID must be set + rule: 'self.type == ''konnectID'' ? has(self.konnectID) : true' + hash_fallback: + description: What to use as hashing input if the primary `hash_on` + does not return a hash (eg. header is missing, or no Consumer identified). + Not available if `hash_on` is set to `cookie`. + type: string + hash_fallback_header: + description: The header name to take the value from as hash input. + Only required when `hash_fallback` is set to `header`. + type: string + hash_fallback_query_arg: + description: The name of the query string argument to take the value + from as hash input. Only required when `hash_fallback` is set to + `query_arg`. + type: string + hash_fallback_uri_capture: + description: The name of the route URI capture to take the value from + as hash input. Only required when `hash_fallback` is set to `uri_capture`. + type: string + hash_on: + description: What to use as hashing input. Using `none` results in + a weighted-round-robin scheme with no hashing. + type: string + hash_on_cookie: + description: The cookie name to take the value from as hash input. + Only required when `hash_on` or `hash_fallback` is set to `cookie`. + If the specified cookie is not in the request, Kong will generate + a value and set the cookie in the response. + type: string + hash_on_cookie_path: + description: The cookie path to set in the response headers. Only + required when `hash_on` or `hash_fallback` is set to `cookie`. + type: string + hash_on_header: + description: The header name to take the value from as hash input. + Only required when `hash_on` is set to `header`. + type: string + hash_on_query_arg: + description: The name of the query string argument to take the value + from as hash input. Only required when `hash_on` is set to `query_arg`. + type: string + hash_on_uri_capture: + description: The name of the route URI capture to take the value from + as hash input. Only required when `hash_on` is set to `uri_capture`. + type: string + healthchecks: + properties: + active: + properties: + concurrency: + format: int64 + type: integer + headers: + additionalProperties: + type: string + type: object + healthy: + properties: + http_statuses: + items: + format: int64 + type: integer + type: array + interval: + type: number + successes: + format: int64 + type: integer + required: + - interval + - successes + type: object + http_path: + type: string + https_sni: + type: string + https_verify_certificate: + type: boolean + timeout: + type: number + type: + type: string + unhealthy: + properties: + http_failures: + format: int64 + type: integer + http_statuses: + items: + format: int64 + type: integer + type: array + interval: + type: number + tcp_failures: + format: int64 + type: integer + timeouts: + format: int64 + type: integer + required: + - http_failures + - interval + - tcp_failures + - timeouts + type: object + required: + - concurrency + - http_path + - https_verify_certificate + - timeout + - type + type: object + passive: + properties: + healthy: + properties: + http_statuses: + items: + format: int64 + type: integer + type: array + successes: + format: int64 + type: integer + required: + - successes + type: object + type: + type: string + unhealthy: + properties: + http_failures: + format: int64 + type: integer + http_statuses: + items: + format: int64 + type: integer + type: array + tcp_failures: + format: int64 + type: integer + timeouts: + format: int64 + type: integer + required: + - http_failures + - tcp_failures + - timeouts + type: object + required: + - type + type: object + threshold: + type: number + required: + - threshold + type: object + host_header: + description: The hostname to be used as `Host` header when proxying + requests through Kong. + type: string + name: + description: This is a hostname, which must be equal to the `host` + of a Service. + type: string + slots: + description: The number of slots in the load balancer algorithm. If + `algorithm` is set to `round-robin`, this setting determines the + maximum number of slots. If `algorithm` is set to `consistent-hashing`, + this setting determines the actual number of slots in the algorithm. + Accepts an integer in the range `10`-`65536`. + format: int64 + type: integer + tags: + description: An optional set of strings associated with the Upstream + for grouping and filtering. + items: + type: string + type: array + use_srv_name: + description: If set, the balancer will use SRV hostname(if DNS Answer + has SRV record) as the proxy upstream `Host`. + type: boolean + required: + - algorithm + - hash_fallback + - hash_on + - hash_on_cookie_path + - slots + - use_srv_name + type: object + status: + default: + conditions: + - lastTransitionTime: "1970-01-01T00:00:00Z" + message: Waiting for controller + reason: Pending + status: Unknown + type: Programmed + description: KongUpstreamStatus represents the current status of the Kong + Service resource. + properties: + conditions: + description: Conditions describe the status of the Konnect entity. + items: + description: Condition contains details for one aspect of the current + state of this API Resource. + properties: + lastTransitionTime: + description: |- + lastTransitionTime is the last time the condition transitioned from one status to another. + This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable. + format: date-time + type: string + message: + description: |- + message is a human readable message indicating details about the transition. + This may be an empty string. + maxLength: 32768 + type: string + observedGeneration: + description: |- + observedGeneration represents the .metadata.generation that the condition was set based upon. + For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date + with respect to the current state of the instance. + format: int64 + minimum: 0 + type: integer + reason: + description: |- + reason contains a programmatic identifier indicating the reason for the condition's last transition. + Producers of specific condition types may define expected values and meanings for this field, + and whether the values are considered a guaranteed API. + The value should be a CamelCase string. + This field may not be empty. + maxLength: 1024 + minLength: 1 + pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$ + type: string + status: + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown + type: string + type: + description: type of condition in CamelCase or in foo.example.com/CamelCase. + maxLength: 316 + pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$ + type: string + required: + - lastTransitionTime + - message + - reason + - status + - type + type: object + maxItems: 8 + minItems: 1 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + konnect: + description: Konnect contains the Konnect entity status. + properties: + controlPlaneID: + description: ControlPlaneID is the Konnect ID of the ControlPlane + this Route is associated with. + type: string + id: + description: |- + ID is the unique identifier of the Konnect entity as assigned by Konnect API. + If it's unset (empty string), it means the Konnect entity hasn't been created yet. + type: string + organizationID: + description: OrgID is ID of Konnect Org that this entity has been + created in. + type: string + serverURL: + description: ServerURL is the URL of the Konnect server in which + the entity exists. + type: string + type: object + type: object + required: + - spec + type: object + x-kubernetes-validations: + - message: controlPlaneRef is required once set + rule: '!has(oldSelf.spec.controlPlaneRef) || has(self.spec.controlPlaneRef)' + - message: spec.controlPlaneRef is immutable when an entity is already Programmed + rule: '(!self.status.conditions.exists(c, c.type == ''Programmed'' && c.status + == ''True'')) ? true : oldSelf.spec.controlPlaneRef == self.spec.controlPlaneRef' + served: true + storage: true + subresources: + status: {} diff --git a/docs/api-reference.md b/docs/api-reference.md index 12c99f78..f2786a88 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -334,6 +334,7 @@ Package v1alpha1 contains API Schema definitions for the configuration.konghq.co - [KongPluginBinding](#kongpluginbinding) - [KongRoute](#kongroute) - [KongService](#kongservice) +- [KongUpstream](#kongupstream) - [KongVault](#kongvault) ### IngressClassParameters @@ -432,6 +433,22 @@ KongService is the schema for Services API which defines a Kong Service. +### KongUpstream + + +KongUpstream is the schema for Upstream API which defines a Kong Upstream. + + + +| Field | Description | +| --- | --- | +| `apiVersion` _string_ | `configuration.konghq.com/v1alpha1` +| `kind` _string_ | `KongUpstream` +| `metadata` _[ObjectMeta](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#objectmeta-v1-meta)_ | Refer to Kubernetes API documentation for fields of `metadata`. | +| `spec` _[KongUpstreamSpec](#kongupstreamspec)_ | | + + + ### KongVault @@ -473,6 +490,7 @@ _Appears in:_ - [KongConsumerSpec](#kongconsumerspec) - [KongPluginBindingSpec](#kongpluginbindingspec) - [KongServiceSpec](#kongservicespec) +- [KongUpstreamSpec](#kongupstreamspec) #### ControllerReference @@ -740,6 +758,73 @@ _Appears in:_ +#### KongUpstreamAPISpec + + +KongUpstreamAPISpec defines specification of a Kong Service. + + + +| Field | Description | +| --- | --- | +| `algorithm` _[UpstreamAlgorithm](#upstreamalgorithm)_ | Which load balancing algorithm to use. | +| `client_certificate` _[UpstreamClientCertificate](#upstreamclientcertificate)_ | If set, the certificate to be used as client certificate while TLS handshaking to the upstream server. | +| `hash_fallback` _[HashFallback](#hashfallback)_ | What to use as hashing input if the primary `hash_on` does not return a hash (eg. header is missing, or no Consumer identified). Not available if `hash_on` is set to `cookie`. | +| `hash_fallback_header` _string_ | The header name to take the value from as hash input. Only required when `hash_fallback` is set to `header`. | +| `hash_fallback_query_arg` _string_ | The name of the query string argument to take the value from as hash input. Only required when `hash_fallback` is set to `query_arg`. | +| `hash_fallback_uri_capture` _string_ | The name of the route URI capture to take the value from as hash input. Only required when `hash_fallback` is set to `uri_capture`. | +| `hash_on` _[HashOn](#hashon)_ | What to use as hashing input. Using `none` results in a weighted-round-robin scheme with no hashing. | +| `hash_on_cookie` _string_ | The cookie name to take the value from as hash input. Only required when `hash_on` or `hash_fallback` is set to `cookie`. If the specified cookie is not in the request, Kong will generate a value and set the cookie in the response. | +| `hash_on_cookie_path` _string_ | The cookie path to set in the response headers. Only required when `hash_on` or `hash_fallback` is set to `cookie`. | +| `hash_on_header` _string_ | The header name to take the value from as hash input. Only required when `hash_on` is set to `header`. | +| `hash_on_query_arg` _string_ | The name of the query string argument to take the value from as hash input. Only required when `hash_on` is set to `query_arg`. | +| `hash_on_uri_capture` _string_ | The name of the route URI capture to take the value from as hash input. Only required when `hash_on` is set to `uri_capture`. | +| `healthchecks` _[Healthchecks](#healthchecks)_ | | +| `host_header` _string_ | The hostname to be used as `Host` header when proxying requests through Kong. | +| `name` _string_ | This is a hostname, which must be equal to the `host` of a Service. | +| `slots` _integer_ | The number of slots in the load balancer algorithm. If `algorithm` is set to `round-robin`, this setting determines the maximum number of slots. If `algorithm` is set to `consistent-hashing`, this setting determines the actual number of slots in the algorithm. Accepts an integer in the range `10`-`65536`. | +| `tags` _string array_ | An optional set of strings associated with the Upstream for grouping and filtering. | +| `use_srv_name` _boolean_ | If set, the balancer will use SRV hostname(if DNS Answer has SRV record) as the proxy upstream `Host`. | + + +_Appears in:_ +- [KongUpstreamSpec](#kongupstreamspec) + +#### KongUpstreamSpec + + +KongUpstreamSpec defines specification of a Kong Route. + + + +| Field | Description | +| --- | --- | +| `controlPlaneRef` _[ControlPlaneRef](#controlplaneref)_ | ControlPlaneRef is a reference to a ControlPlane this KongUpstream is associated with. | +| `algorithm` _[UpstreamAlgorithm](#upstreamalgorithm)_ | Which load balancing algorithm to use. | +| `client_certificate` _[UpstreamClientCertificate](#upstreamclientcertificate)_ | If set, the certificate to be used as client certificate while TLS handshaking to the upstream server. | +| `hash_fallback` _[HashFallback](#hashfallback)_ | What to use as hashing input if the primary `hash_on` does not return a hash (eg. header is missing, or no Consumer identified). Not available if `hash_on` is set to `cookie`. | +| `hash_fallback_header` _string_ | The header name to take the value from as hash input. Only required when `hash_fallback` is set to `header`. | +| `hash_fallback_query_arg` _string_ | The name of the query string argument to take the value from as hash input. Only required when `hash_fallback` is set to `query_arg`. | +| `hash_fallback_uri_capture` _string_ | The name of the route URI capture to take the value from as hash input. Only required when `hash_fallback` is set to `uri_capture`. | +| `hash_on` _[HashOn](#hashon)_ | What to use as hashing input. Using `none` results in a weighted-round-robin scheme with no hashing. | +| `hash_on_cookie` _string_ | The cookie name to take the value from as hash input. Only required when `hash_on` or `hash_fallback` is set to `cookie`. If the specified cookie is not in the request, Kong will generate a value and set the cookie in the response. | +| `hash_on_cookie_path` _string_ | The cookie path to set in the response headers. Only required when `hash_on` or `hash_fallback` is set to `cookie`. | +| `hash_on_header` _string_ | The header name to take the value from as hash input. Only required when `hash_on` is set to `header`. | +| `hash_on_query_arg` _string_ | The name of the query string argument to take the value from as hash input. Only required when `hash_on` is set to `query_arg`. | +| `hash_on_uri_capture` _string_ | The name of the route URI capture to take the value from as hash input. Only required when `hash_on` is set to `uri_capture`. | +| `healthchecks` _[Healthchecks](#healthchecks)_ | | +| `host_header` _string_ | The hostname to be used as `Host` header when proxying requests through Kong. | +| `name` _string_ | This is a hostname, which must be equal to the `host` of a Service. | +| `slots` _integer_ | The number of slots in the load balancer algorithm. If `algorithm` is set to `round-robin`, this setting determines the maximum number of slots. If `algorithm` is set to `consistent-hashing`, this setting determines the actual number of slots in the algorithm. Accepts an integer in the range `10`-`65536`. | +| `tags` _string array_ | An optional set of strings associated with the Upstream for grouping and filtering. | +| `use_srv_name` _boolean_ | If set, the balancer will use SRV hostname(if DNS Answer has SRV record) as the proxy upstream `Host`. | + + +_Appears in:_ +- [KongUpstream](#kongupstream) + + + #### KongVaultSpec diff --git a/go.mod b/go.mod index 7bafe476..3089a9dc 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/kong/kubernetes-configuration go 1.22.4 require ( - github.com/Kong/sdk-konnect-go v0.0.6 + github.com/Kong/sdk-konnect-go v0.0.8 github.com/kong/go-kong v0.59.0 github.com/stretchr/testify v1.9.0 k8s.io/api v0.31.0 diff --git a/go.sum b/go.sum index 181704cd..61363aab 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/Kong/sdk-konnect-go v0.0.6 h1:dbE8p96ys/GJEsmnC5EoJ/qSJxG3pEVCRPO2hpoek5E= -github.com/Kong/sdk-konnect-go v0.0.6/go.mod h1:ipu67aQNnwDzu/LXKePG46cVqkkZnAHKWpsbhTEI8xE= +github.com/Kong/sdk-konnect-go v0.0.8 h1:dfssXOktBykRtga9PpAKOTLQVq0DKyd4jFnUgMZlTNc= +github.com/Kong/sdk-konnect-go v0.0.8/go.mod h1:ipu67aQNnwDzu/LXKePG46cVqkkZnAHKWpsbhTEI8xE= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= diff --git a/pkg/clientset/typed/configuration/v1alpha1/configuration_client.go b/pkg/clientset/typed/configuration/v1alpha1/configuration_client.go index 593985b1..8c7004eb 100644 --- a/pkg/clientset/typed/configuration/v1alpha1/configuration_client.go +++ b/pkg/clientset/typed/configuration/v1alpha1/configuration_client.go @@ -34,6 +34,7 @@ type ConfigurationV1alpha1Interface interface { KongPluginBindingsGetter KongRoutesGetter KongServicesGetter + KongUpstreamsGetter KongVaultsGetter } @@ -66,6 +67,10 @@ func (c *ConfigurationV1alpha1Client) KongServices(namespace string) KongService return newKongServices(c, namespace) } +func (c *ConfigurationV1alpha1Client) KongUpstreams(namespace string) KongUpstreamInterface { + return newKongUpstreams(c, namespace) +} + func (c *ConfigurationV1alpha1Client) KongVaults() KongVaultInterface { return newKongVaults(c) } diff --git a/pkg/clientset/typed/configuration/v1alpha1/fake/fake_configuration_client.go b/pkg/clientset/typed/configuration/v1alpha1/fake/fake_configuration_client.go index a418265c..b4ce4cba 100644 --- a/pkg/clientset/typed/configuration/v1alpha1/fake/fake_configuration_client.go +++ b/pkg/clientset/typed/configuration/v1alpha1/fake/fake_configuration_client.go @@ -52,6 +52,10 @@ func (c *FakeConfigurationV1alpha1) KongServices(namespace string) v1alpha1.Kong return &FakeKongServices{c, namespace} } +func (c *FakeConfigurationV1alpha1) KongUpstreams(namespace string) v1alpha1.KongUpstreamInterface { + return &FakeKongUpstreams{c, namespace} +} + func (c *FakeConfigurationV1alpha1) KongVaults() v1alpha1.KongVaultInterface { return &FakeKongVaults{c} } diff --git a/pkg/clientset/typed/configuration/v1alpha1/fake/fake_kongupstream.go b/pkg/clientset/typed/configuration/v1alpha1/fake/fake_kongupstream.go new file mode 100644 index 00000000..c4d7a480 --- /dev/null +++ b/pkg/clientset/typed/configuration/v1alpha1/fake/fake_kongupstream.go @@ -0,0 +1,147 @@ +/* +Copyright 2021 Kong, 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 ( + "context" + + v1alpha1 "github.com/kong/kubernetes-configuration/api/configuration/v1alpha1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + labels "k8s.io/apimachinery/pkg/labels" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + testing "k8s.io/client-go/testing" +) + +// FakeKongUpstreams implements KongUpstreamInterface +type FakeKongUpstreams struct { + Fake *FakeConfigurationV1alpha1 + ns string +} + +var kongupstreamsResource = v1alpha1.SchemeGroupVersion.WithResource("kongupstreams") + +var kongupstreamsKind = v1alpha1.SchemeGroupVersion.WithKind("KongUpstream") + +// Get takes name of the kongUpstream, and returns the corresponding kongUpstream object, and an error if there is any. +func (c *FakeKongUpstreams) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.KongUpstream, err error) { + emptyResult := &v1alpha1.KongUpstream{} + obj, err := c.Fake. + Invokes(testing.NewGetActionWithOptions(kongupstreamsResource, c.ns, name, options), emptyResult) + + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.KongUpstream), err +} + +// List takes label and field selectors, and returns the list of KongUpstreams that match those selectors. +func (c *FakeKongUpstreams) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.KongUpstreamList, err error) { + emptyResult := &v1alpha1.KongUpstreamList{} + obj, err := c.Fake. + Invokes(testing.NewListActionWithOptions(kongupstreamsResource, kongupstreamsKind, c.ns, opts), emptyResult) + + if obj == nil { + return emptyResult, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.KongUpstreamList{ListMeta: obj.(*v1alpha1.KongUpstreamList).ListMeta} + for _, item := range obj.(*v1alpha1.KongUpstreamList).Items { + if label.Matches(labels.Set(item.Labels)) { + list.Items = append(list.Items, item) + } + } + return list, err +} + +// Watch returns a watch.Interface that watches the requested kongUpstreams. +func (c *FakeKongUpstreams) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchActionWithOptions(kongupstreamsResource, c.ns, opts)) + +} + +// Create takes the representation of a kongUpstream and creates it. Returns the server's representation of the kongUpstream, and an error, if there is any. +func (c *FakeKongUpstreams) Create(ctx context.Context, kongUpstream *v1alpha1.KongUpstream, opts v1.CreateOptions) (result *v1alpha1.KongUpstream, err error) { + emptyResult := &v1alpha1.KongUpstream{} + obj, err := c.Fake. + Invokes(testing.NewCreateActionWithOptions(kongupstreamsResource, c.ns, kongUpstream, opts), emptyResult) + + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.KongUpstream), err +} + +// Update takes the representation of a kongUpstream and updates it. Returns the server's representation of the kongUpstream, and an error, if there is any. +func (c *FakeKongUpstreams) Update(ctx context.Context, kongUpstream *v1alpha1.KongUpstream, opts v1.UpdateOptions) (result *v1alpha1.KongUpstream, err error) { + emptyResult := &v1alpha1.KongUpstream{} + obj, err := c.Fake. + Invokes(testing.NewUpdateActionWithOptions(kongupstreamsResource, c.ns, kongUpstream, opts), emptyResult) + + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.KongUpstream), err +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *FakeKongUpstreams) UpdateStatus(ctx context.Context, kongUpstream *v1alpha1.KongUpstream, opts v1.UpdateOptions) (result *v1alpha1.KongUpstream, err error) { + emptyResult := &v1alpha1.KongUpstream{} + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceActionWithOptions(kongupstreamsResource, "status", c.ns, kongUpstream, opts), emptyResult) + + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.KongUpstream), err +} + +// Delete takes name of the kongUpstream and deletes it. Returns an error if one occurs. +func (c *FakeKongUpstreams) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(kongupstreamsResource, c.ns, name, opts), &v1alpha1.KongUpstream{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeKongUpstreams) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionActionWithOptions(kongupstreamsResource, c.ns, opts, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.KongUpstreamList{}) + return err +} + +// Patch applies the patch and returns the patched kongUpstream. +func (c *FakeKongUpstreams) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.KongUpstream, err error) { + emptyResult := &v1alpha1.KongUpstream{} + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceActionWithOptions(kongupstreamsResource, c.ns, name, pt, data, opts, subresources...), emptyResult) + + if obj == nil { + return emptyResult, err + } + return obj.(*v1alpha1.KongUpstream), err +} diff --git a/pkg/clientset/typed/configuration/v1alpha1/generated_expansion.go b/pkg/clientset/typed/configuration/v1alpha1/generated_expansion.go index 5c589a0c..e086ae5a 100644 --- a/pkg/clientset/typed/configuration/v1alpha1/generated_expansion.go +++ b/pkg/clientset/typed/configuration/v1alpha1/generated_expansion.go @@ -30,4 +30,6 @@ type KongRouteExpansion interface{} type KongServiceExpansion interface{} +type KongUpstreamExpansion interface{} + type KongVaultExpansion interface{} diff --git a/pkg/clientset/typed/configuration/v1alpha1/kongupstream.go b/pkg/clientset/typed/configuration/v1alpha1/kongupstream.go new file mode 100644 index 00000000..c27c2777 --- /dev/null +++ b/pkg/clientset/typed/configuration/v1alpha1/kongupstream.go @@ -0,0 +1,69 @@ +/* +Copyright 2021 Kong, 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 ( + "context" + + v1alpha1 "github.com/kong/kubernetes-configuration/api/configuration/v1alpha1" + scheme "github.com/kong/kubernetes-configuration/pkg/clientset/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + gentype "k8s.io/client-go/gentype" +) + +// KongUpstreamsGetter has a method to return a KongUpstreamInterface. +// A group's client should implement this interface. +type KongUpstreamsGetter interface { + KongUpstreams(namespace string) KongUpstreamInterface +} + +// KongUpstreamInterface has methods to work with KongUpstream resources. +type KongUpstreamInterface interface { + Create(ctx context.Context, kongUpstream *v1alpha1.KongUpstream, opts v1.CreateOptions) (*v1alpha1.KongUpstream, error) + Update(ctx context.Context, kongUpstream *v1alpha1.KongUpstream, opts v1.UpdateOptions) (*v1alpha1.KongUpstream, error) + // Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). + UpdateStatus(ctx context.Context, kongUpstream *v1alpha1.KongUpstream, opts v1.UpdateOptions) (*v1alpha1.KongUpstream, error) + Delete(ctx context.Context, name string, opts v1.DeleteOptions) error + DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error + Get(ctx context.Context, name string, opts v1.GetOptions) (*v1alpha1.KongUpstream, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.KongUpstreamList, error) + Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) + Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.KongUpstream, err error) + KongUpstreamExpansion +} + +// kongUpstreams implements KongUpstreamInterface +type kongUpstreams struct { + *gentype.ClientWithList[*v1alpha1.KongUpstream, *v1alpha1.KongUpstreamList] +} + +// newKongUpstreams returns a KongUpstreams +func newKongUpstreams(c *ConfigurationV1alpha1Client, namespace string) *kongUpstreams { + return &kongUpstreams{ + gentype.NewClientWithList[*v1alpha1.KongUpstream, *v1alpha1.KongUpstreamList]( + "kongupstreams", + c.RESTClient(), + scheme.ParameterCodec, + namespace, + func() *v1alpha1.KongUpstream { return &v1alpha1.KongUpstream{} }, + func() *v1alpha1.KongUpstreamList { return &v1alpha1.KongUpstreamList{} }), + } +}