From 81f8bb14e40744baa8315a24174a7adec8c764d6 Mon Sep 17 00:00:00 2001 From: Rory Z Date: Thu, 28 Jul 2022 22:18:32 +0800 Subject: [PATCH] chore: update describe for status field --- apis/apps/v2alpha1/emqx_types.go | 51 ++++++++++------ apis/apps/v2alpha1/zz_generated.deepcopy.go | 36 +++++------ config/crd/bases/apps.emqx.io_emqxes.yaml | 12 +++- controllers/apps/v2alpha1/emqx_controller.go | 64 ++++++++++---------- e2e/v2alpha1/e2e_test.go | 28 +++------ 5 files changed, 99 insertions(+), 92 deletions(-) diff --git a/apis/apps/v2alpha1/emqx_types.go b/apis/apps/v2alpha1/emqx_types.go index 001ef6c21..ea02834d2 100644 --- a/apis/apps/v2alpha1/emqx_types.go +++ b/apis/apps/v2alpha1/emqx_types.go @@ -110,35 +110,44 @@ const ( ) type Condition struct { - Type ConditionType `json:"type"` - Status corev1.ConditionStatus `json:"status"` - LastUpdateTime string `json:"lastUpdateTime,omitempty"` - LastUpdateAt metav1.Time `json:"-"` - LastTransitionTime string `json:"lastTransitionTime,omitempty"` + // Status of cluster condition. + Type ConditionType `json:"type"` + // Status of the condition, one of True, False, Unknown. + Status corev1.ConditionStatus `json:"status"` // The reason for the condition's last transition. Reason string `json:"reason,omitempty"` // A human readable message indicating details about the transition. Message string `json:"message,omitempty"` + // Last time the condition transitioned from one status to another. + LastTransitionTime string `json:"lastTransitionTime,omitempty"` + // The last time this condition was updated. + LastUpdateTime string `json:"lastUpdateTime,omitempty"` + LastUpdateAt metav1.Time `json:"-"` } -type EMQXNodeStatus struct { - Node string `json:"node,omitempty"` +type EmqxNode struct { + // EMQX node name, example: emqx@127.0.0.1 + Node string `json:"node,omitempty"` + // EMQX node status, example: Running NodeStatus string `json:"node_status,omitempty"` + // Erlang/OTP version used by EMQX, example: 24.2/12.2 OTPRelease string `json:"otp_release,omitempty"` - Version string `json:"version,omitempty"` - Role string `json:"role,omitempty"` + // EMQX version + Version string `json:"version,omitempty"` + // EMQX cluster node role + Role string `json:"role,omitempty"` } // EMQXStatus defines the observed state of EMQX type EMQXStatus struct { - CurrentImage string `json:"currentImage,omitempty"` - OriginalImage string `json:"originalImage,omitempty"` - CoreReplicas int32 `json:"coreReplicas,omitempty"` - ReadyCoreReplicas int32 `json:"readyCoreReplicas,omitempty"` - ReplicantReplicas int32 `json:"replicantReplicas,omitempty"` - ReadyReplicantReplicas int32 `json:"readyReplicantReplicas,omitempty"` - NodeStatuses []EMQXNodeStatus `json:"nodes,omitempty"` - Conditions []Condition `json:"conditions,omitempty"` + CurrentImage string `json:"currentImage,omitempty"` + OriginalImage string `json:"originalImage,omitempty"` + CoreReplicas int32 `json:"coreReplicas,omitempty"` + ReadyCoreReplicas int32 `json:"readyCoreReplicas,omitempty"` + ReplicantReplicas int32 `json:"replicantReplicas,omitempty"` + ReadyReplicantReplicas int32 `json:"readyReplicantReplicas,omitempty"` + EmqxNodes []EmqxNode `json:"emqxNodes,omitempty"` + Conditions []Condition `json:"conditions,omitempty"` } //+kubebuilder:object:root=true @@ -192,9 +201,11 @@ func (s *EMQXStatus) IsCoreUpdating() bool { } func (s *EMQXStatus) IsRunning() bool { - cond := s.Conditions[0] - if cond.Type == ClusterRunning && cond.Status == corev1.ConditionTrue { - return true + if len(s.Conditions) > 0 { + cond := s.Conditions[0] + if cond.Type == ClusterRunning && cond.Status == corev1.ConditionTrue { + return true + } } return false } diff --git a/apis/apps/v2alpha1/zz_generated.deepcopy.go b/apis/apps/v2alpha1/zz_generated.deepcopy.go index e0354c939..97ea3e1f6 100644 --- a/apis/apps/v2alpha1/zz_generated.deepcopy.go +++ b/apis/apps/v2alpha1/zz_generated.deepcopy.go @@ -212,21 +212,6 @@ func (in *EMQXList) DeepCopyObject() runtime.Object { return nil } -// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. -func (in *EMQXNodeStatus) DeepCopyInto(out *EMQXNodeStatus) { - *out = *in -} - -// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EMQXNodeStatus. -func (in *EMQXNodeStatus) DeepCopy() *EMQXNodeStatus { - if in == nil { - return nil - } - out := new(EMQXNodeStatus) - in.DeepCopyInto(out) - return out -} - // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EMQXReplicantTemplate) DeepCopyInto(out *EMQXReplicantTemplate) { *out = *in @@ -369,9 +354,9 @@ func (in *EMQXSpec) DeepCopy() *EMQXSpec { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *EMQXStatus) DeepCopyInto(out *EMQXStatus) { *out = *in - if in.NodeStatuses != nil { - in, out := &in.NodeStatuses, &out.NodeStatuses - *out = make([]EMQXNodeStatus, len(*in)) + if in.EmqxNodes != nil { + in, out := &in.EmqxNodes, &out.EmqxNodes + *out = make([]EmqxNode, len(*in)) copy(*out, *in) } if in.Conditions != nil { @@ -393,6 +378,21 @@ func (in *EMQXStatus) DeepCopy() *EMQXStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *EmqxNode) DeepCopyInto(out *EmqxNode) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new EmqxNode. +func (in *EmqxNode) DeepCopy() *EmqxNode { + if in == nil { + return nil + } + out := new(EmqxNode) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *ServiceTemplate) DeepCopyInto(out *ServiceTemplate) { *out = *in diff --git a/config/crd/bases/apps.emqx.io_emqxes.yaml b/config/crd/bases/apps.emqx.io_emqxes.yaml index 6b0ce5f03..65468384d 100644 --- a/config/crd/bases/apps.emqx.io_emqxes.yaml +++ b/config/crd/bases/apps.emqx.io_emqxes.yaml @@ -13199,8 +13199,11 @@ spec: items: properties: lastTransitionTime: + description: Last time the condition transitioned from one status + to another. type: string lastUpdateTime: + description: The last time this condition was updated. type: string message: description: A human readable message indicating details about @@ -13210,8 +13213,10 @@ spec: description: The reason for the condition's last transition. type: string status: + description: Status of the condition, one of True, False, Unknown. type: string type: + description: Status of cluster condition. type: string required: - status @@ -13223,18 +13228,23 @@ spec: type: integer currentImage: type: string - nodes: + emqxNodes: items: properties: node: + description: 'EMQX node name, example: emqx@127.0.0.1' type: string node_status: + description: 'EMQX node status, example: Running' type: string otp_release: + description: 'Erlang/OTP version used by EMQX, example: 24.2/12.2' type: string role: + description: EMQX cluster node role type: string version: + description: EMQX version type: string type: object type: array diff --git a/controllers/apps/v2alpha1/emqx_controller.go b/controllers/apps/v2alpha1/emqx_controller.go index ef117f27b..96ebc485c 100644 --- a/controllers/apps/v2alpha1/emqx_controller.go +++ b/controllers/apps/v2alpha1/emqx_controller.go @@ -176,78 +176,76 @@ func (r *EMQXReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl. } } - readyCoreReplicas := int32(0) - readyReplicantReplicas := int32(0) - nodeStatuses, err := r.getNodeStatuesByAPI(sts) + instance.Status.CoreReplicas = *instance.Spec.CoreTemplate.Spec.Replicas + if isExistReplicant(instance) { + instance.Status.ReplicantReplicas = *instance.Spec.ReplicantTemplate.Spec.Replicas + } else { + instance.Status.ReplicantReplicas = int32(0) + } + instance.Status.ReadyCoreReplicas = int32(0) + instance.Status.ReadyReplicantReplicas = int32(0) + + emqxNodes, err := r.getNodeStatuesByAPI(sts) if err != nil { r.EventRecorder.Event(instance, corev1.EventTypeWarning, "FailedToGetNodeStatues", err.Error()) } - if nodeStatuses != nil { - instance.Status.NodeStatuses = nodeStatuses + if emqxNodes != nil { + instance.Status.EmqxNodes = emqxNodes - for _, node := range nodeStatuses { + for _, node := range emqxNodes { if node.NodeStatus == "Running" { if node.Role == "core" { - readyCoreReplicas++ + instance.Status.ReadyCoreReplicas++ } if node.Role == "replicant" { - readyReplicantReplicas++ + instance.Status.ReadyReplicantReplicas++ } } } } - instance.Status.CoreReplicas = *instance.Spec.CoreTemplate.Spec.Replicas - instance.Status.ReadyCoreReplicas = readyCoreReplicas - if isExistReplicant(instance) { - instance.Status.ReplicantReplicas = *instance.Spec.ReplicantTemplate.Spec.Replicas - instance.Status.ReadyReplicantReplicas = readyReplicantReplicas - } - switch instance.Status.Conditions[0].Type { case appsv2alpha1.ClusterCoreUpdating: if instance.Status.ReadyCoreReplicas == instance.Status.CoreReplicas { instance.Status.OriginalImage = instance.Status.CurrentImage + + var condition *appsv2alpha1.Condition if isExistReplicant(instance) { - condition := appsv2alpha1.NewCondition( + condition = appsv2alpha1.NewCondition( appsv2alpha1.ClusterReplicantUpdating, corev1.ConditionTrue, "ClusterReplicantUpdating", "Updating replicant node in cluster", ) - instance.Status.SetCondition(*condition) } else { - condition := appsv2alpha1.NewCondition( + condition = appsv2alpha1.NewCondition( appsv2alpha1.ClusterRunning, corev1.ConditionTrue, "ClusterReady", "All node are ready", ) - instance.Status.SetCondition(*condition) } - } - case appsv2alpha1.ClusterRunning: - if instance.Status.CoreReplicas != instance.Status.ReadyCoreReplicas || - instance.Status.ReadyCoreReplicas != instance.Status.ReadyReplicantReplicas { - condition := appsv2alpha1.NewCondition( - appsv2alpha1.ClusterRunning, - corev1.ConditionFalse, - "ClusterNotReady", - "Some node not ready", - ) instance.Status.SetCondition(*condition) } default: + var condition *appsv2alpha1.Condition if instance.Status.CoreReplicas == instance.Status.ReadyCoreReplicas && instance.Status.ReplicantReplicas == instance.Status.ReadyReplicantReplicas { - condition := appsv2alpha1.NewCondition( + condition = appsv2alpha1.NewCondition( appsv2alpha1.ClusterRunning, corev1.ConditionTrue, "ClusterReady", "All node are ready", ) - instance.Status.SetCondition(*condition) + } else { + condition = appsv2alpha1.NewCondition( + appsv2alpha1.ClusterRunning, + corev1.ConditionFalse, + "ClusterNotReady", + "Some node not ready", + ) } + instance.Status.SetCondition(*condition) } // Check cluster status @@ -265,7 +263,7 @@ func (r *EMQXReconciler) SetupWithManager(mgr ctrl.Manager) error { Complete(r) } -func (r *EMQXReconciler) getNodeStatuesByAPI(obj client.Object) ([]appsv2alpha1.EMQXNodeStatus, error) { +func (r *EMQXReconciler) getNodeStatuesByAPI(obj client.Object) ([]appsv2alpha1.EmqxNode, error) { resp, body, err := r.Handler.RequestAPI(obj, "GET", username, password, dashboardPort, "api/v5/nodes") if err != nil { return nil, fmt.Errorf("failed to get listeners: %v", err) @@ -274,7 +272,7 @@ func (r *EMQXReconciler) getNodeStatuesByAPI(obj client.Object) ([]appsv2alpha1. return nil, fmt.Errorf("failed to get listener, status : %s, body: %s", resp.Status, body) } - nodeStatuses := []appsv2alpha1.EMQXNodeStatus{} + nodeStatuses := []appsv2alpha1.EmqxNode{} if err := json.Unmarshal(body, &nodeStatuses); err != nil { return nil, fmt.Errorf("failed to unmarshal node statuses: %v", err) } diff --git a/e2e/v2alpha1/e2e_test.go b/e2e/v2alpha1/e2e_test.go index 046dd665d..43364915a 100644 --- a/e2e/v2alpha1/e2e_test.go +++ b/e2e/v2alpha1/e2e_test.go @@ -70,18 +70,12 @@ var _ = Describe("E2E Test", func() { Expect(k8sClient.Create(context.TODO(), instance)).Should(Succeed()) }) It("Check EMQX Status", func() { - Eventually(func() corev1.ConditionStatus { + Eventually(func() bool { _ = k8sClient.Get(context.TODO(), types.NamespacedName{Name: "e2e-test", Namespace: "default"}, instance) - running := corev1.ConditionFalse - for _, c := range instance.Status.Conditions { - if c.Type == appsv2alpha1.ClusterRunning { - running = c.Status - } - } - return running - }, timeout, interval).Should(Equal(corev1.ConditionTrue)) + return instance.Status.IsRunning() + }, timeout, interval).Should(BeTrue()) - Expect(instance.Status.NodeStatuses).Should(HaveLen(3)) + Expect(instance.Status.EmqxNodes).Should(HaveLen(3)) Expect(instance.Status.CoreReplicas).Should(Equal(int32(3))) Expect(instance.Status.ReadyCoreReplicas).Should(Equal(int32(3))) Expect(instance.Status.ReplicantReplicas).Should(Equal(int32(0))) @@ -121,18 +115,12 @@ var _ = Describe("E2E Test", func() { Expect(k8sClient.Create(context.TODO(), instance)).Should(Succeed()) }) It("Check EMQX Status", func() { - Eventually(func() corev1.ConditionStatus { + Eventually(func() bool { _ = k8sClient.Get(context.TODO(), types.NamespacedName{Name: "e2e-test", Namespace: "default"}, instance) - running := corev1.ConditionFalse - for _, c := range instance.Status.Conditions { - if c.Type == appsv2alpha1.ClusterRunning { - running = c.Status - } - } - return running - }, timeout, interval).Should(Equal(corev1.ConditionTrue)) + return instance.Status.IsRunning() + }, timeout, interval).Should(BeTrue()) - Expect(instance.Status.NodeStatuses).Should(HaveLen(6)) + Expect(instance.Status.EmqxNodes).Should(HaveLen(6)) Expect(instance.Status.CoreReplicas).Should(Equal(int32(3))) Expect(instance.Status.ReadyCoreReplicas).Should(Equal(int32(3))) Expect(instance.Status.ReplicantReplicas).Should(Equal(int32(3)))