From 407b91f0e7d660983d289d2457404c55b0fa6ee5 Mon Sep 17 00:00:00 2001 From: shreddedbacon Date: Wed, 2 Oct 2024 15:45:22 +1000 Subject: [PATCH] refactor: use status conditions to store build status --- apis/lagoon/v1beta1/lagoonbuild_types.go | 3 +- apis/lagoon/v1beta1/lagoontask_types.go | 23 ++++- apis/lagoon/v1beta2/lagoonbuild_helpers.go | 21 ++--- apis/lagoon/v1beta2/lagoonbuild_types.go | 23 ++--- apis/lagoon/v1beta2/lagoontask_helpers.go | 3 +- apis/lagoon/v1beta2/lagoontask_types.go | 22 ++--- apis/lagoon/v1beta2/zz_generated.deepcopy.go | 53 ++--------- .../crd/bases/crd.lagoon.sh_lagoonbuilds.yaml | 90 +++++++++++++++++-- .../crd/bases/crd.lagoon.sh_lagoontasks.yaml | 86 ++++++++++++++++-- config/manager/manager.yaml | 3 - controller-test.sh | 3 +- controllers/v1beta2/build_controller.go | 3 + .../v1beta2/podmonitor_buildhandlers.go | 36 ++++---- .../v1beta2/podmonitor_taskhandlers.go | 21 +++-- internal/messenger/consumer.go | 7 +- 15 files changed, 257 insertions(+), 140 deletions(-) diff --git a/apis/lagoon/v1beta1/lagoonbuild_types.go b/apis/lagoon/v1beta1/lagoonbuild_types.go index ed3aa281..2e2eb830 100644 --- a/apis/lagoon/v1beta1/lagoonbuild_types.go +++ b/apis/lagoon/v1beta1/lagoonbuild_types.go @@ -102,7 +102,8 @@ type LagoonBuildConditions struct { LastTransitionTime string `json:"lastTransitionTime"` Status corev1.ConditionStatus `json:"status"` Type BuildStatusType `json:"type"` - // Condition string `json:"condition"` + Reason string `json:"reason"` + Message string `json:"message"` } func init() { diff --git a/apis/lagoon/v1beta1/lagoontask_types.go b/apis/lagoon/v1beta1/lagoontask_types.go index 20393163..861a3fe4 100644 --- a/apis/lagoon/v1beta1/lagoontask_types.go +++ b/apis/lagoon/v1beta1/lagoontask_types.go @@ -171,13 +171,34 @@ type LagoonTaskConditions struct { LastTransitionTime string `json:"lastTransitionTime"` Status corev1.ConditionStatus `json:"status"` Type TaskStatusType `json:"type"` - // Condition string `json:"condition"` + Reason string `json:"reason"` + Message string `json:"message"` } func init() { SchemeBuilder.Register(&LagoonTask{}, &LagoonTaskList{}) } +// convert to string as required for environment ID for backwards compatability +func (a *LagoonTaskEnvironment) UnmarshalJSON(data []byte) error { + tmpMap := map[string]interface{}{} + json.Unmarshal(data, &tmpMap) + if value, ok := tmpMap["id"]; ok { + a.ID = fmt.Sprintf("%v", value) + } + return nil +} + +// convert to string as required for project ID for backwards compatability +func (a *LagoonTaskProject) UnmarshalJSON(data []byte) error { + tmpMap := map[string]interface{}{} + json.Unmarshal(data, &tmpMap) + if value, ok := tmpMap["id"]; ok { + a.ID = fmt.Sprintf("%v", value) + } + return nil +} + // this is a custom unmarshal function that will check deployerToken and sshKey which come from Lagoon as `1|0` booleans because javascript // this converts them from floats to bools func (a *LagoonAdvancedTaskInfo) UnmarshalJSON(data []byte) error { diff --git a/apis/lagoon/v1beta2/lagoonbuild_helpers.go b/apis/lagoon/v1beta2/lagoonbuild_helpers.go index 4045d666..dd207aa0 100644 --- a/apis/lagoon/v1beta2/lagoonbuild_helpers.go +++ b/apis/lagoon/v1beta2/lagoonbuild_helpers.go @@ -14,6 +14,7 @@ import ( "github.com/uselagoon/remote-controller/internal/helpers" "github.com/uselagoon/remote-controller/internal/metrics" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/selection" "k8s.io/apimachinery/pkg/types" @@ -44,7 +45,7 @@ var ( ) // BuildContainsStatus . -func BuildContainsStatus(slice []LagoonBuildConditions, s LagoonBuildConditions) bool { +func BuildContainsStatus(slice []metav1.Condition, s metav1.Condition) bool { for _, item := range slice { if item == s { return true @@ -363,20 +364,16 @@ func updateLagoonBuild(namespace string, jobSpec LagoonTaskSpec, lagoonBuild *La conditions := lagoonBuild.Status.Conditions // sort the build conditions by time so the first and last can be extracted sort.Slice(conditions, func(i, j int) bool { - iTime, _ := time.Parse("2006-01-02T15:04:05Z", conditions[i].LastTransitionTime) - jTime, _ := time.Parse("2006-01-02T15:04:05Z", conditions[j].LastTransitionTime) - return iTime.Before(jTime) + iTime := conditions[i].LastTransitionTime + jTime := conditions[j].LastTransitionTime + return iTime.Before(&jTime) }) // get the starting time, or fallback to default - sTime, err := time.Parse("2006-01-02T15:04:05Z", conditions[0].LastTransitionTime) - if err == nil { - msg.Meta.StartTime = sTime.Format("2006-01-02 15:04:05") - } + sTime := conditions[0].LastTransitionTime + msg.Meta.StartTime = sTime.Format("2006-01-02 15:04:05") // get the ending time, or fallback to default - eTime, err := time.Parse("2006-01-02T15:04:05Z", conditions[len(conditions)-1].LastTransitionTime) - if err == nil { - msg.Meta.EndTime = eTime.Format("2006-01-02 15:04:05") - } + eTime := conditions[len(conditions)-1].LastTransitionTime + msg.Meta.EndTime = eTime.Format("2006-01-02 15:04:05") } msgBytes, err := json.Marshal(msg) if err != nil { diff --git a/apis/lagoon/v1beta2/lagoonbuild_types.go b/apis/lagoon/v1beta2/lagoonbuild_types.go index fcbcc7b5..01a5b4e0 100644 --- a/apis/lagoon/v1beta2/lagoonbuild_types.go +++ b/apis/lagoon/v1beta2/lagoonbuild_types.go @@ -18,12 +18,14 @@ package v1beta2 import ( "strings" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) // +kubebuilder:object:root=true -//+kubebuilder:storageversion +// +kubebuilder:storageversion +// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=`.status.phase`,description="Status of the LagoonBuild" +// +kubebuilder:printcolumn:name="BuildStep",type="string",JSONPath=`.status.conditions[?(@.type == "BuildStep")].reason`,description="The build step of the LagoonBuild" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" // LagoonBuild is the Schema for the lagoonbuilds API type LagoonBuild struct { @@ -88,18 +90,11 @@ type LagoonBuildSpec struct { // LagoonBuildStatus defines the observed state of LagoonBuild type LagoonBuildStatus struct { - // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - // Important: Run "make" to regenerate code after modifying this file - Conditions []LagoonBuildConditions `json:"conditions,omitempty"` - Log []byte `json:"log,omitempty"` -} - -// LagoonBuildConditions defines the observed conditions of build pods. -type LagoonBuildConditions struct { - LastTransitionTime string `json:"lastTransitionTime"` - Status corev1.ConditionStatus `json:"status"` - Type BuildStatusType `json:"type"` - // Condition string `json:"condition"` + // Conditions provide a standard mechanism for higher-level status reporting from a controller. + // They are an extension mechanism which allows tools and other controllers to collect summary information about + // resources without needing to understand resource-specific status details. + Conditions []metav1.Condition `json:"conditions,omitempty"` + Phase string `json:"phase,omitempty"` } func init() { diff --git a/apis/lagoon/v1beta2/lagoontask_helpers.go b/apis/lagoon/v1beta2/lagoontask_helpers.go index b2a45266..aad178a2 100644 --- a/apis/lagoon/v1beta2/lagoontask_helpers.go +++ b/apis/lagoon/v1beta2/lagoontask_helpers.go @@ -11,6 +11,7 @@ import ( "github.com/uselagoon/machinery/api/schema" "github.com/uselagoon/remote-controller/internal/helpers" corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/selection" "k8s.io/apimachinery/pkg/types" @@ -41,7 +42,7 @@ var ( ) // TaskContainsStatus . -func TaskContainsStatus(slice []LagoonTaskConditions, s LagoonTaskConditions) bool { +func TaskContainsStatus(slice []metav1.Condition, s metav1.Condition) bool { for _, item := range slice { if item == s { return true diff --git a/apis/lagoon/v1beta2/lagoontask_types.go b/apis/lagoon/v1beta2/lagoontask_types.go index 7ed56687..8e9e4d6f 100644 --- a/apis/lagoon/v1beta2/lagoontask_types.go +++ b/apis/lagoon/v1beta2/lagoontask_types.go @@ -23,7 +23,6 @@ import ( "strings" "github.com/uselagoon/machinery/api/schema" - corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) @@ -31,7 +30,9 @@ import ( // NOTE: json tags are required. Any new fields you add must have json tags for the fields to be serialized. // +kubebuilder:object:root=true -//+kubebuilder:storageversion +// +kubebuilder:storageversion +// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=`.status.phase`,description="Status of the LagoonTask" +// +kubebuilder:printcolumn:name="Age",type="date",JSONPath=".metadata.creationTimestamp" // LagoonTask is the Schema for the lagoontasks API type LagoonTask struct { @@ -147,18 +148,11 @@ type LagoonTaskEnvironment struct { // LagoonTaskStatus defines the observed state of LagoonTask type LagoonTaskStatus struct { - // INSERT ADDITIONAL STATUS FIELD - define observed state of cluster - // Important: Run "make" to regenerate code after modifying this file - Conditions []LagoonTaskConditions `json:"conditions,omitempty"` - Log []byte `json:"log,omitempty"` -} - -// LagoonTaskConditions defines the observed conditions of task pods. -type LagoonTaskConditions struct { - LastTransitionTime string `json:"lastTransitionTime"` - Status corev1.ConditionStatus `json:"status"` - Type TaskStatusType `json:"type"` - // Condition string `json:"condition"` + // Conditions provide a standard mechanism for higher-level status reporting from a controller. + // They are an extension mechanism which allows tools and other controllers to collect summary information about + // resources without needing to understand resource-specific status details. + Conditions []metav1.Condition `json:"conditions,omitempty"` + Phase string `json:"phase,omitempty"` } func init() { diff --git a/apis/lagoon/v1beta2/zz_generated.deepcopy.go b/apis/lagoon/v1beta2/zz_generated.deepcopy.go index b8802ec1..a083b879 100644 --- a/apis/lagoon/v1beta2/zz_generated.deepcopy.go +++ b/apis/lagoon/v1beta2/zz_generated.deepcopy.go @@ -21,6 +21,7 @@ limitations under the License. package v1beta2 import ( + "k8s.io/apimachinery/pkg/apis/meta/v1" runtime "k8s.io/apimachinery/pkg/runtime" ) @@ -101,21 +102,6 @@ func (in *LagoonBuild) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *LagoonBuildConditions) DeepCopyInto(out *LagoonBuildConditions) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LagoonBuildConditions. -func (in *LagoonBuildConditions) DeepCopy() *LagoonBuildConditions { - if in == nil { - return nil - } - out := new(LagoonBuildConditions) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LagoonBuildList) DeepCopyInto(out *LagoonBuildList) { *out = *in @@ -173,13 +159,10 @@ func (in *LagoonBuildStatus) DeepCopyInto(out *LagoonBuildStatus) { *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions - *out = make([]LagoonBuildConditions, len(*in)) - copy(*out, *in) - } - if in.Log != nil { - in, out := &in.Log, &out.Log - *out = make([]byte, len(*in)) - copy(*out, *in) + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } } @@ -260,21 +243,6 @@ func (in *LagoonTask) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *LagoonTaskConditions) DeepCopyInto(out *LagoonTaskConditions) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LagoonTaskConditions. -func (in *LagoonTaskConditions) DeepCopy() *LagoonTaskConditions { - if in == nil { - return nil - } - out := new(LagoonTaskConditions) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LagoonTaskEnvironment) DeepCopyInto(out *LagoonTaskEnvironment) { *out = *in @@ -386,13 +354,10 @@ func (in *LagoonTaskStatus) DeepCopyInto(out *LagoonTaskStatus) { *out = *in if in.Conditions != nil { in, out := &in.Conditions, &out.Conditions - *out = make([]LagoonTaskConditions, len(*in)) - copy(*out, *in) - } - if in.Log != nil { - in, out := &in.Log, &out.Log - *out = make([]byte, len(*in)) - copy(*out, *in) + *out = make([]v1.Condition, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } } } diff --git a/config/crd/bases/crd.lagoon.sh_lagoonbuilds.yaml b/config/crd/bases/crd.lagoon.sh_lagoonbuilds.yaml index ed182224..ac4dcf1f 100644 --- a/config/crd/bases/crd.lagoon.sh_lagoonbuilds.yaml +++ b/config/crd/bases/crd.lagoon.sh_lagoonbuilds.yaml @@ -188,6 +188,10 @@ spec: properties: lastTransitionTime: type: string + message: + type: string + reason: + type: string status: type: string type: @@ -195,6 +199,8 @@ spec: type: string required: - lastTransitionTime + - message + - reason - status - type type: object @@ -681,7 +687,19 @@ spec: type: object served: true storage: false - - name: v1beta2 + - additionalPrinterColumns: + - description: Status of the LagoonBuild + jsonPath: .status.phase + name: Status + type: string + - description: The build step of the LagoonBuild + jsonPath: .status.conditions[?(@.type == "BuildStep")].reason + name: BuildStep + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta2 schema: openAPIV3Schema: description: LagoonBuild is the Schema for the lagoonbuilds API @@ -842,33 +860,87 @@ spec: description: LagoonBuildStatus defines the observed state of LagoonBuild properties: conditions: - description: 'INSERT ADDITIONAL STATUS FIELD - define observed state - of cluster Important: Run "make" to regenerate code after modifying - this file' + description: Conditions provide a standard mechanism for higher-level + status reporting from a controller. They are an extension mechanism + which allows tools and other controllers to collect summary information + about resources without needing to understand resource-specific + status details. items: - description: LagoonBuildConditions defines the observed conditions - of build pods. + 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 \ttype FooStatus struct{ \t // Represents the observations + of a foo's current state. \t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\" \t // + +patchMergeKey=type \t // +patchStrategy=merge \t // +listType=map + \t // +listMapKey=type \t Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n \t // other fields + \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: BuildStatusType const for the status 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 - log: - format: byte + phase: type: string type: object type: object served: true storage: true + subresources: {} status: acceptedNames: kind: "" diff --git a/config/crd/bases/crd.lagoon.sh_lagoontasks.yaml b/config/crd/bases/crd.lagoon.sh_lagoontasks.yaml index bdb06319..f3b67c4a 100644 --- a/config/crd/bases/crd.lagoon.sh_lagoontasks.yaml +++ b/config/crd/bases/crd.lagoon.sh_lagoontasks.yaml @@ -170,6 +170,10 @@ spec: properties: lastTransitionTime: type: string + message: + type: string + reason: + type: string status: type: string type: @@ -177,6 +181,8 @@ spec: type: string required: - lastTransitionTime + - message + - reason - status - type type: object @@ -663,7 +669,15 @@ spec: type: object served: true storage: false - - name: v1beta2 + - additionalPrinterColumns: + - description: Status of the LagoonTask + jsonPath: .status.phase + name: Status + type: string + - jsonPath: .metadata.creationTimestamp + name: Age + type: date + name: v1beta2 schema: openAPIV3Schema: description: LagoonTask is the Schema for the lagoontasks API @@ -804,33 +818,87 @@ spec: description: LagoonTaskStatus defines the observed state of LagoonTask properties: conditions: - description: 'INSERT ADDITIONAL STATUS FIELD - define observed state - of cluster Important: Run "make" to regenerate code after modifying - this file' + description: Conditions provide a standard mechanism for higher-level + status reporting from a controller. They are an extension mechanism + which allows tools and other controllers to collect summary information + about resources without needing to understand resource-specific + status details. items: - description: LagoonTaskConditions defines the observed conditions - of task pods. + 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 \ttype FooStatus struct{ \t // Represents the observations + of a foo's current state. \t // Known .status.conditions.type + are: \"Available\", \"Progressing\", and \"Degraded\" \t // + +patchMergeKey=type \t // +patchStrategy=merge \t // +listType=map + \t // +listMapKey=type \t Conditions []metav1.Condition + `json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\" + protobuf:\"bytes,1,rep,name=conditions\"` \n \t // other fields + \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: TaskStatusType const for the status 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 - log: - format: byte + phase: type: string type: object type: object served: true storage: true + subresources: {} status: acceptedNames: kind: "" diff --git a/config/manager/manager.yaml b/config/manager/manager.yaml index b6c85a52..93489562 100644 --- a/config/manager/manager.yaml +++ b/config/manager/manager.yaml @@ -30,9 +30,6 @@ spec: image: controller:latest name: manager resources: - limits: - cpu: 100m - memory: 30Mi requests: cpu: 100m memory: 20Mi diff --git a/controller-test.sh b/controller-test.sh index 7aa198e7..0da8fe52 100755 --- a/controller-test.sh +++ b/controller-test.sh @@ -26,6 +26,7 @@ HARBOR_VERSION=${HARBOR_VERSION:-1.6.4} check_controller_log () { echo "=========== CONTROLLER LOG ============" + kubectl logs $(kubectl get pods -n ${CONTROLLER_NAMESPACE} --no-headers | awk '{print $1}') -c manager -n ${CONTROLLER_NAMESPACE} --previous=true kubectl logs $(kubectl get pods -n ${CONTROLLER_NAMESPACE} --no-headers | awk '{print $1}') -c manager -n ${CONTROLLER_NAMESPACE} if $(kubectl logs $(kubectl get pods -n ${CONTROLLER_NAMESPACE} --no-headers | awk '{print $1}') -c manager -n ${CONTROLLER_NAMESPACE} | grep -q "Build ${1} Failed") then @@ -179,7 +180,7 @@ check_lagoon_build () { fi done echo "==> Build running" - kubectl -n ${NS} logs ${1} -f + # kubectl -n ${NS} logs ${1} -f } start_docker_compose_services diff --git a/controllers/v1beta2/build_controller.go b/controllers/v1beta2/build_controller.go index c33d0ded..476228fd 100644 --- a/controllers/v1beta2/build_controller.go +++ b/controllers/v1beta2/build_controller.go @@ -327,6 +327,9 @@ func (r *LagoonBuildReconciler) getOrCreateBuildResource(ctx context.Context, la "crd.lagoon.sh/version": crdVersion, }, ) + // all new builds start as "queued" but will transition to pending or running fairly quickly + // unless they are actually queued :D + newBuild.Status.Phase = "Queued" err := r.Get(ctx, types.NamespacedName{ Namespace: ns, Name: newBuild.ObjectMeta.Name, diff --git a/controllers/v1beta2/podmonitor_buildhandlers.go b/controllers/v1beta2/podmonitor_buildhandlers.go index a2b11b34..e5619998 100644 --- a/controllers/v1beta2/podmonitor_buildhandlers.go +++ b/controllers/v1beta2/podmonitor_buildhandlers.go @@ -16,8 +16,11 @@ import ( lagooncrd "github.com/uselagoon/remote-controller/apis/lagoon/v1beta2" "github.com/uselagoon/remote-controller/internal/helpers" "github.com/uselagoon/remote-controller/internal/metrics" + "golang.org/x/text/cases" + "golang.org/x/text/language" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" + meta "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/selection" @@ -147,7 +150,7 @@ func (r *LagoonMonitorReconciler) buildLogsToLagoonLogs( logs []byte, ) error { if r.EnableMQ { - buildStep := "running" + buildStep := "pending" if condition == "failed" || condition == "complete" || condition == "cancelled" { // set build step to anything other than running if the condition isn't running buildStep = condition @@ -237,7 +240,7 @@ func (r *LagoonMonitorReconciler) updateDeploymentAndEnvironmentTask( condition string, ) error { if r.EnableMQ { - buildStep := "running" + buildStep := "pending" if condition == "failed" || condition == "complete" || condition == "cancelled" { // set build step to anything other than running if the condition isn't running buildStep = condition @@ -382,7 +385,7 @@ func (r *LagoonMonitorReconciler) buildStatusLogsToLagoonLogs( condition string, ) error { if r.EnableMQ { - buildStep := "running" + buildStep := "pending" if condition == "failed" || condition == "complete" || condition == "cancelled" { // set build step to anything other than running if the condition isn't running buildStep = condition @@ -492,7 +495,7 @@ func (r *LagoonMonitorReconciler) updateDeploymentWithLogs( collectLogs = false } } - buildStep := "running" + buildStep := "pending" if value, ok := jobPod.Labels["lagoon.sh/buildStep"]; ok { buildStep = value } @@ -551,20 +554,19 @@ Build %s "lagoon.sh/buildStarted": "true", }, }, - "statusMessages": map[string]interface{}{}, } - - condition := lagooncrd.LagoonBuildConditions{ - Type: buildCondition, - Status: corev1.ConditionTrue, - LastTransitionTime: time.Now().UTC().Format(time.RFC3339), - } - if !lagooncrd.BuildContainsStatus(lagoonBuild.Status.Conditions, condition) { - lagoonBuild.Status.Conditions = append(lagoonBuild.Status.Conditions, condition) - mergeMap["status"] = map[string]interface{}{ - "conditions": lagoonBuild.Status.Conditions, - // don't save build logs in resource anymore - } + condition := metav1.Condition{ + Type: "BuildStep", + // Reason needs to be CamelCase not camelCase. Would need to update the `build-deploy-tool` to use CamelCase + // to eventually remove the need for `cases` + Reason: cases.Title(language.English, cases.NoLower).String(buildStep), + Status: metav1.ConditionTrue, + LastTransitionTime: metav1.NewTime(time.Now().UTC()), + } + _ = meta.SetStatusCondition(&lagoonBuild.Status.Conditions, condition) + mergeMap["status"] = map[string]interface{}{ + "conditions": lagoonBuild.Status.Conditions, + "phase": buildCondition.String(), } // get the configmap for lagoon-env so we can use it for updating the deployment in lagoon diff --git a/controllers/v1beta2/podmonitor_taskhandlers.go b/controllers/v1beta2/podmonitor_taskhandlers.go index 45b75027..a32e23fd 100644 --- a/controllers/v1beta2/podmonitor_taskhandlers.go +++ b/controllers/v1beta2/podmonitor_taskhandlers.go @@ -17,6 +17,7 @@ import ( "github.com/uselagoon/remote-controller/internal/helpers" "github.com/uselagoon/remote-controller/internal/metrics" corev1 "k8s.io/api/core/v1" + meta "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" ctrl "sigs.k8s.io/controller-runtime" @@ -334,20 +335,18 @@ Task %s "lagoon.sh/taskStatus": taskCondition.String(), }, }, - "statusMessages": map[string]interface{}{}, } - condition := lagooncrd.LagoonTaskConditions{ - Type: taskCondition, - Status: corev1.ConditionTrue, - LastTransitionTime: time.Now().UTC().Format(time.RFC3339), + condition := metav1.Condition{ + Reason: taskCondition.String(), + Type: "TaskCondition", + Status: metav1.ConditionTrue, + LastTransitionTime: metav1.NewTime(time.Now().UTC()), } - if !lagooncrd.TaskContainsStatus(lagoonTask.Status.Conditions, condition) { - lagoonTask.Status.Conditions = append(lagoonTask.Status.Conditions, condition) - mergeMap["status"] = map[string]interface{}{ - "conditions": lagoonTask.Status.Conditions, - // don't save build logs in resource anymore - } + _ = meta.SetStatusCondition(&lagoonTask.Status.Conditions, condition) + mergeMap["status"] = map[string]interface{}{ + "conditions": lagoonTask.Status.Conditions, + "phase": taskCondition.String(), } // send any messages to lagoon message queues diff --git a/internal/messenger/consumer.go b/internal/messenger/consumer.go index 28f3acac..1129b061 100644 --- a/internal/messenger/consumer.go +++ b/internal/messenger/consumer.go @@ -260,9 +260,10 @@ func (m *Messenger) Consumer(targetName string) { //error { job.ObjectMeta.Namespace = namespace job.SetLabels( map[string]string{ - "lagoon.sh/taskType": lagoonv1beta2.TaskTypeStandard.String(), - "lagoon.sh/taskStatus": lagoonv1beta2.TaskStatusPending.String(), - "lagoon.sh/controller": m.ControllerNamespace, + "lagoon.sh/taskType": lagoonv1beta2.TaskTypeStandard.String(), + "lagoon.sh/taskStatus": lagoonv1beta2.TaskStatusPending.String(), + "lagoon.sh/controller": m.ControllerNamespace, + "crd.lagoon.sh/version": "v1beta2", }, ) job.ObjectMeta.Name = fmt.Sprintf("lagoon-task-%s-%s", job.Spec.Task.ID, helpers.HashString(job.Spec.Task.ID)[0:6])