github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/controllers/apps/configuration/config_related_helper.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 configuration
    21  
    22  import (
    23  	"context"
    24  	"reflect"
    25  
    26  	appv1 "k8s.io/api/apps/v1"
    27  	corev1 "k8s.io/api/core/v1"
    28  	"sigs.k8s.io/controller-runtime/pkg/client"
    29  
    30  	workloads "github.com/1aal/kubeblocks/apis/workloads/v1alpha1"
    31  	"github.com/1aal/kubeblocks/pkg/configuration/core"
    32  	cfgutil "github.com/1aal/kubeblocks/pkg/configuration/util"
    33  	"github.com/1aal/kubeblocks/pkg/constant"
    34  	intctrlutil "github.com/1aal/kubeblocks/pkg/controllerutil"
    35  	"github.com/1aal/kubeblocks/pkg/generics"
    36  )
    37  
    38  func retrieveRelatedComponentsByConfigmap[T generics.Object, PT generics.PObject[T], L generics.ObjList[T], PL generics.PObjList[T, L]](cli client.Client, ctx context.Context, configSpecName string, _ func(T, PT, L, PL), cfg client.ObjectKey, opts ...client.ListOption) ([]T, []string, error) {
    39  	var objList L
    40  	if err := cli.List(ctx, PL(&objList), opts...); err != nil {
    41  		return nil, nil, err
    42  	}
    43  
    44  	objs := make([]T, 0)
    45  	containers := cfgutil.NewSet()
    46  	configSpecKey := core.GenerateTPLUniqLabelKeyWithConfig(configSpecName)
    47  	items := toObjects[T, L, PL](&objList)
    48  	for i := range items {
    49  		obj := toResourceObject(&items[i])
    50  		if objs == nil {
    51  			return nil, nil, core.MakeError("failed to convert to resource object")
    52  		}
    53  		if !foundComponentConfigSpec(obj.GetAnnotations(), configSpecKey, cfg.Name) {
    54  			continue
    55  		}
    56  		podTemplate := transformPodTemplate(obj)
    57  		if podTemplate == nil {
    58  			continue
    59  		}
    60  		volumeMounted := intctrlutil.GetVolumeMountName(podTemplate.Spec.Volumes, cfg.Name)
    61  		if volumeMounted == nil {
    62  			continue
    63  		}
    64  		// filter config manager sidecar container
    65  		contains := intctrlutil.GetContainersByConfigmap(podTemplate.Spec.Containers,
    66  			volumeMounted.Name, core.GenerateEnvFromName(cfg.Name),
    67  			func(containerName string) bool {
    68  				return constant.ConfigSidecarName == containerName
    69  			})
    70  		if len(contains) > 0 {
    71  			objs = append(objs, items[i])
    72  			containers.Add(contains...)
    73  		}
    74  	}
    75  	return objs, containers.AsSlice(), nil
    76  }
    77  
    78  func transformPodTemplate(obj client.Object) *corev1.PodTemplateSpec {
    79  	switch v := obj.(type) {
    80  	default:
    81  		return nil
    82  	case *appv1.StatefulSet:
    83  		return &v.Spec.Template
    84  	case *appv1.Deployment:
    85  		return &v.Spec.Template
    86  	case *workloads.ReplicatedStateMachine:
    87  		return &v.Spec.Template
    88  	}
    89  }
    90  
    91  func toObjects[T generics.Object, L generics.ObjList[T], PL generics.PObjList[T, L]](compList PL) []T {
    92  	return reflect.ValueOf(compList).Elem().FieldByName("Items").Interface().([]T)
    93  }
    94  
    95  func toResourceObject(obj any) client.Object {
    96  	return obj.(client.Object)
    97  }
    98  
    99  func foundComponentConfigSpec(annotations map[string]string, key, value string) bool {
   100  	return len(annotations) != 0 && annotations[key] == value
   101  }