github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/controllers/apps/cluster_status_conditions.go (about) 1 /* 2 Copyright (C) 2022-2023 ApeCloud Co., Ltd 3 4 This file is part of KubeBlocks project 5 6 This program is free software: you can redistribute it and/or modify 7 it under the terms of the GNU Affero General Public License as published by 8 the Free Software Foundation, either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU Affero General Public License for more details. 15 16 You should have received a copy of the GNU Affero General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 package apps 21 22 import ( 23 "fmt" 24 25 "golang.org/x/exp/maps" 26 "golang.org/x/exp/slices" 27 "k8s.io/apimachinery/pkg/api/meta" 28 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 29 30 appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1" 31 intctrlutil "github.com/1aal/kubeblocks/pkg/controllerutil" 32 ) 33 34 const ( 35 ReasonPreCheckSucceed = "PreCheckSucceed" // ReasonPreCheckSucceed preChecks succeeded for provisioning started 36 ReasonPreCheckFailed = "PreCheckFailed" // ReasonPreCheckFailed preChecks failed for provisioning started 37 ReasonApplyResourcesFailed = "ApplyResourcesFailed" // ReasonApplyResourcesFailed applies resources failed to create or change the cluster 38 ReasonApplyResourcesSucceed = "ApplyResourcesSucceed" // ReasonApplyResourcesSucceed applies resources succeeded to create or change the cluster 39 ReasonReplicasNotReady = "ReplicasNotReady" // ReasonReplicasNotReady the pods of components are not ready 40 ReasonAllReplicasReady = "AllReplicasReady" // ReasonAllReplicasReady the pods of components are ready 41 ReasonComponentsNotReady = "ComponentsNotReady" // ReasonComponentsNotReady the components of cluster are not ready 42 ReasonClusterReady = "ClusterReady" // ReasonClusterReady the components of cluster are ready, the component phase is running 43 ) 44 45 func setProvisioningStartedCondition(conditions *[]metav1.Condition, clusterName string, clusterGeneration int64, err error) { 46 var condition metav1.Condition 47 if err == nil { 48 condition = newProvisioningStartedCondition(clusterName, clusterGeneration) 49 } else { 50 condition = newFailedProvisioningStartedCondition(err) 51 } 52 meta.SetStatusCondition(conditions, condition) 53 } 54 55 // newProvisioningStartedCondition creates the provisioning started condition in cluster conditions. 56 func newProvisioningStartedCondition(clusterName string, clusterGeneration int64) metav1.Condition { 57 return metav1.Condition{ 58 Type: appsv1alpha1.ConditionTypeProvisioningStarted, 59 ObservedGeneration: clusterGeneration, 60 Status: metav1.ConditionTrue, 61 Message: fmt.Sprintf("The operator has started the provisioning of Cluster: %s", clusterName), 62 Reason: ReasonPreCheckSucceed, 63 } 64 } 65 66 func getConditionReasonWithError(defaultReason string, err error) string { 67 if err == nil { 68 return defaultReason 69 } 70 controllerErr := intctrlutil.UnwrapControllerError(err) 71 if controllerErr != nil { 72 defaultReason = string(controllerErr.Type) 73 } 74 return defaultReason 75 } 76 77 // newApplyResourcesCondition creates a condition when applied resources succeed. 78 func newFailedProvisioningStartedCondition(err error) metav1.Condition { 79 return metav1.Condition{ 80 Type: appsv1alpha1.ConditionTypeProvisioningStarted, 81 Status: metav1.ConditionFalse, 82 Message: err.Error(), 83 Reason: getConditionReasonWithError(ReasonPreCheckFailed, err), 84 } 85 } 86 87 func setApplyResourceCondition(conditions *[]metav1.Condition, clusterGeneration int64, err error) { 88 condition := newApplyResourcesCondition(clusterGeneration) 89 // ignore requeue error 90 if err != nil && !intctrlutil.IsRequeueError(err) { 91 condition = newFailedApplyResourcesCondition(err) 92 } 93 meta.SetStatusCondition(conditions, condition) 94 } 95 96 // newApplyResourcesCondition creates a condition when applied resources succeed. 97 func newApplyResourcesCondition(clusterGeneration int64) metav1.Condition { 98 return metav1.Condition{ 99 Type: appsv1alpha1.ConditionTypeApplyResources, 100 ObservedGeneration: clusterGeneration, 101 Status: metav1.ConditionTrue, 102 Message: "Successfully applied for resources", 103 Reason: ReasonApplyResourcesSucceed, 104 } 105 } 106 107 // newApplyResourcesCondition creates a condition when applied resources succeed. 108 func newFailedApplyResourcesCondition(err error) metav1.Condition { 109 return metav1.Condition{ 110 Type: appsv1alpha1.ConditionTypeApplyResources, 111 Status: metav1.ConditionFalse, 112 Message: err.Error(), 113 Reason: getConditionReasonWithError(ReasonApplyResourcesFailed, err), 114 } 115 } 116 117 // newAllReplicasPodsReadyConditions creates a condition when all pods of components are ready 118 func newAllReplicasPodsReadyConditions() metav1.Condition { 119 return metav1.Condition{ 120 Type: appsv1alpha1.ConditionTypeReplicasReady, 121 Status: metav1.ConditionTrue, 122 Message: "all pods of components are ready, waiting for the probe detection successful", 123 Reason: ReasonAllReplicasReady, 124 } 125 } 126 127 // newReplicasNotReadyCondition creates a condition when pods of components are not ready 128 func newReplicasNotReadyCondition(notReadyComponentNames map[string]struct{}) metav1.Condition { 129 cNameSlice := maps.Keys(notReadyComponentNames) 130 slices.Sort(cNameSlice) 131 return metav1.Condition{ 132 Type: appsv1alpha1.ConditionTypeReplicasReady, 133 Status: metav1.ConditionFalse, 134 Message: fmt.Sprintf("pods are not ready in Components: %v, refer to related component message in Cluster.status.components", cNameSlice), 135 Reason: ReasonReplicasNotReady, 136 } 137 } 138 139 // newClusterReadyCondition creates a condition when all components of cluster are running 140 func newClusterReadyCondition(clusterName string) metav1.Condition { 141 return metav1.Condition{ 142 Type: appsv1alpha1.ConditionTypeReady, 143 Status: metav1.ConditionTrue, 144 Message: fmt.Sprintf("Cluster: %s is ready, current phase is Running", clusterName), 145 Reason: ReasonClusterReady, 146 } 147 } 148 149 // newComponentsNotReadyCondition creates a condition when components of cluster are not ready 150 func newComponentsNotReadyCondition(notReadyComponentNames map[string]struct{}) metav1.Condition { 151 cNameSlice := maps.Keys(notReadyComponentNames) 152 slices.Sort(cNameSlice) 153 return metav1.Condition{ 154 Type: appsv1alpha1.ConditionTypeReady, 155 Status: metav1.ConditionFalse, 156 Message: fmt.Sprintf("pods are unavailable in Components: %v, refer to related component message in Cluster.status.components", cNameSlice), 157 Reason: ReasonComponentsNotReady, 158 } 159 }