From 3bb4a56acd26f796da90fd5737b51f1399a68a15 Mon Sep 17 00:00:00 2001 From: Jakub Warczarek Date: Mon, 8 Jul 2024 20:30:39 +0200 Subject: [PATCH 1/9] fix(scaffolding): provide custom path for kustomize --- Makefile | 2 +- hack/generators/kic/kustomize.go | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 36d94dc1a..ee9b96fbd 100644 --- a/Makefile +++ b/Makefile @@ -234,7 +234,7 @@ generate.testcases-registration: .PHONY: generate.kic-webhook-config generate.kic-webhook-config: kic-webhook-config-generator - $(KIC_WEBHOOKCONFIG_GENERATOR) + KUSTOMIZE=$(KUSTOMIZE) $(KIC_WEBHOOKCONFIG_GENERATOR) # ------------------------------------------------------------------------------ # Files generation checks diff --git a/hack/generators/kic/kustomize.go b/hack/generators/kic/kustomize.go index e078399ba..638ef25e8 100644 --- a/hack/generators/kic/kustomize.go +++ b/hack/generators/kic/kustomize.go @@ -5,6 +5,7 @@ import ( "fmt" "io" "log" + "os" "os/exec" ) @@ -14,7 +15,11 @@ func BuildKustomizeForURLAndRef(ctx context.Context, url, ref string) ([]byte, e kustomizeResourceURL := fmt.Sprintf("%s?ref=%s", url, ref) log.Printf("Running 'kustomize build %s'\n", kustomizeResourceURL) - cmd := exec.CommandContext(ctx, "kustomize", "build", kustomizeResourceURL) + kustomize := "kustomize" + if k := os.Getenv("KUSTOMIZE"); k != "" { + kustomize = k + } + cmd := exec.CommandContext(ctx, kustomize, "build", kustomizeResourceURL) stdout, err := cmd.StdoutPipe() if err != nil { return nil, err From 4f0729e39908931a2f49e1054271c0c90902cf24 Mon Sep 17 00:00:00 2001 From: Jakub Warczarek Date: Mon, 8 Jul 2024 20:34:11 +0200 Subject: [PATCH 2/9] feat: introduce CRD KongPluginInstallation --- CHANGELOG.md | 2 + api/v1alpha1/kongplugin_installation.go | 129 ++++++++++++ api/v1alpha1/zz_generated.deepcopy.go | 102 +++++++++ ...or.konghq.com_kongplugininstallations.yaml | 159 ++++++++++++++ docs/api-reference.md | 55 +++++ hack/generators/kic/role-generator/main.go | 2 +- .../typed/apis/v1alpha1/apis_client.go | 5 + .../apis/v1alpha1/fake/fake_apis_client.go | 4 + .../fake/fake_kongplugininstallation.go | 141 +++++++++++++ .../apis/v1alpha1/generated_expansion.go | 2 + .../apis/v1alpha1/kongplugininstallation.go | 195 ++++++++++++++++++ 11 files changed, 795 insertions(+), 1 deletion(-) create mode 100644 api/v1alpha1/kongplugin_installation.go create mode 100644 config/crd/bases/gateway-operator.konghq.com_kongplugininstallations.yaml create mode 100644 pkg/clientset/typed/apis/v1alpha1/fake/fake_kongplugininstallation.go create mode 100644 pkg/clientset/typed/apis/v1alpha1/kongplugininstallation.go diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e72ebdd5..e3cbb1b77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,6 +29,8 @@ - Proper `User-Agent` header is now set on outgoing HTTP requests. [#387](https://github.com/Kong/gateway-operator/pull/387) +- Introduce `KongPluginInstallation` CRD + [400](https://github.com/Kong/gateway-operator/pull/400) ### Fixed diff --git a/api/v1alpha1/kongplugin_installation.go b/api/v1alpha1/kongplugin_installation.go new file mode 100644 index 000000000..812657c1a --- /dev/null +++ b/api/v1alpha1/kongplugin_installation.go @@ -0,0 +1,129 @@ +/* +Copyright 2022 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 ( + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" +) + +func init() { + SchemeBuilder.Register(&KongPluginInstallation{}, &KongPluginInstallationList{}) +} + +//+genclient +//+k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object +//+kubebuilder:object:root=true +//+kubebuilder:subresource:status +//+kubebuilder:resource:shortName=kpi,categories=kong;all +//+kubebuilder:subresource:status +//+kubebuilder:printcolumn:name="Programmed",type=string,JSONPath=`.status.conditions[?(@.type=="Programmed")].status` + +// KongPluginInstallation allows to use a custom Kong Plugin distributed as a container image available in a registry. +// Such plugin can be associated with GatewayConfiguration or DataPlane to be available for particular Kong Gateway +// and to be configured with KongPlugin CRD. +type KongPluginInstallation struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec KongPluginInstallationSpec `json:"spec,omitempty"` + Status KongPluginInstallationStatus `json:"status,omitempty"` +} + +//+kubebuilder:object:root=true + +// KongPluginInstallationList contains a list of KongPluginInstallation. +type KongPluginInstallationList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []KongPluginInstallation `json:"items"` +} + +// KongPluginInstallationSpec defines the desired state of KongPluginInstallation. +type KongPluginInstallationSpec struct { + + // Image is OCI image URL for a packaged Custom Kong Plugin. + // + //+kubebuilder:validation:Required + Image string `json:"image"` + + // SecretRef allows specifying secret to be used for OCI registry authentication to pull the image with custom Kong Plugin. + // The Secret format should follow https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry. + // When field is omitted it is assumed that the image is public and can be fetched without providing any credentials. + // + //+optional + SecretRef *corev1.SecretReference `json:"secretRef,omitempty"` +} + +// KongPluginInstallationStatus defines the observed state of KongPluginInstallation. +type KongPluginInstallationStatus struct { + // Conditions describe the current conditions of this KongPluginInstallation. + // + //+listType=map + //+listMapKey=type + //+kubebuilder:validation:MaxItems=8 + Conditions []metav1.Condition `json:"conditions,omitempty"` +} + +// KongPluginInstallationConditionType is the type for status conditions on +// KongPluginInstallation resources. This type should be used with the +// KongPluginInstallationStatus.Conditions field. +type KongPluginInstallationConditionType string + +// KongPluginInstallationConditionReason defines the set of reasons that explain why +// a particular KongPluginInstallation condition type has been raised. +type KongPluginInstallationConditionReason string + +const ( + // This condition indicates whether the controller has fetched and make + // available for use a specific Custom Kong Plugin. + // + // It is a positive-polarity summary condition, and so should always be + // present on the resource with ObservedGeneration set. + // + // It should be set to Unknown if the controller performs updates to the + // status before it has all the information it needs to be able to determine + // if the condition is true. + // + // Possible reasons for this condition to be true are: + // + // * "Programmed" + // + // Possible reasons for this condition to be False are: + // + // * "Invalid" + // * "Fetching" + // + // Possible reasons for this condition to be Unknown are: + // + // * "Fetching". + // + + // Controllers should prefer to use the values of KongPluginInstallationConditionReason + // for the corresponding Reason, where appropriate. + KongPluginInstallationConditionStatusAccepted KongPluginInstallationConditionType = "Accepted" + + // This reason is used with the "Accepted" condition when the KongPluginInstallation + // was not accepted because image can't be fetched, more details can be obtained from the + // condition's message. + KongPluginInstallationReasonInvalidParameters KongPluginInstallationConditionReason = "Invalid" + + // This reason is used with the "Accepted" condition when the + // requested controller has started processing the KongPluginInstallation, + // but it haven't yet finished. + KongPluginInstallationReasonPending KongPluginInstallationConditionReason = "Fetching" +) diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index e8b9e3655..64af57dd4 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -21,6 +21,7 @@ limitations under the License. package v1alpha1 import ( + corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -371,6 +372,107 @@ func (in *ExtensionRef) DeepCopy() *ExtensionRef { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KongPluginInstallation) DeepCopyInto(out *KongPluginInstallation) { + *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 KongPluginInstallation. +func (in *KongPluginInstallation) DeepCopy() *KongPluginInstallation { + if in == nil { + return nil + } + out := new(KongPluginInstallation) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KongPluginInstallation) 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 *KongPluginInstallationList) DeepCopyInto(out *KongPluginInstallationList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]KongPluginInstallation, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KongPluginInstallationList. +func (in *KongPluginInstallationList) DeepCopy() *KongPluginInstallationList { + if in == nil { + return nil + } + out := new(KongPluginInstallationList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *KongPluginInstallationList) 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 *KongPluginInstallationSpec) DeepCopyInto(out *KongPluginInstallationSpec) { + *out = *in + if in.SecretRef != nil { + in, out := &in.SecretRef, &out.SecretRef + *out = new(corev1.SecretReference) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new KongPluginInstallationSpec. +func (in *KongPluginInstallationSpec) DeepCopy() *KongPluginInstallationSpec { + if in == nil { + return nil + } + out := new(KongPluginInstallationSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *KongPluginInstallationStatus) DeepCopyInto(out *KongPluginInstallationStatus) { + *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 KongPluginInstallationStatus. +func (in *KongPluginInstallationStatus) DeepCopy() *KongPluginInstallationStatus { + if in == nil { + return nil + } + out := new(KongPluginInstallationStatus) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LLMPrompt) DeepCopyInto(out *LLMPrompt) { *out = *in diff --git a/config/crd/bases/gateway-operator.konghq.com_kongplugininstallations.yaml b/config/crd/bases/gateway-operator.konghq.com_kongplugininstallations.yaml new file mode 100644 index 000000000..058dad253 --- /dev/null +++ b/config/crd/bases/gateway-operator.konghq.com_kongplugininstallations.yaml @@ -0,0 +1,159 @@ +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + annotations: + controller-gen.kubebuilder.io/version: v0.15.0 + name: kongplugininstallations.gateway-operator.konghq.com +spec: + group: gateway-operator.konghq.com + names: + categories: + - kong + - all + kind: KongPluginInstallation + listKind: KongPluginInstallationList + plural: kongplugininstallations + shortNames: + - kpi + singular: kongplugininstallation + scope: Namespaced + versions: + - additionalPrinterColumns: + - jsonPath: .status.conditions[?(@.type=="Programmed")].status + name: Programmed + type: string + name: v1alpha1 + schema: + openAPIV3Schema: + description: |- + KongPluginInstallation allows to use a custom Kong Plugin distributed as a container image available in a registry. + Such plugin can be associated with GatewayConfiguration or DataPlane to be available for particular Kong Gateway + and to be configured with KongPlugin CRD. + 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: KongPluginInstallationSpec defines the desired state of KongPluginInstallation. + properties: + image: + description: Image is OCI image URL for a packaged Custom Kong Plugin. + type: string + secretRef: + description: |- + SecretRef allows specifying secret to be used for OCI registry authentication to pull the image with custom Kong Plugin. + The Secret format should follow https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry. + When field is omitted it is assumed that the image is public and can be fetched without providing any credentials. + properties: + name: + description: name is unique within a namespace to reference a + secret resource. + type: string + namespace: + description: namespace defines the space within which the secret + name must be unique. + type: string + type: object + x-kubernetes-map-type: atomic + required: + - image + type: object + status: + description: KongPluginInstallationStatus defines the observed state of + KongPluginInstallation. + properties: + conditions: + description: Conditions describe the current conditions of this KongPluginInstallation. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource.\n---\nThis struct is intended for + direct use as an array at the field path .status.conditions. For + example,\n\n\n\ttype FooStatus struct{\n\t // Represents the + observations of a foo's current state.\n\t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\"\n\t // + +patchMergeKey=type\n\t // +patchStrategy=merge\n\t // +listType=map\n\t + \ // +listMapKey=type\n\t Conditions []metav1.Condition `json:\"conditions,omitempty\" + patchStrategy:\"merge\" patchMergeKey:\"type\" protobuf:\"bytes,1,rep,name=conditions\"`\n\n\n\t + \ // other fields\n\t}" + 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. + --- + Many .condition.type values are consistent across resources like Available, but because arbitrary conditions can be + useful (see .node.status.conditions), the ability to deconflict is important. + The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt) + 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 + type: array + x-kubernetes-list-map-keys: + - type + x-kubernetes-list-type: map + type: object + type: object + served: true + storage: true + subresources: + status: {} diff --git a/docs/api-reference.md b/docs/api-reference.md index de3cc40b5..e89278beb 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -11,6 +11,7 @@ Package v1alpha1 contains API Schema definitions for the operator v1alpha1 API g - [AIGateway](#aigateway) - [DataPlaneMetricsExtension](#dataplanemetricsextension) +- [KongPluginInstallation](#kongplugininstallation) ### AIGateway @@ -80,6 +81,25 @@ the EE version of Kong Gateway Operator with a valid license. +### KongPluginInstallation + + +KongPluginInstallation allows to use a custom Kong Plugin distributed as a container image available in a registry. +Such plugin can be associated with GatewayConfiguration or DataPlane to be available for particular Kong Gateway +and to be configured with KongPlugin CRD. + + + +| Field | Description | +| --- | --- | +| `apiVersion` _string_ | `gateway-operator.konghq.com/v1alpha1` +| `kind` _string_ | `KongPluginInstallation` +| `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` _[KongPluginInstallationSpec](#kongplugininstallationspec)_ | | +| `status` _[KongPluginInstallationStatus](#kongplugininstallationstatus)_ | | + + + ### Types In this section you will find types that the CRDs rely on. @@ -288,6 +308,41 @@ _Appears in:_ - [ControlPlaneOptions](#controlplaneoptions) - [ControlPlaneSpec](#controlplanespec) + + + + +#### KongPluginInstallationSpec + + +KongPluginInstallationSpec defines the desired state of KongPluginInstallation. + + + +| Field | Description | +| --- | --- | +| `image` _string_ | Image is OCI image URL for a packaged Custom Kong Plugin. | +| `secretRef` _[SecretReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretreference-v1-core)_ | SecretRef allows specifying secret to be used for OCI registry authentication to pull the image with custom Kong Plugin. The Secret format should follow https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry. When field is omitted it is assumed that the image is public and can be fetched without providing any credentials. | + + +_Appears in:_ +- [KongPluginInstallation](#kongplugininstallation) + +#### KongPluginInstallationStatus + + +KongPluginInstallationStatus defines the observed state of KongPluginInstallation. + + + +| Field | Description | +| --- | --- | +| `conditions` _[Condition](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#condition-v1-meta) array_ | Conditions describe the current conditions of this KongPluginInstallation. | + + +_Appears in:_ +- [KongPluginInstallation](#kongplugininstallation) + #### LLMPrompt diff --git a/hack/generators/kic/role-generator/main.go b/hack/generators/kic/role-generator/main.go index 6ac77eb7e..1d3615b5e 100644 --- a/hack/generators/kic/role-generator/main.go +++ b/hack/generators/kic/role-generator/main.go @@ -7,11 +7,11 @@ import ( "strings" "github.com/Masterminds/semver" - "github.com/kong/gateway-operator/hack/generators/kic" kongsemver "github.com/kong/semver/v4" rbacv1 "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/util/yaml" + "github.com/kong/gateway-operator/hack/generators/kic" kicversions "github.com/kong/gateway-operator/internal/versions" ) diff --git a/pkg/clientset/typed/apis/v1alpha1/apis_client.go b/pkg/clientset/typed/apis/v1alpha1/apis_client.go index a18f46277..d60120dc2 100644 --- a/pkg/clientset/typed/apis/v1alpha1/apis_client.go +++ b/pkg/clientset/typed/apis/v1alpha1/apis_client.go @@ -30,6 +30,7 @@ type ApisV1alpha1Interface interface { RESTClient() rest.Interface AIGatewaysGetter DataPlaneMetricsExtensionsGetter + KongPluginInstallationsGetter } // ApisV1alpha1Client is used to interact with features provided by the apis group. @@ -45,6 +46,10 @@ func (c *ApisV1alpha1Client) DataPlaneMetricsExtensions(namespace string) DataPl return newDataPlaneMetricsExtensions(c, namespace) } +func (c *ApisV1alpha1Client) KongPluginInstallations(namespace string) KongPluginInstallationInterface { + return newKongPluginInstallations(c, namespace) +} + // NewForConfig creates a new ApisV1alpha1Client for the given config. // NewForConfig is equivalent to NewForConfigAndClient(c, httpClient), // where httpClient was generated with rest.HTTPClientFor(c). diff --git a/pkg/clientset/typed/apis/v1alpha1/fake/fake_apis_client.go b/pkg/clientset/typed/apis/v1alpha1/fake/fake_apis_client.go index 76c878a36..2ce93e15a 100644 --- a/pkg/clientset/typed/apis/v1alpha1/fake/fake_apis_client.go +++ b/pkg/clientset/typed/apis/v1alpha1/fake/fake_apis_client.go @@ -36,6 +36,10 @@ func (c *FakeApisV1alpha1) DataPlaneMetricsExtensions(namespace string) v1alpha1 return &FakeDataPlaneMetricsExtensions{c, namespace} } +func (c *FakeApisV1alpha1) KongPluginInstallations(namespace string) v1alpha1.KongPluginInstallationInterface { + return &FakeKongPluginInstallations{c, namespace} +} + // RESTClient returns a RESTClient that is used to communicate // with API server by this client implementation. func (c *FakeApisV1alpha1) RESTClient() rest.Interface { diff --git a/pkg/clientset/typed/apis/v1alpha1/fake/fake_kongplugininstallation.go b/pkg/clientset/typed/apis/v1alpha1/fake/fake_kongplugininstallation.go new file mode 100644 index 000000000..928044558 --- /dev/null +++ b/pkg/clientset/typed/apis/v1alpha1/fake/fake_kongplugininstallation.go @@ -0,0 +1,141 @@ +/* +Copyright 2022 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/gateway-operator/api/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" +) + +// FakeKongPluginInstallations implements KongPluginInstallationInterface +type FakeKongPluginInstallations struct { + Fake *FakeApisV1alpha1 + ns string +} + +var kongplugininstallationsResource = v1alpha1.SchemeGroupVersion.WithResource("kongplugininstallations") + +var kongplugininstallationsKind = v1alpha1.SchemeGroupVersion.WithKind("KongPluginInstallation") + +// Get takes name of the kongPluginInstallation, and returns the corresponding kongPluginInstallation object, and an error if there is any. +func (c *FakeKongPluginInstallations) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.KongPluginInstallation, err error) { + obj, err := c.Fake. + Invokes(testing.NewGetAction(kongplugininstallationsResource, c.ns, name), &v1alpha1.KongPluginInstallation{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.KongPluginInstallation), err +} + +// List takes label and field selectors, and returns the list of KongPluginInstallations that match those selectors. +func (c *FakeKongPluginInstallations) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.KongPluginInstallationList, err error) { + obj, err := c.Fake. + Invokes(testing.NewListAction(kongplugininstallationsResource, kongplugininstallationsKind, c.ns, opts), &v1alpha1.KongPluginInstallationList{}) + + if obj == nil { + return nil, err + } + + label, _, _ := testing.ExtractFromListOptions(opts) + if label == nil { + label = labels.Everything() + } + list := &v1alpha1.KongPluginInstallationList{ListMeta: obj.(*v1alpha1.KongPluginInstallationList).ListMeta} + for _, item := range obj.(*v1alpha1.KongPluginInstallationList).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 kongPluginInstallations. +func (c *FakeKongPluginInstallations) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + return c.Fake. + InvokesWatch(testing.NewWatchAction(kongplugininstallationsResource, c.ns, opts)) + +} + +// Create takes the representation of a kongPluginInstallation and creates it. Returns the server's representation of the kongPluginInstallation, and an error, if there is any. +func (c *FakeKongPluginInstallations) Create(ctx context.Context, kongPluginInstallation *v1alpha1.KongPluginInstallation, opts v1.CreateOptions) (result *v1alpha1.KongPluginInstallation, err error) { + obj, err := c.Fake. + Invokes(testing.NewCreateAction(kongplugininstallationsResource, c.ns, kongPluginInstallation), &v1alpha1.KongPluginInstallation{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.KongPluginInstallation), err +} + +// Update takes the representation of a kongPluginInstallation and updates it. Returns the server's representation of the kongPluginInstallation, and an error, if there is any. +func (c *FakeKongPluginInstallations) Update(ctx context.Context, kongPluginInstallation *v1alpha1.KongPluginInstallation, opts v1.UpdateOptions) (result *v1alpha1.KongPluginInstallation, err error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateAction(kongplugininstallationsResource, c.ns, kongPluginInstallation), &v1alpha1.KongPluginInstallation{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.KongPluginInstallation), 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 *FakeKongPluginInstallations) UpdateStatus(ctx context.Context, kongPluginInstallation *v1alpha1.KongPluginInstallation, opts v1.UpdateOptions) (*v1alpha1.KongPluginInstallation, error) { + obj, err := c.Fake. + Invokes(testing.NewUpdateSubresourceAction(kongplugininstallationsResource, "status", c.ns, kongPluginInstallation), &v1alpha1.KongPluginInstallation{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.KongPluginInstallation), err +} + +// Delete takes name of the kongPluginInstallation and deletes it. Returns an error if one occurs. +func (c *FakeKongPluginInstallations) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + _, err := c.Fake. + Invokes(testing.NewDeleteActionWithOptions(kongplugininstallationsResource, c.ns, name, opts), &v1alpha1.KongPluginInstallation{}) + + return err +} + +// DeleteCollection deletes a collection of objects. +func (c *FakeKongPluginInstallations) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + action := testing.NewDeleteCollectionAction(kongplugininstallationsResource, c.ns, listOpts) + + _, err := c.Fake.Invokes(action, &v1alpha1.KongPluginInstallationList{}) + return err +} + +// Patch applies the patch and returns the patched kongPluginInstallation. +func (c *FakeKongPluginInstallations) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.KongPluginInstallation, err error) { + obj, err := c.Fake. + Invokes(testing.NewPatchSubresourceAction(kongplugininstallationsResource, c.ns, name, pt, data, subresources...), &v1alpha1.KongPluginInstallation{}) + + if obj == nil { + return nil, err + } + return obj.(*v1alpha1.KongPluginInstallation), err +} diff --git a/pkg/clientset/typed/apis/v1alpha1/generated_expansion.go b/pkg/clientset/typed/apis/v1alpha1/generated_expansion.go index 34886cc34..c74037b5d 100644 --- a/pkg/clientset/typed/apis/v1alpha1/generated_expansion.go +++ b/pkg/clientset/typed/apis/v1alpha1/generated_expansion.go @@ -21,3 +21,5 @@ package v1alpha1 type AIGatewayExpansion interface{} type DataPlaneMetricsExtensionExpansion interface{} + +type KongPluginInstallationExpansion interface{} diff --git a/pkg/clientset/typed/apis/v1alpha1/kongplugininstallation.go b/pkg/clientset/typed/apis/v1alpha1/kongplugininstallation.go new file mode 100644 index 000000000..ac4160422 --- /dev/null +++ b/pkg/clientset/typed/apis/v1alpha1/kongplugininstallation.go @@ -0,0 +1,195 @@ +/* +Copyright 2022 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" + "time" + + v1alpha1 "github.com/kong/gateway-operator/api/v1alpha1" + scheme "github.com/kong/gateway-operator/pkg/clientset/scheme" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + types "k8s.io/apimachinery/pkg/types" + watch "k8s.io/apimachinery/pkg/watch" + rest "k8s.io/client-go/rest" +) + +// KongPluginInstallationsGetter has a method to return a KongPluginInstallationInterface. +// A group's client should implement this interface. +type KongPluginInstallationsGetter interface { + KongPluginInstallations(namespace string) KongPluginInstallationInterface +} + +// KongPluginInstallationInterface has methods to work with KongPluginInstallation resources. +type KongPluginInstallationInterface interface { + Create(ctx context.Context, kongPluginInstallation *v1alpha1.KongPluginInstallation, opts v1.CreateOptions) (*v1alpha1.KongPluginInstallation, error) + Update(ctx context.Context, kongPluginInstallation *v1alpha1.KongPluginInstallation, opts v1.UpdateOptions) (*v1alpha1.KongPluginInstallation, error) + UpdateStatus(ctx context.Context, kongPluginInstallation *v1alpha1.KongPluginInstallation, opts v1.UpdateOptions) (*v1alpha1.KongPluginInstallation, 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.KongPluginInstallation, error) + List(ctx context.Context, opts v1.ListOptions) (*v1alpha1.KongPluginInstallationList, 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.KongPluginInstallation, err error) + KongPluginInstallationExpansion +} + +// kongPluginInstallations implements KongPluginInstallationInterface +type kongPluginInstallations struct { + client rest.Interface + ns string +} + +// newKongPluginInstallations returns a KongPluginInstallations +func newKongPluginInstallations(c *ApisV1alpha1Client, namespace string) *kongPluginInstallations { + return &kongPluginInstallations{ + client: c.RESTClient(), + ns: namespace, + } +} + +// Get takes name of the kongPluginInstallation, and returns the corresponding kongPluginInstallation object, and an error if there is any. +func (c *kongPluginInstallations) Get(ctx context.Context, name string, options v1.GetOptions) (result *v1alpha1.KongPluginInstallation, err error) { + result = &v1alpha1.KongPluginInstallation{} + err = c.client.Get(). + Namespace(c.ns). + Resource("kongplugininstallations"). + Name(name). + VersionedParams(&options, scheme.ParameterCodec). + Do(ctx). + Into(result) + return +} + +// List takes label and field selectors, and returns the list of KongPluginInstallations that match those selectors. +func (c *kongPluginInstallations) List(ctx context.Context, opts v1.ListOptions) (result *v1alpha1.KongPluginInstallationList, err error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + result = &v1alpha1.KongPluginInstallationList{} + err = c.client.Get(). + Namespace(c.ns). + Resource("kongplugininstallations"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Do(ctx). + Into(result) + return +} + +// Watch returns a watch.Interface that watches the requested kongPluginInstallations. +func (c *kongPluginInstallations) Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error) { + var timeout time.Duration + if opts.TimeoutSeconds != nil { + timeout = time.Duration(*opts.TimeoutSeconds) * time.Second + } + opts.Watch = true + return c.client.Get(). + Namespace(c.ns). + Resource("kongplugininstallations"). + VersionedParams(&opts, scheme.ParameterCodec). + Timeout(timeout). + Watch(ctx) +} + +// Create takes the representation of a kongPluginInstallation and creates it. Returns the server's representation of the kongPluginInstallation, and an error, if there is any. +func (c *kongPluginInstallations) Create(ctx context.Context, kongPluginInstallation *v1alpha1.KongPluginInstallation, opts v1.CreateOptions) (result *v1alpha1.KongPluginInstallation, err error) { + result = &v1alpha1.KongPluginInstallation{} + err = c.client.Post(). + Namespace(c.ns). + Resource("kongplugininstallations"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(kongPluginInstallation). + Do(ctx). + Into(result) + return +} + +// Update takes the representation of a kongPluginInstallation and updates it. Returns the server's representation of the kongPluginInstallation, and an error, if there is any. +func (c *kongPluginInstallations) Update(ctx context.Context, kongPluginInstallation *v1alpha1.KongPluginInstallation, opts v1.UpdateOptions) (result *v1alpha1.KongPluginInstallation, err error) { + result = &v1alpha1.KongPluginInstallation{} + err = c.client.Put(). + Namespace(c.ns). + Resource("kongplugininstallations"). + Name(kongPluginInstallation.Name). + VersionedParams(&opts, scheme.ParameterCodec). + Body(kongPluginInstallation). + Do(ctx). + Into(result) + return +} + +// UpdateStatus was generated because the type contains a Status member. +// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus(). +func (c *kongPluginInstallations) UpdateStatus(ctx context.Context, kongPluginInstallation *v1alpha1.KongPluginInstallation, opts v1.UpdateOptions) (result *v1alpha1.KongPluginInstallation, err error) { + result = &v1alpha1.KongPluginInstallation{} + err = c.client.Put(). + Namespace(c.ns). + Resource("kongplugininstallations"). + Name(kongPluginInstallation.Name). + SubResource("status"). + VersionedParams(&opts, scheme.ParameterCodec). + Body(kongPluginInstallation). + Do(ctx). + Into(result) + return +} + +// Delete takes name of the kongPluginInstallation and deletes it. Returns an error if one occurs. +func (c *kongPluginInstallations) Delete(ctx context.Context, name string, opts v1.DeleteOptions) error { + return c.client.Delete(). + Namespace(c.ns). + Resource("kongplugininstallations"). + Name(name). + Body(&opts). + Do(ctx). + Error() +} + +// DeleteCollection deletes a collection of objects. +func (c *kongPluginInstallations) DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error { + var timeout time.Duration + if listOpts.TimeoutSeconds != nil { + timeout = time.Duration(*listOpts.TimeoutSeconds) * time.Second + } + return c.client.Delete(). + Namespace(c.ns). + Resource("kongplugininstallations"). + VersionedParams(&listOpts, scheme.ParameterCodec). + Timeout(timeout). + Body(&opts). + Do(ctx). + Error() +} + +// Patch applies the patch and returns the patched kongPluginInstallation. +func (c *kongPluginInstallations) Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *v1alpha1.KongPluginInstallation, err error) { + result = &v1alpha1.KongPluginInstallation{} + err = c.client.Patch(pt). + Namespace(c.ns). + Resource("kongplugininstallations"). + Name(name). + SubResource(subresources...). + VersionedParams(&opts, scheme.ParameterCodec). + Body(data). + Do(ctx). + Into(result) + return +} From 5f732c0ec14cb2ef70357358d891dbf754d0355d Mon Sep 17 00:00:00 2001 From: Jakub Warczarek Date: Tue, 9 Jul 2024 17:27:11 +0200 Subject: [PATCH 3/9] Apply suggestions from code review MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patryk Małek --- api/v1alpha1/kongplugin_installation.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/v1alpha1/kongplugin_installation.go b/api/v1alpha1/kongplugin_installation.go index 812657c1a..3c4d6a5df 100644 --- a/api/v1alpha1/kongplugin_installation.go +++ b/api/v1alpha1/kongplugin_installation.go @@ -89,8 +89,8 @@ type KongPluginInstallationConditionType string type KongPluginInstallationConditionReason string const ( - // This condition indicates whether the controller has fetched and make - // available for use a specific Custom Kong Plugin. + // This condition indicates whether the controller has fetched the plugin image + // and made it available for use as a specific Custom Kong Plugin. // // It is a positive-polarity summary condition, and so should always be // present on the resource with ObservedGeneration set. @@ -99,7 +99,7 @@ const ( // status before it has all the information it needs to be able to determine // if the condition is true. // - // Possible reasons for this condition to be true are: + // Possible reasons for this condition to be True are: // // * "Programmed" // From 6353a0e1e78cee9f3b0d066dba9b719c82b8e345 Mon Sep 17 00:00:00 2001 From: Jakub Warczarek Date: Tue, 9 Jul 2024 17:54:34 +0200 Subject: [PATCH 4/9] CR suggestions --- ...on.go => kongplugin_installation_types.go} | 52 +++++++++---------- ...or.konghq.com_kongplugininstallations.yaml | 17 +++--- docs/api-reference.md | 10 ++-- 3 files changed, 40 insertions(+), 39 deletions(-) rename api/v1alpha1/{kongplugin_installation.go => kongplugin_installation_types.go} (65%) diff --git a/api/v1alpha1/kongplugin_installation.go b/api/v1alpha1/kongplugin_installation_types.go similarity index 65% rename from api/v1alpha1/kongplugin_installation.go rename to api/v1alpha1/kongplugin_installation_types.go index 3c4d6a5df..3ca16f8a5 100644 --- a/api/v1alpha1/kongplugin_installation.go +++ b/api/v1alpha1/kongplugin_installation_types.go @@ -31,11 +31,11 @@ func init() { //+kubebuilder:subresource:status //+kubebuilder:resource:shortName=kpi,categories=kong;all //+kubebuilder:subresource:status -//+kubebuilder:printcolumn:name="Programmed",type=string,JSONPath=`.status.conditions[?(@.type=="Programmed")].status` +//+kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].status` -// KongPluginInstallation allows to use a custom Kong Plugin distributed as a container image available in a registry. -// Such plugin can be associated with GatewayConfiguration or DataPlane to be available for particular Kong Gateway -// and to be configured with KongPlugin CRD. +// KongPluginInstallation allows using a custom Kong Plugin distributed as a container image available in a registry. +// Such a plugin can be associated with GatewayConfiguration or DataPlane to be available for particular Kong Gateway +// and configured with KongPlugin CRD. type KongPluginInstallation struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -56,14 +56,14 @@ type KongPluginInstallationList struct { // KongPluginInstallationSpec defines the desired state of KongPluginInstallation. type KongPluginInstallationSpec struct { - // Image is OCI image URL for a packaged Custom Kong Plugin. + // The image is an OCI image URL for a packaged Custom Kong Plugin. // //+kubebuilder:validation:Required Image string `json:"image"` - // SecretRef allows specifying secret to be used for OCI registry authentication to pull the image with custom Kong Plugin. + // SecretRef allows referring specific Kubernetes Secret to use for OCI registry authentication for pulling an image with Custom Kong Plugin. // The Secret format should follow https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry. - // When field is omitted it is assumed that the image is public and can be fetched without providing any credentials. + // When the field is omitted it is assumed that the image is public and can be fetched without providing credentials. // //+optional SecretRef *corev1.SecretReference `json:"secretRef,omitempty"` @@ -90,7 +90,7 @@ type KongPluginInstallationConditionReason string const ( // This condition indicates whether the controller has fetched the plugin image - // and made it available for use as a specific Custom Kong Plugin. + // and made it available for use as a specific Custom Kong Plugin. // // It is a positive-polarity summary condition, and so should always be // present on the resource with ObservedGeneration set. @@ -99,31 +99,31 @@ const ( // status before it has all the information it needs to be able to determine // if the condition is true. // - // Possible reasons for this condition to be True are: + // Possible reasons for this condition to be "True" are: // - // * "Programmed" + // * "Ready" // - // Possible reasons for this condition to be False are: + // Possible reasons for this condition to be "False" are: // - // * "Invalid" - // * "Fetching" + // * "Failed" + // * "Pending" // - // Possible reasons for this condition to be Unknown are: + // Possible reasons for this condition to be "Unknown" are: // - // * "Fetching". + // * "Pending". // + KongPluginInstallationConditionStatusAccepted KongPluginInstallationConditionType = "Ready" - // Controllers should prefer to use the values of KongPluginInstallationConditionReason - // for the corresponding Reason, where appropriate. - KongPluginInstallationConditionStatusAccepted KongPluginInstallationConditionType = "Accepted" + // KongPluginInstallationReasonReady is used with the "Ready" condition when + // the condition is "True". + KongPluginInstallationReasonReady KongPluginInstallationConditionReason = "Ready" - // This reason is used with the "Accepted" condition when the KongPluginInstallation - // was not accepted because image can't be fetched, more details can be obtained from the - // condition's message. - KongPluginInstallationReasonInvalidParameters KongPluginInstallationConditionReason = "Invalid" + // KongPluginInstallationReasonFailed is used with the "Ready" condition when + // the KongPluginInstallation can't be configured e.g. image can't be fetched. + // More details can be obtained from the condition's message. + KongPluginInstallationReasonFailed KongPluginInstallationConditionReason = "Failed" - // This reason is used with the "Accepted" condition when the - // requested controller has started processing the KongPluginInstallation, - // but it haven't yet finished. - KongPluginInstallationReasonPending KongPluginInstallationConditionReason = "Fetching" + // KongPluginInstallationReasonPending is used with the "Ready" condition when the requested + // controller has started processing the KongPluginInstallation, but it hasn't finished yet. + KongPluginInstallationReasonPending KongPluginInstallationConditionReason = "Pending" ) diff --git a/config/crd/bases/gateway-operator.konghq.com_kongplugininstallations.yaml b/config/crd/bases/gateway-operator.konghq.com_kongplugininstallations.yaml index 058dad253..15c0868e3 100644 --- a/config/crd/bases/gateway-operator.konghq.com_kongplugininstallations.yaml +++ b/config/crd/bases/gateway-operator.konghq.com_kongplugininstallations.yaml @@ -20,16 +20,16 @@ spec: scope: Namespaced versions: - additionalPrinterColumns: - - jsonPath: .status.conditions[?(@.type=="Programmed")].status - name: Programmed + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready type: string name: v1alpha1 schema: openAPIV3Schema: description: |- - KongPluginInstallation allows to use a custom Kong Plugin distributed as a container image available in a registry. - Such plugin can be associated with GatewayConfiguration or DataPlane to be available for particular Kong Gateway - and to be configured with KongPlugin CRD. + KongPluginInstallation allows using a custom Kong Plugin distributed as a container image available in a registry. + Such a plugin can be associated with GatewayConfiguration or DataPlane to be available for particular Kong Gateway + and configured with KongPlugin CRD. properties: apiVersion: description: |- @@ -52,13 +52,14 @@ spec: description: KongPluginInstallationSpec defines the desired state of KongPluginInstallation. properties: image: - description: Image is OCI image URL for a packaged Custom Kong Plugin. + description: The image is an OCI image URL for a packaged Custom Kong + Plugin. type: string secretRef: description: |- - SecretRef allows specifying secret to be used for OCI registry authentication to pull the image with custom Kong Plugin. + SecretRef allows referring specific Kubernetes Secret to use for OCI registry authentication for pulling an image with Custom Kong Plugin. The Secret format should follow https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry. - When field is omitted it is assumed that the image is public and can be fetched without providing any credentials. + When the field is omitted it is assumed that the image is public and can be fetched without providing credentials. properties: name: description: name is unique within a namespace to reference a diff --git a/docs/api-reference.md b/docs/api-reference.md index e89278beb..1258bcbd5 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -84,9 +84,9 @@ the EE version of Kong Gateway Operator with a valid license. ### KongPluginInstallation -KongPluginInstallation allows to use a custom Kong Plugin distributed as a container image available in a registry. -Such plugin can be associated with GatewayConfiguration or DataPlane to be available for particular Kong Gateway -and to be configured with KongPlugin CRD. +KongPluginInstallation allows using a custom Kong Plugin distributed as a container image available in a registry. +Such a plugin can be associated with GatewayConfiguration or DataPlane to be available for particular Kong Gateway +and configured with KongPlugin CRD. @@ -321,8 +321,8 @@ KongPluginInstallationSpec defines the desired state of KongPluginInstallation. | Field | Description | | --- | --- | -| `image` _string_ | Image is OCI image URL for a packaged Custom Kong Plugin. | -| `secretRef` _[SecretReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretreference-v1-core)_ | SecretRef allows specifying secret to be used for OCI registry authentication to pull the image with custom Kong Plugin. The Secret format should follow https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry. When field is omitted it is assumed that the image is public and can be fetched without providing any credentials. | +| `image` _string_ | The image is an OCI image URL for a packaged Custom Kong Plugin. | +| `secretRef` _[SecretReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretreference-v1-core)_ | SecretRef allows referring specific Kubernetes Secret to use for OCI registry authentication for pulling an image with Custom Kong Plugin. The Secret format should follow https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry. When the field is omitted it is assumed that the image is public and can be fetched without providing credentials. | _Appears in:_ From d6434e5d63e918d7900b0db59f88bedeea8ff681 Mon Sep 17 00:00:00 2001 From: Jakub Warczarek Date: Wed, 10 Jul 2024 10:45:58 +0200 Subject: [PATCH 5/9] Apply suggestions from code review Co-authored-by: Travis Raines <571832+rainest@users.noreply.github.com> --- api/v1alpha1/kongplugin_installation_types.go | 21 ++++++++++--------- ...or.konghq.com_kongplugininstallations.yaml | 13 ++++++------ docs/api-reference.md | 6 +++--- 3 files changed, 21 insertions(+), 19 deletions(-) diff --git a/api/v1alpha1/kongplugin_installation_types.go b/api/v1alpha1/kongplugin_installation_types.go index 3ca16f8a5..cd792fd1b 100644 --- a/api/v1alpha1/kongplugin_installation_types.go +++ b/api/v1alpha1/kongplugin_installation_types.go @@ -53,17 +53,17 @@ type KongPluginInstallationList struct { Items []KongPluginInstallation `json:"items"` } -// KongPluginInstallationSpec defines the desired state of KongPluginInstallation. +// KongPluginInstallationSpec provides the information necessary to retrieve and install a Kong custom plugin. type KongPluginInstallationSpec struct { - // The image is an OCI image URL for a packaged Custom Kong Plugin. + // The image is an OCI image URL for a packaged custom Kong plugin. // //+kubebuilder:validation:Required Image string `json:"image"` - // SecretRef allows referring specific Kubernetes Secret to use for OCI registry authentication for pulling an image with Custom Kong Plugin. - // The Secret format should follow https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry. - // When the field is omitted it is assumed that the image is public and can be fetched without providing credentials. + // SecretRef is a reference to a Kubernetes Secret containing credentials necessary to pull the OCI image + // in Image. It must follow the format in https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry. + // It is optional. If the image is public, omit this field. // //+optional SecretRef *corev1.SecretReference `json:"secretRef,omitempty"` @@ -79,13 +79,14 @@ type KongPluginInstallationStatus struct { Conditions []metav1.Condition `json:"conditions,omitempty"` } -// KongPluginInstallationConditionType is the type for status conditions on -// KongPluginInstallation resources. This type should be used with the -// KongPluginInstallationStatus.Conditions field. +// The following are KongPluginInstallation specific types for +// https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.30/#condition-v1-meta fields + +// KongPluginInstallationConditionType is the type for Conditions in a KongPluginInstallation's +// Status.Conditions array. type KongPluginInstallationConditionType string -// KongPluginInstallationConditionReason defines the set of reasons that explain why -// a particular KongPluginInstallation condition type has been raised. +// KongPluginInstallationConditionReason is a reason for the KongPluginInstallation condition's last transition. type KongPluginInstallationConditionReason string const ( diff --git a/config/crd/bases/gateway-operator.konghq.com_kongplugininstallations.yaml b/config/crd/bases/gateway-operator.konghq.com_kongplugininstallations.yaml index 15c0868e3..211286417 100644 --- a/config/crd/bases/gateway-operator.konghq.com_kongplugininstallations.yaml +++ b/config/crd/bases/gateway-operator.konghq.com_kongplugininstallations.yaml @@ -49,17 +49,18 @@ spec: metadata: type: object spec: - description: KongPluginInstallationSpec defines the desired state of KongPluginInstallation. + description: KongPluginInstallationSpec provides the information necessary + to retrieve and install a Kong custom plugin. properties: image: - description: The image is an OCI image URL for a packaged Custom Kong - Plugin. + description: The image is an OCI image URL for a packaged custom Kong + plugin. type: string secretRef: description: |- - SecretRef allows referring specific Kubernetes Secret to use for OCI registry authentication for pulling an image with Custom Kong Plugin. - The Secret format should follow https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry. - When the field is omitted it is assumed that the image is public and can be fetched without providing credentials. + SecretRef is a reference to a Kubernetes Secret containing credentials necessary to pull the OCI image + in Image. It must follow the format in https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry. + It is optional. If the image is public, omit this field. properties: name: description: name is unique within a namespace to reference a diff --git a/docs/api-reference.md b/docs/api-reference.md index 1258bcbd5..099e743c1 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -315,14 +315,14 @@ _Appears in:_ #### KongPluginInstallationSpec -KongPluginInstallationSpec defines the desired state of KongPluginInstallation. +KongPluginInstallationSpec provides the information necessary to retrieve and install a Kong custom plugin. | Field | Description | | --- | --- | -| `image` _string_ | The image is an OCI image URL for a packaged Custom Kong Plugin. | -| `secretRef` _[SecretReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretreference-v1-core)_ | SecretRef allows referring specific Kubernetes Secret to use for OCI registry authentication for pulling an image with Custom Kong Plugin. The Secret format should follow https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry. When the field is omitted it is assumed that the image is public and can be fetched without providing credentials. | +| `image` _string_ | The image is an OCI image URL for a packaged custom Kong plugin. | +| `secretRef` _[SecretReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretreference-v1-core)_ | SecretRef is a reference to a Kubernetes Secret containing credentials necessary to pull the OCI image in Image. It must follow the format in https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry. It is optional. If the image is public, omit this field. | _Appears in:_ From eb24bd6070110a61281bd85a45bdc39f2a63017b Mon Sep 17 00:00:00 2001 From: Jakub Warczarek Date: Tue, 16 Jul 2024 19:17:47 +0200 Subject: [PATCH 6/9] CR fixes --- api/v1alpha1/kongplugin_installation_types.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/v1alpha1/kongplugin_installation_types.go b/api/v1alpha1/kongplugin_installation_types.go index cd792fd1b..3a02d1ce0 100644 --- a/api/v1alpha1/kongplugin_installation_types.go +++ b/api/v1alpha1/kongplugin_installation_types.go @@ -113,14 +113,14 @@ const ( // // * "Pending". // - KongPluginInstallationConditionStatusAccepted KongPluginInstallationConditionType = "Ready" + KongPluginInstallationConditionStatusAccepted KongPluginInstallationConditionType = "Accepted" - // KongPluginInstallationReasonReady is used with the "Ready" condition when - // the condition is "True". + // KongPluginInstallationReasonReady indicates that the controller has downloaded the plugin + // and can install it on a DataPlane or Gateway. KongPluginInstallationReasonReady KongPluginInstallationConditionReason = "Ready" // KongPluginInstallationReasonFailed is used with the "Ready" condition when - // the KongPluginInstallation can't be configured e.g. image can't be fetched. + // the KongPluginInstallation can't be fetched e.g. image can't be fetched. // More details can be obtained from the condition's message. KongPluginInstallationReasonFailed KongPluginInstallationConditionReason = "Failed" From 7222951bcecba59e8ca23e6061420209b20f2fdd Mon Sep 17 00:00:00 2001 From: Jakub Warczarek Date: Tue, 16 Jul 2024 19:18:10 +0200 Subject: [PATCH 7/9] Apply suggestions from code review Co-authored-by: Travis Raines <571832+rainest@users.noreply.github.com> --- api/v1alpha1/kongplugin_installation_types.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/v1alpha1/kongplugin_installation_types.go b/api/v1alpha1/kongplugin_installation_types.go index 3a02d1ce0..50d0282c8 100644 --- a/api/v1alpha1/kongplugin_installation_types.go +++ b/api/v1alpha1/kongplugin_installation_types.go @@ -119,12 +119,12 @@ const ( // and can install it on a DataPlane or Gateway. KongPluginInstallationReasonReady KongPluginInstallationConditionReason = "Ready" - // KongPluginInstallationReasonFailed is used with the "Ready" condition when + // KongPluginInstallationReasonFailed is used with the "Accepted" condition type when // the KongPluginInstallation can't be fetched e.g. image can't be fetched. // More details can be obtained from the condition's message. KongPluginInstallationReasonFailed KongPluginInstallationConditionReason = "Failed" - // KongPluginInstallationReasonPending is used with the "Ready" condition when the requested + // KongPluginInstallationReasonPending is used with the "Accepted" condition type when the requested // controller has started processing the KongPluginInstallation, but it hasn't finished yet. KongPluginInstallationReasonPending KongPluginInstallationConditionReason = "Pending" ) From cddbd33f63f7f49e26209877046ce96a8b20e485 Mon Sep 17 00:00:00 2001 From: Jakub Warczarek Date: Tue, 16 Jul 2024 19:27:20 +0200 Subject: [PATCH 8/9] Be more descriptive --- CHANGELOG.md | 3 ++- api/v1alpha1/kongplugin_installation_types.go | 17 ++++++++++------- api/v1alpha1/zz_generated.deepcopy.go | 4 ++-- ...ator.konghq.com_kongplugininstallations.yaml | 4 ++-- docs/api-reference.md | 2 +- 5 files changed, 17 insertions(+), 13 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e3cbb1b77..a6e28415d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -29,7 +29,8 @@ - Proper `User-Agent` header is now set on outgoing HTTP requests. [#387](https://github.com/Kong/gateway-operator/pull/387) -- Introduce `KongPluginInstallation` CRD +- Introduce `KongPluginInstallation` CRD to allow installing custom Kong + plugins distributed as container images. [400](https://github.com/Kong/gateway-operator/pull/400) ### Fixed diff --git a/api/v1alpha1/kongplugin_installation_types.go b/api/v1alpha1/kongplugin_installation_types.go index 50d0282c8..5f2350b1f 100644 --- a/api/v1alpha1/kongplugin_installation_types.go +++ b/api/v1alpha1/kongplugin_installation_types.go @@ -61,12 +61,12 @@ type KongPluginInstallationSpec struct { //+kubebuilder:validation:Required Image string `json:"image"` - // SecretRef is a reference to a Kubernetes Secret containing credentials necessary to pull the OCI image + // ImagePullSecretRef is a reference to a Kubernetes Secret containing credentials necessary to pull the OCI image // in Image. It must follow the format in https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry. // It is optional. If the image is public, omit this field. // //+optional - SecretRef *corev1.SecretReference `json:"secretRef,omitempty"` + ImagePullSecretRef *corev1.SecretReference `json:"imagePullSecretRef,omitempty"` } // KongPluginInstallationStatus defines the observed state of KongPluginInstallation. @@ -91,14 +91,14 @@ type KongPluginInstallationConditionReason string const ( // This condition indicates whether the controller has fetched the plugin image - // and made it available for use as a specific Custom Kong Plugin. + // and made it available for use as a specific custom Kong Plugin. // // It is a positive-polarity summary condition, and so should always be // present on the resource with ObservedGeneration set. // // It should be set to Unknown if the controller performs updates to the // status before it has all the information it needs to be able to determine - // if the condition is true. + // if the condition is true (e.g. haven't started the download yet). // // Possible reasons for this condition to be "True" are: // @@ -106,8 +106,8 @@ const ( // // Possible reasons for this condition to be "False" are: // - // * "Failed" // * "Pending" + // * "Failed" // // Possible reasons for this condition to be "Unknown" are: // @@ -120,11 +120,14 @@ const ( KongPluginInstallationReasonReady KongPluginInstallationConditionReason = "Ready" // KongPluginInstallationReasonFailed is used with the "Accepted" condition type when - // the KongPluginInstallation can't be fetched e.g. image can't be fetched. + // the KongPluginInstallation can't be fetched e.g. image can't be fetched due to lack + // of permissions or the image doesn't exist. It's a state that can't be recovered without + // manual intervention. // More details can be obtained from the condition's message. KongPluginInstallationReasonFailed KongPluginInstallationConditionReason = "Failed" // KongPluginInstallationReasonPending is used with the "Accepted" condition type when the requested - // controller has started processing the KongPluginInstallation, but it hasn't finished yet. + // controller has started processing the KongPluginInstallation, but it hasn't finished yet, e.g. + // fetching and unpacking the image is in progress. KongPluginInstallationReasonPending KongPluginInstallationConditionReason = "Pending" ) diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 64af57dd4..5e55ed208 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -434,8 +434,8 @@ func (in *KongPluginInstallationList) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *KongPluginInstallationSpec) DeepCopyInto(out *KongPluginInstallationSpec) { *out = *in - if in.SecretRef != nil { - in, out := &in.SecretRef, &out.SecretRef + if in.ImagePullSecretRef != nil { + in, out := &in.ImagePullSecretRef, &out.ImagePullSecretRef *out = new(corev1.SecretReference) **out = **in } diff --git a/config/crd/bases/gateway-operator.konghq.com_kongplugininstallations.yaml b/config/crd/bases/gateway-operator.konghq.com_kongplugininstallations.yaml index 211286417..1a97639e9 100644 --- a/config/crd/bases/gateway-operator.konghq.com_kongplugininstallations.yaml +++ b/config/crd/bases/gateway-operator.konghq.com_kongplugininstallations.yaml @@ -56,9 +56,9 @@ spec: description: The image is an OCI image URL for a packaged custom Kong plugin. type: string - secretRef: + imagePullSecretRef: description: |- - SecretRef is a reference to a Kubernetes Secret containing credentials necessary to pull the OCI image + ImagePullSecretRef is a reference to a Kubernetes Secret containing credentials necessary to pull the OCI image in Image. It must follow the format in https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry. It is optional. If the image is public, omit this field. properties: diff --git a/docs/api-reference.md b/docs/api-reference.md index 099e743c1..4bb962464 100644 --- a/docs/api-reference.md +++ b/docs/api-reference.md @@ -322,7 +322,7 @@ KongPluginInstallationSpec provides the information necessary to retrieve and in | Field | Description | | --- | --- | | `image` _string_ | The image is an OCI image URL for a packaged custom Kong plugin. | -| `secretRef` _[SecretReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretreference-v1-core)_ | SecretRef is a reference to a Kubernetes Secret containing credentials necessary to pull the OCI image in Image. It must follow the format in https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry. It is optional. If the image is public, omit this field. | +| `imagePullSecretRef` _[SecretReference](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.28/#secretreference-v1-core)_ | ImagePullSecretRef is a reference to a Kubernetes Secret containing credentials necessary to pull the OCI image in Image. It must follow the format in https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry. It is optional. If the image is public, omit this field. | _Appears in:_ From 974e3230d594b355b366842812d947a4a44c6f9f Mon Sep 17 00:00:00 2001 From: Jakub Warczarek Date: Fri, 19 Jul 2024 17:01:11 +0200 Subject: [PATCH 9/9] Update --- go.mod | 6 +++--- go.sum | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index 9de1f6e3b..8c9cde791 100644 --- a/go.mod +++ b/go.mod @@ -200,7 +200,7 @@ require ( replace ( k8s.io/api => k8s.io/api v0.30.2 k8s.io/apiextensions-apiserver => k8s.io/apiextensions-apiserver v0.30.2 - k8s.io/apimachinery => k8s.io/apimachinery v0.30.2 + k8s.io/apimachinery => k8s.io/apimachinery v0.30.3 k8s.io/apiserver => k8s.io/apiserver v0.30.2 k8s.io/cli-runtime => k8s.io/cli-runtime v0.30.2 k8s.io/client-go => k8s.io/client-go v0.30.2 @@ -210,7 +210,7 @@ replace ( k8s.io/component-base => k8s.io/component-base v0.30.2 k8s.io/component-helpers => k8s.io/component-helpers v0.30.2 k8s.io/controller-manager => k8s.io/controller-manager v0.30.2 - k8s.io/cri-api => k8s.io/cri-api v0.30.2 + k8s.io/cri-api => k8s.io/cri-api v0.30.3 k8s.io/csi-translation-lib => k8s.io/csi-translation-lib v0.30.2 k8s.io/dynamic-resource-allocation => k8s.io/dynamic-resource-allocation v0.30.2 k8s.io/endpointslice => k8s.io/endpointslice v0.30.2 @@ -223,7 +223,7 @@ replace ( k8s.io/kubelet => k8s.io/kubelet v0.30.2 k8s.io/legacy-cloud-providers => k8s.io/legacy-cloud-providers v0.30.2 k8s.io/metrics => k8s.io/metrics v0.30.2 - k8s.io/mount-utils => k8s.io/mount-utils v0.30.2 + k8s.io/mount-utils => k8s.io/mount-utils v0.30.3 k8s.io/pod-security-admission => k8s.io/pod-security-admission v0.30.2 k8s.io/sample-apiserver => k8s.io/sample-apiserver v0.30.2 k8s.io/sample-cli-plugin => k8s.io/sample-cli-plugin v0.30.2 diff --git a/go.sum b/go.sum index 02f62307a..de91372e7 100644 --- a/go.sum +++ b/go.sum @@ -573,8 +573,8 @@ k8s.io/api v0.30.2 h1:+ZhRj+28QT4UOH+BKznu4CBgPWgkXO7XAvMcMl0qKvI= k8s.io/api v0.30.2/go.mod h1:ULg5g9JvOev2dG0u2hig4Z7tQ2hHIuS+m8MNZ+X6EmI= k8s.io/apiextensions-apiserver v0.30.2 h1:l7Eue2t6QiLHErfn2vwK4KgF4NeDgjQkCXtEbOocKIE= k8s.io/apiextensions-apiserver v0.30.2/go.mod h1:lsJFLYyK40iguuinsb3nt+Sj6CmodSI4ACDLep1rgjw= -k8s.io/apimachinery v0.30.2 h1:fEMcnBj6qkzzPGSVsAZtQThU62SmQ4ZymlXRC5yFSCg= -k8s.io/apimachinery v0.30.2/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= +k8s.io/apimachinery v0.30.3 h1:q1laaWCmrszyQuSQCfNB8cFgCuDAoPszKY4ucAjDwHc= +k8s.io/apimachinery v0.30.3/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc= k8s.io/apiserver v0.30.2 h1:ACouHiYl1yFI2VFI3YGM+lvxgy6ir4yK2oLOsLI1/tw= k8s.io/apiserver v0.30.2/go.mod h1:BOTdFBIch9Sv0ypSEcUR6ew/NUFGocRFNl72Ra7wTm8= k8s.io/client-go v0.30.2 h1:sBIVJdojUNPDU/jObC+18tXWcTJVcwyqS9diGdWHk50=