github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/controllers/apps/operations/util/common_util.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 util
    21  
    22  import (
    23  	"context"
    24  	"encoding/json"
    25  	"time"
    26  
    27  	"sigs.k8s.io/controller-runtime/pkg/client"
    28  
    29  	appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1"
    30  	dpv1alpha1 "github.com/1aal/kubeblocks/apis/dataprotection/v1alpha1"
    31  	intctrlutil "github.com/1aal/kubeblocks/pkg/constant"
    32  )
    33  
    34  func setOpsRequestToCluster(cluster *appsv1alpha1.Cluster, opsRequestSlice []appsv1alpha1.OpsRecorder) {
    35  	if cluster.Annotations == nil {
    36  		cluster.Annotations = map[string]string{}
    37  	}
    38  	if len(opsRequestSlice) > 0 {
    39  		result, _ := json.Marshal(opsRequestSlice)
    40  		cluster.Annotations[intctrlutil.OpsRequestAnnotationKey] = string(result)
    41  	} else {
    42  		delete(cluster.Annotations, intctrlutil.OpsRequestAnnotationKey)
    43  	}
    44  }
    45  
    46  // PatchClusterOpsAnnotations patches OpsRequest annotation in Cluster.annotations
    47  func PatchClusterOpsAnnotations(ctx context.Context,
    48  	cli client.Client,
    49  	cluster *appsv1alpha1.Cluster,
    50  	opsRequestSlice []appsv1alpha1.OpsRecorder) error {
    51  	patch := client.MergeFrom(cluster.DeepCopy())
    52  	setOpsRequestToCluster(cluster, opsRequestSlice)
    53  	return cli.Patch(ctx, cluster, patch)
    54  }
    55  
    56  // UpdateClusterOpsAnnotations updates OpsRequest annotation in Cluster.annotations
    57  func UpdateClusterOpsAnnotations(ctx context.Context,
    58  	cli client.Client,
    59  	cluster *appsv1alpha1.Cluster,
    60  	opsRequestSlice []appsv1alpha1.OpsRecorder) error {
    61  	setOpsRequestToCluster(cluster, opsRequestSlice)
    62  	return cli.Update(ctx, cluster)
    63  }
    64  
    65  // PatchOpsRequestReconcileAnnotation patches the reconcile annotation to OpsRequest
    66  func PatchOpsRequestReconcileAnnotation(ctx context.Context, cli client.Client, namespace string, opsRequestName string) error {
    67  	opsRequest := &appsv1alpha1.OpsRequest{}
    68  	if err := cli.Get(ctx, client.ObjectKey{Name: opsRequestName, Namespace: namespace}, opsRequest); err != nil {
    69  		return err
    70  	}
    71  	patch := client.MergeFrom(opsRequest.DeepCopy())
    72  	if opsRequest.Annotations == nil {
    73  		opsRequest.Annotations = map[string]string{}
    74  	}
    75  	// because many changes may be triggered within one second, if the accuracy is only in seconds, the event may be lost.
    76  	// so use nanoseconds to record the time.
    77  	opsRequest.Annotations[intctrlutil.ReconcileAnnotationKey] = time.Now().Format(time.RFC3339Nano)
    78  	return cli.Patch(ctx, opsRequest, patch)
    79  }
    80  
    81  // GetOpsRequestSliceFromCluster gets OpsRequest slice from cluster annotations.
    82  // this records what OpsRequests are running in cluster
    83  func GetOpsRequestSliceFromCluster(cluster *appsv1alpha1.Cluster) ([]appsv1alpha1.OpsRecorder, error) {
    84  	var (
    85  		opsRequestValue string
    86  		opsRequestSlice []appsv1alpha1.OpsRecorder
    87  		ok              bool
    88  	)
    89  	if cluster == nil || cluster.Annotations == nil {
    90  		return nil, nil
    91  	}
    92  	if opsRequestValue, ok = cluster.Annotations[intctrlutil.OpsRequestAnnotationKey]; !ok {
    93  		return nil, nil
    94  	}
    95  	// opsRequest annotation value in cluster to slice
    96  	if err := json.Unmarshal([]byte(opsRequestValue), &opsRequestSlice); err != nil {
    97  		return nil, err
    98  	}
    99  	return opsRequestSlice, nil
   100  }
   101  
   102  // GetOpsRequestFromBackup gets OpsRequest slice from cluster annotations.
   103  func GetOpsRequestFromBackup(backup *dpv1alpha1.Backup) *appsv1alpha1.OpsRecorder {
   104  	var (
   105  		opsRequestName string
   106  		opsRequestType string
   107  		ok             bool
   108  	)
   109  	if backup == nil || backup.Labels == nil {
   110  		return nil
   111  	}
   112  	if opsRequestName, ok = backup.Labels[intctrlutil.OpsRequestNameLabelKey]; !ok {
   113  		return nil
   114  	}
   115  	if opsRequestType, ok = backup.Labels[intctrlutil.OpsRequestTypeLabelKey]; !ok {
   116  		return nil
   117  	}
   118  	return &appsv1alpha1.OpsRecorder{
   119  		Name: opsRequestName,
   120  		Type: appsv1alpha1.OpsType(opsRequestType),
   121  	}
   122  }