From 1e6bd1e50cda3841c41bc2af84f4bdcab316c14b Mon Sep 17 00:00:00 2001 From: Max Jonas Werner Date: Wed, 22 Mar 2023 17:40:59 +0100 Subject: [PATCH] Introduce v1 API and bump Receiver version to v1 This commit bumps the Receiver API version to v1 in preparation of the Flux GitOps GA milestone (https://fluxcd.io/roadmap/#flux-gitops-ga-q1-2023). We are now actively maintaining two versions of the notification API group in parallel: v1 which currently only holds the Receiver kind and v1beta2 for all other kinds. Since we haven't run into this situation before, I had to change the way we expose the API docs in ./docs/api: The directory now has sub-directories for each active API version. Therefore we need to change our scripts in the website repository to take this change into account so that we expose both API group version at https://fluxcd.io/flux/components/notification/api/. refs #436 Signed-off-by: Max Jonas Werner --- Makefile | 3 +- api/v1/doc.go | 20 + api/v1/groupversion_info.go | 33 + api/v1/receiver_types.go | 159 +++ api/v1/reference_types.go | 49 + api/v1/zz_generated.deepcopy.go | 164 ++++ api/v1beta2/receiver_types.go | 1 - ...notification.toolkit.fluxcd.io_alerts.yaml | 8 +- ...ification.toolkit.fluxcd.io_providers.yaml | 8 +- ...ification.toolkit.fluxcd.io_receivers.yaml | 230 ++++- config/testdata/status-defaults/receiver.yaml | 2 +- controllers/receiver_controller.go | 11 +- controllers/receiver_controller_test.go | 7 +- controllers/suite_test.go | 4 +- docs/api/v1/notification.md | 442 +++++++++ docs/api/{ => v1beta2}/notification.md | 2 +- docs/spec/v1/receivers.md | 912 ++++++++++++++++++ hack/api-docs/template/pkg.tpl | 7 +- internal/server/receiver_handler_test.go | 2 +- internal/server/receiver_handlers.go | 2 +- main.go | 8 +- 21 files changed, 2053 insertions(+), 21 deletions(-) create mode 100644 api/v1/doc.go create mode 100644 api/v1/groupversion_info.go create mode 100644 api/v1/receiver_types.go create mode 100644 api/v1/reference_types.go create mode 100644 api/v1/zz_generated.deepcopy.go create mode 100644 docs/api/v1/notification.md rename docs/api/{ => v1beta2}/notification.md (99%) create mode 100644 docs/spec/v1/receivers.md diff --git a/Makefile b/Makefile index 2fbc186f1..2502071f8 100644 --- a/Makefile +++ b/Makefile @@ -87,7 +87,8 @@ manifests: controller-gen # Generate API reference documentation api-docs: gen-crd-api-reference-docs - $(GEN_CRD_API_REFERENCE_DOCS) -api-dir=./api/v1beta2 -config=./hack/api-docs/config.json -template-dir=./hack/api-docs/template -out-file=./docs/api/notification.md + $(GEN_CRD_API_REFERENCE_DOCS) -api-dir=./api/v1beta2 -config=./hack/api-docs/config.json -template-dir=./hack/api-docs/template -out-file=./docs/api/v1beta2/notification.md + $(GEN_CRD_API_REFERENCE_DOCS) -api-dir=./api/v1 -config=./hack/api-docs/config.json -template-dir=./hack/api-docs/template -out-file=./docs/api/v1/notification.md # Run go mod tidy tidy: diff --git a/api/v1/doc.go b/api/v1/doc.go new file mode 100644 index 000000000..3eb81cb22 --- /dev/null +++ b/api/v1/doc.go @@ -0,0 +1,20 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package v1 contains API Schema definitions for the notification v1 API group. +// +kubebuilder:object:generate=true +// +groupName=notification.toolkit.fluxcd.io +package v1 diff --git a/api/v1/groupversion_info.go b/api/v1/groupversion_info.go new file mode 100644 index 000000000..20a8a0bb4 --- /dev/null +++ b/api/v1/groupversion_info.go @@ -0,0 +1,33 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/scheme" +) + +var ( + // GroupVersion is group version used to register these objects. + GroupVersion = schema.GroupVersion{Group: "notification.toolkit.fluxcd.io", Version: "v1"} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme. + SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion} + + // AddToScheme adds the types in this group-version to the given scheme. + AddToScheme = SchemeBuilder.AddToScheme +) diff --git a/api/v1/receiver_types.go b/api/v1/receiver_types.go new file mode 100644 index 000000000..89a4679df --- /dev/null +++ b/api/v1/receiver_types.go @@ -0,0 +1,159 @@ +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +import ( + "crypto/sha256" + "fmt" + "time" + + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + "github.com/fluxcd/pkg/apis/meta" +) + +const ( + ReceiverKind string = "Receiver" + ReceiverWebhookPath string = "/hook/" + GenericReceiver string = "generic" + GenericHMACReceiver string = "generic-hmac" + GitHubReceiver string = "github" + GitLabReceiver string = "gitlab" + BitbucketReceiver string = "bitbucket" + HarborReceiver string = "harbor" + DockerHubReceiver string = "dockerhub" + QuayReceiver string = "quay" + GCRReceiver string = "gcr" + NexusReceiver string = "nexus" + ACRReceiver string = "acr" +) + +// ReceiverSpec defines the desired state of the Receiver. +type ReceiverSpec struct { + // Type of webhook sender, used to determine + // the validation procedure and payload deserialization. + // +kubebuilder:validation:Enum=generic;generic-hmac;github;gitlab;bitbucket;harbor;dockerhub;quay;gcr;nexus;acr + // +required + Type string `json:"type"` + + // Interval at which to reconcile the Receiver with its Secret references. + // +kubebuilder:validation:Type=string + // +kubebuilder:validation:Pattern="^([0-9]+(\\.[0-9]+)?(ms|s|m|h))+$" + // +optional + Interval *metav1.Duration `json:"interval,omitempty"` + + // Events specifies the list of event types to handle, + // e.g. 'push' for GitHub or 'Push Hook' for GitLab. + // +optional + Events []string `json:"events"` + + // A list of resources to be notified about changes. + // +required + Resources []CrossNamespaceObjectReference `json:"resources"` + + // SecretRef specifies the Secret containing the token used + // to validate the payload authenticity. + // +required + SecretRef meta.LocalObjectReference `json:"secretRef,omitempty"` + + // Suspend tells the controller to suspend subsequent + // events handling for this receiver. + // +optional + Suspend bool `json:"suspend,omitempty"` +} + +// ReceiverStatus defines the observed state of the Receiver. +type ReceiverStatus struct { + meta.ReconcileRequestStatus `json:",inline"` + + // Conditions holds the conditions for the Receiver. + // +optional + Conditions []metav1.Condition `json:"conditions,omitempty"` + + // URL is the generated incoming webhook address in the format + // of '/hook/sha256sum(token+name+namespace)'. + // Deprecated: Replaced by WebhookPath. + // +optional + URL string `json:"url,omitempty"` + + // WebhookPath is the generated incoming webhook address in the format + // of '/hook/sha256sum(token+name+namespace)'. + // +optional + WebhookPath string `json:"webhookPath,omitempty"` + + // ObservedGeneration is the last observed generation of the Receiver object. + // +optional + ObservedGeneration int64 `json:"observedGeneration,omitempty"` +} + +// GetConditions returns the status conditions of the object. +func (in *Receiver) GetConditions() []metav1.Condition { + return in.Status.Conditions +} + +// SetConditions sets the status conditions on the object. +func (in *Receiver) SetConditions(conditions []metav1.Condition) { + in.Status.Conditions = conditions +} + +// GetWebhookPath returns the incoming webhook path for the given token. +func (in *Receiver) GetWebhookPath(token string) string { + digest := sha256.Sum256([]byte(token + in.GetName() + in.GetNamespace())) + return fmt.Sprintf("%s%x", ReceiverWebhookPath, digest) +} + +// GetInterval returns the interval value with a default of 10m for this Receiver. +func (in *Receiver) GetInterval() time.Duration { + duration := 10 * time.Minute + if in.Spec.Interval != nil { + duration = in.Spec.Interval.Duration + } + + return duration +} + +// +genclient +// +genclient:Namespaced +// +kubebuilder:storageversion +// +kubebuilder:object:root=true +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="" +// +kubebuilder:printcolumn:name="Ready",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].status",description="" +// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.conditions[?(@.type==\"Ready\")].message",description="" + +// Receiver is the Schema for the receivers API. +type Receiver struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ReceiverSpec `json:"spec,omitempty"` + // +kubebuilder:default:={"observedGeneration":-1} + Status ReceiverStatus `json:"status,omitempty"` +} + +// +kubebuilder:object:root=true + +// ReceiverList contains a list of Receivers. +type ReceiverList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Receiver `json:"items"` +} + +func init() { + SchemeBuilder.Register(&Receiver{}, &ReceiverList{}) +} diff --git a/api/v1/reference_types.go b/api/v1/reference_types.go new file mode 100644 index 000000000..de1d42224 --- /dev/null +++ b/api/v1/reference_types.go @@ -0,0 +1,49 @@ +/* +Copyright 2020 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package v1 + +// CrossNamespaceObjectReference contains enough information to let you locate the +// typed referenced object at cluster level +type CrossNamespaceObjectReference struct { + // API version of the referent + // +optional + APIVersion string `json:"apiVersion,omitempty"` + + // Kind of the referent + // +kubebuilder:validation:Enum=Bucket;GitRepository;Kustomization;HelmRelease;HelmChart;HelmRepository;ImageRepository;ImagePolicy;ImageUpdateAutomation;OCIRepository + // +required + Kind string `json:"kind,omitempty"` + + // Name of the referent + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=53 + // +required + Name string `json:"name"` + + // Namespace of the referent + // +kubebuilder:validation:MinLength=1 + // +kubebuilder:validation:MaxLength=53 + // +kubebuilder:validation:Optional + // +optional + Namespace string `json:"namespace,omitempty"` + + // MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels + // map is equivalent to an element of matchExpressions, whose key field is "key", the + // operator is "In", and the values array contains only "value". The requirements are ANDed. + // +optional + MatchLabels map[string]string `json:"matchLabels,omitempty"` +} diff --git a/api/v1/zz_generated.deepcopy.go b/api/v1/zz_generated.deepcopy.go new file mode 100644 index 000000000..15861e955 --- /dev/null +++ b/api/v1/zz_generated.deepcopy.go @@ -0,0 +1,164 @@ +//go:build !ignore_autogenerated +// +build !ignore_autogenerated + +/* +Copyright 2022 The Flux authors + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Code generated by controller-gen. DO NOT EDIT. + +package v1 + +import ( + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CrossNamespaceObjectReference) DeepCopyInto(out *CrossNamespaceObjectReference) { + *out = *in + if in.MatchLabels != nil { + in, out := &in.MatchLabels, &out.MatchLabels + *out = make(map[string]string, len(*in)) + for key, val := range *in { + (*out)[key] = val + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CrossNamespaceObjectReference. +func (in *CrossNamespaceObjectReference) DeepCopy() *CrossNamespaceObjectReference { + if in == nil { + return nil + } + out := new(CrossNamespaceObjectReference) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Receiver) DeepCopyInto(out *Receiver) { + *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 Receiver. +func (in *Receiver) DeepCopy() *Receiver { + if in == nil { + return nil + } + out := new(Receiver) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Receiver) 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 *ReceiverList) DeepCopyInto(out *ReceiverList) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ListMeta.DeepCopyInto(&out.ListMeta) + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Receiver, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReceiverList. +func (in *ReceiverList) DeepCopy() *ReceiverList { + if in == nil { + return nil + } + out := new(ReceiverList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ReceiverList) 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 *ReceiverSpec) DeepCopyInto(out *ReceiverSpec) { + *out = *in + if in.Interval != nil { + in, out := &in.Interval, &out.Interval + *out = new(metav1.Duration) + **out = **in + } + if in.Events != nil { + in, out := &in.Events, &out.Events + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Resources != nil { + in, out := &in.Resources, &out.Resources + *out = make([]CrossNamespaceObjectReference, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + out.SecretRef = in.SecretRef +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReceiverSpec. +func (in *ReceiverSpec) DeepCopy() *ReceiverSpec { + if in == nil { + return nil + } + out := new(ReceiverSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ReceiverStatus) DeepCopyInto(out *ReceiverStatus) { + *out = *in + out.ReconcileRequestStatus = in.ReconcileRequestStatus + if in.Conditions != nil { + in, out := &in.Conditions, &out.Conditions + *out = make([]metav1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ReceiverStatus. +func (in *ReceiverStatus) DeepCopy() *ReceiverStatus { + if in == nil { + return nil + } + out := new(ReceiverStatus) + in.DeepCopyInto(out) + return out +} diff --git a/api/v1beta2/receiver_types.go b/api/v1beta2/receiver_types.go index d52a49969..a29808749 100644 --- a/api/v1beta2/receiver_types.go +++ b/api/v1beta2/receiver_types.go @@ -128,7 +128,6 @@ func (in *Receiver) GetInterval() time.Duration { // +genclient // +genclient:Namespaced -// +kubebuilder:storageversion // +kubebuilder:object:root=true // +kubebuilder:subresource:status // +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp",description="" diff --git a/config/crd/bases/notification.toolkit.fluxcd.io_alerts.yaml b/config/crd/bases/notification.toolkit.fluxcd.io_alerts.yaml index fbf395bca..233112377 100644 --- a/config/crd/bases/notification.toolkit.fluxcd.io_alerts.yaml +++ b/config/crd/bases/notification.toolkit.fluxcd.io_alerts.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.8.0 creationTimestamp: null name: alerts.notification.toolkit.fluxcd.io spec: @@ -414,3 +414,9 @@ spec: storage: true subresources: status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crd/bases/notification.toolkit.fluxcd.io_providers.yaml b/config/crd/bases/notification.toolkit.fluxcd.io_providers.yaml index 3b0da5645..5ca7a49ef 100644 --- a/config/crd/bases/notification.toolkit.fluxcd.io_providers.yaml +++ b/config/crd/bases/notification.toolkit.fluxcd.io_providers.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.8.0 creationTimestamp: null name: providers.notification.toolkit.fluxcd.io spec: @@ -399,3 +399,9 @@ spec: storage: true subresources: status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/crd/bases/notification.toolkit.fluxcd.io_receivers.yaml b/config/crd/bases/notification.toolkit.fluxcd.io_receivers.yaml index 021d1882b..43d20211f 100644 --- a/config/crd/bases/notification.toolkit.fluxcd.io_receivers.yaml +++ b/config/crd/bases/notification.toolkit.fluxcd.io_receivers.yaml @@ -3,7 +3,7 @@ apiVersion: apiextensions.k8s.io/v1 kind: CustomResourceDefinition metadata: annotations: - controller-gen.kubebuilder.io/version: v0.11.1 + controller-gen.kubebuilder.io/version: v0.8.0 creationTimestamp: null name: receivers.notification.toolkit.fluxcd.io spec: @@ -15,6 +15,226 @@ spec: singular: receiver scope: Namespaced versions: + - additionalPrinterColumns: + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + - jsonPath: .status.conditions[?(@.type=="Ready")].status + name: Ready + type: string + - jsonPath: .status.conditions[?(@.type=="Ready")].message + name: Status + type: string + name: v1 + schema: + openAPIV3Schema: + description: Receiver is the Schema for the receivers API. + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: ReceiverSpec defines the desired state of the Receiver. + properties: + events: + description: Events specifies the list of event types to handle, e.g. + 'push' for GitHub or 'Push Hook' for GitLab. + items: + type: string + type: array + interval: + description: Interval at which to reconcile the Receiver with its + Secret references. + pattern: ^([0-9]+(\.[0-9]+)?(ms|s|m|h))+$ + type: string + resources: + description: A list of resources to be notified about changes. + items: + description: CrossNamespaceObjectReference contains enough information + to let you locate the typed referenced object at cluster level + properties: + apiVersion: + description: API version of the referent + type: string + kind: + description: Kind of the referent + enum: + - Bucket + - GitRepository + - Kustomization + - HelmRelease + - HelmChart + - HelmRepository + - ImageRepository + - ImagePolicy + - ImageUpdateAutomation + - OCIRepository + type: string + matchLabels: + additionalProperties: + type: string + description: MatchLabels is a map of {key,value} pairs. A single + {key,value} in the matchLabels map is equivalent to an element + of matchExpressions, whose key field is "key", the operator + is "In", and the values array contains only "value". The requirements + are ANDed. + type: object + name: + description: Name of the referent + maxLength: 53 + minLength: 1 + type: string + namespace: + description: Namespace of the referent + maxLength: 53 + minLength: 1 + type: string + required: + - name + type: object + type: array + secretRef: + description: SecretRef specifies the Secret containing the token used + to validate the payload authenticity. + properties: + name: + description: Name of the referent. + type: string + required: + - name + type: object + suspend: + description: Suspend tells the controller to suspend subsequent events + handling for this receiver. + type: boolean + type: + description: Type of webhook sender, used to determine the validation + procedure and payload deserialization. + enum: + - generic + - generic-hmac + - github + - gitlab + - bitbucket + - harbor + - dockerhub + - quay + - gcr + - nexus + - acr + type: string + required: + - resources + - type + type: object + status: + default: + observedGeneration: -1 + description: ReceiverStatus defines the observed state of the Receiver. + properties: + conditions: + description: Conditions holds the conditions for the Receiver. + items: + description: "Condition contains details for one aspect of the current + state of this API Resource. --- This struct is intended for direct + use as an array at the field path .status.conditions. For example, + \n type FooStatus struct{ // Represents the observations of a + foo's current state. // Known .status.conditions.type are: \"Available\", + \"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge + // +listType=map // +listMapKey=type Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }" + 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 + type: array + lastHandledReconcileAt: + description: LastHandledReconcileAt holds the value of the most recent + reconcile request value, so a change of the annotation value can + be detected. + type: string + observedGeneration: + description: ObservedGeneration is the last observed generation of + the Receiver object. + format: int64 + type: integer + url: + description: 'URL is the generated incoming webhook address in the + format of ''/hook/sha256sum(token+name+namespace)''. Deprecated: + Replaced by WebhookPath.' + type: string + webhookPath: + description: WebhookPath is the generated incoming webhook address + in the format of '/hook/sha256sum(token+name+namespace)'. + type: string + type: object + type: object + served: true + storage: true + subresources: + status: {} - additionalPrinterColumns: - jsonPath: .metadata.creationTimestamp name: Age @@ -435,6 +655,12 @@ spec: type: object type: object served: true - storage: true + storage: false subresources: status: {} +status: + acceptedNames: + kind: "" + plural: "" + conditions: [] + storedVersions: [] diff --git a/config/testdata/status-defaults/receiver.yaml b/config/testdata/status-defaults/receiver.yaml index 254f51afb..fbba61a78 100644 --- a/config/testdata/status-defaults/receiver.yaml +++ b/config/testdata/status-defaults/receiver.yaml @@ -1,4 +1,4 @@ -apiVersion: notification.toolkit.fluxcd.io/v1beta1 +apiVersion: notification.toolkit.fluxcd.io/v1 kind: Receiver metadata: name: status-defaults diff --git a/controllers/receiver_controller.go b/controllers/receiver_controller.go index f441fc1cc..5d2af0125 100644 --- a/controllers/receiver_controller.go +++ b/controllers/receiver_controller.go @@ -40,7 +40,8 @@ import ( "github.com/fluxcd/pkg/runtime/patch" "github.com/fluxcd/pkg/runtime/predicates" - apiv1 "github.com/fluxcd/notification-controller/api/v1beta2" + apiv1 "github.com/fluxcd/notification-controller/api/v1" + apiv1b2 "github.com/fluxcd/notification-controller/api/v1beta2" ) // ReceiverReconciler reconciles a Receiver object @@ -126,14 +127,14 @@ func (r *ReceiverReconciler) Reconcile(ctx context.Context, req ctrl.Request) (r } }() - if !controllerutil.ContainsFinalizer(obj, apiv1.NotificationFinalizer) { - controllerutil.AddFinalizer(obj, apiv1.NotificationFinalizer) + if !controllerutil.ContainsFinalizer(obj, apiv1b2.NotificationFinalizer) { + controllerutil.AddFinalizer(obj, apiv1b2.NotificationFinalizer) result = ctrl.Result{Requeue: true} return } if !obj.ObjectMeta.DeletionTimestamp.IsZero() { - controllerutil.RemoveFinalizer(obj, apiv1.NotificationFinalizer) + controllerutil.RemoveFinalizer(obj, apiv1b2.NotificationFinalizer) result = ctrl.Result{} return } @@ -155,7 +156,7 @@ func (r *ReceiverReconciler) reconcile(ctx context.Context, obj *apiv1.Receiver) token, err := r.token(ctx, obj) if err != nil { - conditions.MarkFalse(obj, meta.ReadyCondition, apiv1.TokenNotFoundReason, err.Error()) + conditions.MarkFalse(obj, meta.ReadyCondition, apiv1b2.TokenNotFoundReason, err.Error()) obj.Status.URL = "" obj.Status.WebhookPath = "" return ctrl.Result{Requeue: true}, err diff --git a/controllers/receiver_controller_test.go b/controllers/receiver_controller_test.go index 0f123469f..b57b40b98 100644 --- a/controllers/receiver_controller_test.go +++ b/controllers/receiver_controller_test.go @@ -39,7 +39,8 @@ import ( "github.com/fluxcd/pkg/runtime/conditions" "github.com/fluxcd/pkg/ssa" - apiv1 "github.com/fluxcd/notification-controller/api/v1beta2" + apiv1 "github.com/fluxcd/notification-controller/api/v1" + apiv1b2 "github.com/fluxcd/notification-controller/api/v1beta2" "github.com/fluxcd/notification-controller/internal/server" ) @@ -101,7 +102,7 @@ func TestReceiverReconciler_Reconcile(t *testing.T) { g.Expect(conditions.GetReason(resultR, meta.ReadyCondition)).To(BeIdenticalTo(meta.SucceededReason)) g.Expect(conditions.Has(resultR, meta.ReconcilingCondition)).To(BeFalse()) - g.Expect(controllerutil.ContainsFinalizer(resultR, apiv1.NotificationFinalizer)).To(BeTrue()) + g.Expect(controllerutil.ContainsFinalizer(resultR, apiv1b2.NotificationFinalizer)).To(BeTrue()) }) t.Run("fails with secret not found error", func(t *testing.T) { @@ -122,7 +123,7 @@ func TestReceiverReconciler_Reconcile(t *testing.T) { return !conditions.IsReady(resultR) }, timeout, time.Second).Should(BeTrue()) - g.Expect(conditions.GetReason(resultR, meta.ReadyCondition)).To(BeIdenticalTo(apiv1.TokenNotFoundReason)) + g.Expect(conditions.GetReason(resultR, meta.ReadyCondition)).To(BeIdenticalTo(apiv1b2.TokenNotFoundReason)) g.Expect(conditions.GetMessage(resultR, meta.ReadyCondition)).To(ContainSubstring(secretName)) g.Expect(conditions.Has(resultR, meta.ReconcilingCondition)).To(BeTrue()) diff --git a/controllers/suite_test.go b/controllers/suite_test.go index 4ab956a5c..9c2302d3a 100644 --- a/controllers/suite_test.go +++ b/controllers/suite_test.go @@ -40,7 +40,8 @@ import ( "github.com/fluxcd/pkg/runtime/testenv" "github.com/fluxcd/pkg/ssa" - apiv1 "github.com/fluxcd/notification-controller/api/v1beta2" + apiv1 "github.com/fluxcd/notification-controller/api/v1" + apiv1b2 "github.com/fluxcd/notification-controller/api/v1beta2" // +kubebuilder:scaffold:imports ) @@ -54,6 +55,7 @@ var ( func TestMain(m *testing.M) { var err error utilruntime.Must(apiv1.AddToScheme(scheme.Scheme)) + utilruntime.Must(apiv1b2.AddToScheme(scheme.Scheme)) testEnv = testenv.New(testenv.WithCRDPath( filepath.Join("..", "config", "crd", "bases"), diff --git a/docs/api/v1/notification.md b/docs/api/v1/notification.md new file mode 100644 index 000000000..a124fee16 --- /dev/null +++ b/docs/api/v1/notification.md @@ -0,0 +1,442 @@ +

Notification API reference v1

+

Packages:

+ +

notification.toolkit.fluxcd.io/v1

+

Package v1 contains API Schema definitions for the notification v1 API group.

+Resource Types: + +

Receiver +

+

Receiver is the Schema for the receivers API.

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+apiVersion
+string
+notification.toolkit.fluxcd.io/v1 +
+kind
+string +
+Receiver +
+metadata
+ + +Kubernetes meta/v1.ObjectMeta + + +
+Refer to the Kubernetes API documentation for the fields of the +metadata field. +
+spec
+ + +ReceiverSpec + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+type
+ +string + +
+

Type of webhook sender, used to determine +the validation procedure and payload deserialization.

+
+interval
+ + +Kubernetes meta/v1.Duration + + +
+(Optional) +

Interval at which to reconcile the Receiver with its Secret references.

+
+events
+ +[]string + +
+(Optional) +

Events specifies the list of event types to handle, +e.g. ‘push’ for GitHub or ‘Push Hook’ for GitLab.

+
+resources
+ + +[]CrossNamespaceObjectReference + + +
+

A list of resources to be notified about changes.

+
+secretRef
+ + +github.com/fluxcd/pkg/apis/meta.LocalObjectReference + + +
+

SecretRef specifies the Secret containing the token used +to validate the payload authenticity.

+
+suspend
+ +bool + +
+(Optional) +

Suspend tells the controller to suspend subsequent +events handling for this receiver.

+
+
+status
+ + +ReceiverStatus + + +
+
+
+
+

CrossNamespaceObjectReference +

+

+(Appears on: +ReceiverSpec) +

+

CrossNamespaceObjectReference contains enough information to let you locate the +typed referenced object at cluster level

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+apiVersion
+ +string + +
+(Optional) +

API version of the referent

+
+kind
+ +string + +
+

Kind of the referent

+
+name
+ +string + +
+

Name of the referent

+
+namespace
+ +string + +
+(Optional) +

Namespace of the referent

+
+matchLabels
+ +map[string]string + +
+(Optional) +

MatchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels +map is equivalent to an element of matchExpressions, whose key field is “key”, the +operator is “In”, and the values array contains only “value”. The requirements are ANDed.

+
+
+
+

ReceiverSpec +

+

+(Appears on: +Receiver) +

+

ReceiverSpec defines the desired state of the Receiver.

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+type
+ +string + +
+

Type of webhook sender, used to determine +the validation procedure and payload deserialization.

+
+interval
+ + +Kubernetes meta/v1.Duration + + +
+(Optional) +

Interval at which to reconcile the Receiver with its Secret references.

+
+events
+ +[]string + +
+(Optional) +

Events specifies the list of event types to handle, +e.g. ‘push’ for GitHub or ‘Push Hook’ for GitLab.

+
+resources
+ + +[]CrossNamespaceObjectReference + + +
+

A list of resources to be notified about changes.

+
+secretRef
+ + +github.com/fluxcd/pkg/apis/meta.LocalObjectReference + + +
+

SecretRef specifies the Secret containing the token used +to validate the payload authenticity.

+
+suspend
+ +bool + +
+(Optional) +

Suspend tells the controller to suspend subsequent +events handling for this receiver.

+
+
+
+

ReceiverStatus +

+

+(Appears on: +Receiver) +

+

ReceiverStatus defines the observed state of the Receiver.

+
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
FieldDescription
+ReconcileRequestStatus
+ + +github.com/fluxcd/pkg/apis/meta.ReconcileRequestStatus + + +
+

+(Members of ReconcileRequestStatus are embedded into this type.) +

+
+conditions
+ + +[]Kubernetes meta/v1.Condition + + +
+(Optional) +

Conditions holds the conditions for the Receiver.

+
+url
+ +string + +
+(Optional) +

URL is the generated incoming webhook address in the format +of ‘/hook/sha256sum(token+name+namespace)’. +Deprecated: Replaced by WebhookPath.

+
+webhookPath
+ +string + +
+(Optional) +

WebhookPath is the generated incoming webhook address in the format +of ‘/hook/sha256sum(token+name+namespace)’.

+
+observedGeneration
+ +int64 + +
+(Optional) +

ObservedGeneration is the last observed generation of the Receiver object.

+
+
+
+
+

This page was automatically generated with gen-crd-api-reference-docs

+
diff --git a/docs/api/notification.md b/docs/api/v1beta2/notification.md similarity index 99% rename from docs/api/notification.md rename to docs/api/v1beta2/notification.md index f61bd7616..e117cbe96 100644 --- a/docs/api/notification.md +++ b/docs/api/v1beta2/notification.md @@ -1,4 +1,4 @@ -

Notification API reference

+

Notification API reference v1beta2

Packages: