github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/controllers/apps/configuration/config_reconcile_wrapper.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  	appv1 "k8s.io/api/apps/v1"
    24  	corev1 "k8s.io/api/core/v1"
    25  	"sigs.k8s.io/controller-runtime/pkg/client"
    26  
    27  	appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1"
    28  	workloads "github.com/1aal/kubeblocks/apis/workloads/v1alpha1"
    29  	"github.com/1aal/kubeblocks/controllers/apps/components"
    30  	cfgcore "github.com/1aal/kubeblocks/pkg/configuration/core"
    31  	intctrlutil "github.com/1aal/kubeblocks/pkg/controllerutil"
    32  	"github.com/1aal/kubeblocks/pkg/generics"
    33  )
    34  
    35  type configSpecList []appsv1alpha1.ComponentConfigSpec
    36  
    37  type configReconcileContext struct {
    38  	intctrlutil.ResourceFetcher[configReconcileContext]
    39  
    40  	Name           string
    41  	MatchingLabels client.MatchingLabels
    42  	ConfigSpec     *appsv1alpha1.ComponentConfigSpec
    43  	ConfigMap      *corev1.ConfigMap
    44  
    45  	Containers   []string
    46  	StatefulSets []appv1.StatefulSet
    47  	RSMList      []workloads.ReplicatedStateMachine
    48  	Deployments  []appv1.Deployment
    49  
    50  	ConfigConstraint *appsv1alpha1.ConfigConstraint
    51  }
    52  
    53  func newConfigReconcileContext(resourceCtx *intctrlutil.ResourceCtx,
    54  	cm *corev1.ConfigMap,
    55  	cc *appsv1alpha1.ConfigConstraint,
    56  	configSpecName string,
    57  	matchingLabels client.MatchingLabels) *configReconcileContext {
    58  	configContext := configReconcileContext{
    59  		ConfigMap:        cm,
    60  		ConfigConstraint: cc,
    61  		Name:             configSpecName,
    62  		MatchingLabels:   matchingLabels,
    63  	}
    64  	return configContext.Init(resourceCtx, &configContext)
    65  }
    66  
    67  func (l configSpecList) findByName(name string) *appsv1alpha1.ComponentConfigSpec {
    68  	for i := range l {
    69  		configSpec := &l[i]
    70  		if configSpec.Name == name {
    71  			return configSpec
    72  		}
    73  	}
    74  	return nil
    75  }
    76  
    77  func (c *configReconcileContext) GetRelatedObjects() error {
    78  	return c.Cluster().
    79  		ClusterDef().
    80  		ClusterVer().
    81  		ClusterComponent().
    82  		ClusterDefComponent().
    83  		RSM().
    84  		StatefulSet().
    85  		Deployment().
    86  		Complete()
    87  }
    88  
    89  func (c *configReconcileContext) StatefulSet() *configReconcileContext {
    90  	stsFn := func() (err error) {
    91  		dComp := c.ClusterDefComObj
    92  		if dComp == nil || dComp.WorkloadType == appsv1alpha1.Stateless || len(c.RSMList) != 0 {
    93  			return
    94  		}
    95  
    96  		c.StatefulSets, c.Containers, err = retrieveRelatedComponentsByConfigmap(
    97  			c.Client,
    98  			c.Context,
    99  			c.Name,
   100  			generics.StatefulSetSignature,
   101  			client.ObjectKeyFromObject(c.ConfigMap),
   102  			client.InNamespace(c.Namespace),
   103  			c.MatchingLabels)
   104  		return
   105  	}
   106  	return c.Wrap(stsFn)
   107  }
   108  
   109  func (c *configReconcileContext) RSM() *configReconcileContext {
   110  	stsFn := func() (err error) {
   111  		dComp := c.ClusterDefComObj
   112  		if dComp == nil {
   113  			return
   114  		}
   115  		c.RSMList, c.Containers, err = retrieveRelatedComponentsByConfigmap(
   116  			c.Client,
   117  			c.Context,
   118  			c.Name,
   119  			generics.RSMSignature,
   120  			client.ObjectKeyFromObject(c.ConfigMap),
   121  			client.InNamespace(c.Namespace),
   122  			c.MatchingLabels)
   123  		if err != nil {
   124  			return
   125  		}
   126  
   127  		// fix uid mismatch bug: convert rsm to sts
   128  		// NODE: all components use the StatefulSet
   129  		for _, rsm := range c.RSMList {
   130  			var stsObject appv1.StatefulSet
   131  			if err = c.Client.Get(c.Context, client.ObjectKeyFromObject(components.ConvertRSMToSTS(&rsm)), &stsObject); err != nil {
   132  				return
   133  			}
   134  			c.StatefulSets = append(c.StatefulSets, stsObject)
   135  		}
   136  		return
   137  	}
   138  	return c.Wrap(stsFn)
   139  }
   140  
   141  func (c *configReconcileContext) Deployment() *configReconcileContext {
   142  	deployFn := func() (err error) {
   143  		dComp := c.ClusterDefComObj
   144  		if dComp == nil || dComp.WorkloadType != appsv1alpha1.Stateless || len(c.RSMList) != 0 {
   145  			return
   146  		}
   147  
   148  		c.Deployments, c.Containers, err = retrieveRelatedComponentsByConfigmap(
   149  			c.Client,
   150  			c.Context,
   151  			c.Name,
   152  			generics.DeploymentSignature,
   153  			client.ObjectKeyFromObject(c.ConfigMap),
   154  			client.InNamespace(c.Namespace),
   155  			c.MatchingLabels)
   156  		return
   157  	}
   158  	return c.Wrap(deployFn)
   159  }
   160  
   161  func (c *configReconcileContext) Complete() (err error) {
   162  	err = c.Err
   163  	if err != nil {
   164  		return
   165  	}
   166  
   167  	var configSpecs configSpecList
   168  	if configSpecs, err = cfgcore.GetConfigTemplatesFromComponent(
   169  		c.clusterComponents(),
   170  		c.clusterDefComponents(),
   171  		c.clusterVerComponents(),
   172  		c.ComponentName); err != nil {
   173  		return
   174  	}
   175  	c.ConfigSpec = configSpecs.findByName(c.Name)
   176  	return
   177  }
   178  
   179  func (c *configReconcileContext) clusterComponents() []appsv1alpha1.ClusterComponentSpec {
   180  	return c.ClusterObj.Spec.ComponentSpecs
   181  }
   182  
   183  func (c *configReconcileContext) clusterDefComponents() []appsv1alpha1.ClusterComponentDefinition {
   184  	return c.ClusterDefObj.Spec.ComponentDefs
   185  }
   186  
   187  func (c *configReconcileContext) clusterVerComponents() []appsv1alpha1.ClusterComponentVersion {
   188  	if c.ClusterVerObj == nil {
   189  		return nil
   190  	}
   191  	return c.ClusterVerObj.Spec.ComponentVersions
   192  }