From b3431139915ab430f1c82ce31165ad318b8436d9 Mon Sep 17 00:00:00 2001 From: Aurel Canciu Date: Tue, 3 Nov 2020 18:23:32 +0200 Subject: [PATCH] Adopt k8s standardized conditions Use the newly introduced standardized Condition type kubernetes/enhancements#1624 Relates to fluxcd/flux2#225 Signed-off-by: Aurel Canciu --- api/v1alpha1/condition_types.go | 48 --------------- api/v1alpha1/imagerepository_types.go | 11 ++-- api/v1alpha1/zz_generated.deepcopy.go | 18 +----- ...e.toolkit.fluxcd.io_imagerepositories.yaml | 61 +++++++++++++++---- controllers/imagerepository_controller.go | 16 ++--- controllers/scan_test.go | 2 +- 6 files changed, 65 insertions(+), 91 deletions(-) diff --git a/api/v1alpha1/condition_types.go b/api/v1alpha1/condition_types.go index b4c02a00..2814cdbf 100644 --- a/api/v1alpha1/condition_types.go +++ b/api/v1alpha1/condition_types.go @@ -16,55 +16,7 @@ limitations under the License. package v1alpha1 -import ( - corev1 "k8s.io/api/core/v1" - metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" -) - -// Condition contains condition information for a toolkit resource. -type Condition struct { - // Type of the condition, currently ('Ready'). - // +required - Type string `json:"type"` - - // Status of the condition, one of ('True', 'False', 'Unknown'). - // +required - Status corev1.ConditionStatus `json:"status"` - - // LastTransitionTime is the timestamp corresponding to the last status - // change of this condition. - // +required - LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` - - // Reason is a brief machine readable explanation for the condition's last - // transition. - // +required - Reason string `json:"reason,omitempty"` - - // Message is a human readable description of the details of the last - // transition, complementing reason. - // +optional - Message string `json:"message,omitempty"` -} - const ( - // ReadyCondition records the last reconciliation result. - ReadyCondition string = "Ready" -) - -const ( - // ReconciliationSucceededReason represents the fact that the reconciliation of the resource has succeeded. - ReconciliationSucceededReason string = "ReconciliationSucceeded" - - // ReconciliationFailedReason represents the fact that the reconciliation of the resource has failed. - ReconciliationFailedReason string = "ReconciliationFailed" - // ImageURLInvalidReason represents the fact that a given repository has an invalid image URL. ImageURLInvalidReason string = "ImageURLInvalid" - - // ProgressingReason represents the fact that a reconciliation is underway. - ProgressingReason string = "Progressing" - - // SuspendedReason represents the fact that the reconciliation is suspended. - SuspendedReason string = "Suspended" ) diff --git a/api/v1alpha1/imagerepository_types.go b/api/v1alpha1/imagerepository_types.go index b924d8f8..1e7f5307 100644 --- a/api/v1alpha1/imagerepository_types.go +++ b/api/v1alpha1/imagerepository_types.go @@ -17,7 +17,6 @@ limitations under the License. package v1alpha1 import ( - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "github.com/fluxcd/pkg/apis/meta" @@ -49,7 +48,7 @@ type ScanResult struct { // ImageRepositoryStatus defines the observed state of ImageRepository type ImageRepositoryStatus struct { // +optional - Conditions []Condition `json:"conditions,omitempty"` + Conditions []metav1.Condition `json:"conditions,omitempty"` // ObservedGeneration is the last reconciled generation. // +optional @@ -69,10 +68,10 @@ type ImageRepositoryStatus struct { } // SetImageRepositoryReadiness sets the ready condition with the given status, reason and message. -func SetImageRepositoryReadiness(ir ImageRepository, status corev1.ConditionStatus, reason, message string) ImageRepository { - ir.Status.Conditions = []Condition{ +func SetImageRepositoryReadiness(ir ImageRepository, status metav1.ConditionStatus, reason, message string) ImageRepository { + ir.Status.Conditions = []metav1.Condition{ { - Type: ReadyCondition, + Type: meta.ReadyCondition, Status: status, LastTransitionTime: metav1.Now(), Reason: reason, @@ -85,7 +84,7 @@ func SetImageRepositoryReadiness(ir ImageRepository, status corev1.ConditionStat func GetLastTransitionTime(ir ImageRepository) *metav1.Time { for _, condition := range ir.Status.Conditions { - if condition.Type == ReadyCondition { + if condition.Type == meta.ReadyCondition { return &condition.LastTransitionTime } } diff --git a/api/v1alpha1/zz_generated.deepcopy.go b/api/v1alpha1/zz_generated.deepcopy.go index 10de0f74..59e1b985 100644 --- a/api/v1alpha1/zz_generated.deepcopy.go +++ b/api/v1alpha1/zz_generated.deepcopy.go @@ -25,22 +25,6 @@ import ( runtime "k8s.io/apimachinery/pkg/runtime" ) -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *Condition) DeepCopyInto(out *Condition) { - *out = *in - in.LastTransitionTime.DeepCopyInto(&out.LastTransitionTime) -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Condition. -func (in *Condition) DeepCopy() *Condition { - if in == nil { - return nil - } - out := new(Condition) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ImagePolicy) DeepCopyInto(out *ImagePolicy) { *out = *in @@ -236,7 +220,7 @@ func (in *ImageRepositoryStatus) DeepCopyInto(out *ImageRepositoryStatus) { *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions - *out = make([]Condition, len(*in)) + *out = make([]v1.Condition, len(*in)) for i := range *in { (*in)[i].DeepCopyInto(&(*out)[i]) } diff --git a/config/crd/bases/image.toolkit.fluxcd.io_imagerepositories.yaml b/config/crd/bases/image.toolkit.fluxcd.io_imagerepositories.yaml index 4979043a..668f6d7c 100644 --- a/config/crd/bases/image.toolkit.fluxcd.io_imagerepositories.yaml +++ b/config/crd/bases/image.toolkit.fluxcd.io_imagerepositories.yaml @@ -67,30 +67,69 @@ spec: type: string conditions: items: - description: Condition contains condition information for a toolkit - resource. + 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, + 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 timestamp corresponding - to the last status change of this condition. + 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 description of the - details of the last transition, complementing reason. + 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 is a brief machine readable explanation - for the condition's last transition. + 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'). + description: status of the condition, one of True, False, Unknown. + enum: + - "True" + - "False" + - Unknown type: string type: - description: Type of the condition, currently ('Ready'). + 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 diff --git a/controllers/imagerepository_controller.go b/controllers/imagerepository_controller.go index 7bb7388c..233b9a40 100644 --- a/controllers/imagerepository_controller.go +++ b/controllers/imagerepository_controller.go @@ -25,7 +25,7 @@ import ( "github.com/go-logr/logr" "github.com/google/go-containerregistry/pkg/name" "github.com/google/go-containerregistry/pkg/v1/remote" - corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" kuberecorder "k8s.io/client-go/tools/record" ctrl "sigs.k8s.io/controller-runtime" @@ -83,8 +83,8 @@ func (r *ImageRepositoryReconciler) Reconcile(req ctrl.Request) (ctrl.Result, er msg := "ImageRepository is suspended, skipping reconciliation" status := imagev1alpha1.SetImageRepositoryReadiness( imageRepo, - corev1.ConditionFalse, - imagev1alpha1.SuspendedReason, + metav1.ConditionFalse, + meta.SuspendedReason, msg, ) if err := r.Status().Update(ctx, &status); err != nil { @@ -99,7 +99,7 @@ func (r *ImageRepositoryReconciler) Reconcile(req ctrl.Request) (ctrl.Result, er if err != nil { status := imagev1alpha1.SetImageRepositoryReadiness( imageRepo, - corev1.ConditionFalse, + metav1.ConditionFalse, imagev1alpha1.ImageURLInvalidReason, err.Error(), ) @@ -144,8 +144,8 @@ func (r *ImageRepositoryReconciler) scan(ctx context.Context, imageRepo imagev1a if err != nil { return imagev1alpha1.SetImageRepositoryReadiness( imageRepo, - corev1.ConditionFalse, - imagev1alpha1.ReconciliationFailedReason, + metav1.ConditionFalse, + meta.ReconciliationFailedReason, err.Error(), ), err } @@ -164,8 +164,8 @@ func (r *ImageRepositoryReconciler) scan(ctx context.Context, imageRepo imagev1a return imagev1alpha1.SetImageRepositoryReadiness( imageRepo, - corev1.ConditionTrue, - imagev1alpha1.ReconciliationSucceededReason, + metav1.ConditionTrue, + meta.ReconciliationSucceededReason, fmt.Sprintf("successful scan, found %v tags", len(tags)), ), nil } diff --git a/controllers/scan_test.go b/controllers/scan_test.go index d8fcafaf..6a5206c4 100644 --- a/controllers/scan_test.go +++ b/controllers/scan_test.go @@ -144,7 +144,7 @@ var _ = Describe("ImageRepository controller", func() { Expect(cond.Message).To( Equal("ImageRepository is suspended, skipping reconciliation")) Expect(cond.Reason).To( - Equal(imagev1alpha1.SuspendedReason)) + Equal(meta.SuspendedReason)) }) })