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  }