github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/controllers/apps/configuration/sync_upgrade_policy.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 "fmt" 24 25 corev1 "k8s.io/api/core/v1" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/apimachinery/pkg/labels" 28 29 appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1" 30 "github.com/1aal/kubeblocks/pkg/configuration/core" 31 podutil "github.com/1aal/kubeblocks/pkg/controllerutil" 32 ) 33 34 type syncPolicy struct { 35 } 36 37 func init() { 38 RegisterPolicy(appsv1alpha1.OperatorSyncUpdate, &syncPolicy{}) 39 } 40 41 func (o *syncPolicy) GetPolicyName() string { 42 return string(appsv1alpha1.OperatorSyncUpdate) 43 } 44 45 func (o *syncPolicy) Upgrade(params reconfigureParams) (ReturnedStatus, error) { 46 configPatch := params.ConfigPatch 47 if !configPatch.IsModify { 48 return makeReturnedStatus(ESNone), nil 49 } 50 51 updatedParameters := getOnlineUpdateParams(configPatch, params.ConfigConstraint.FormatterConfig) 52 if len(updatedParameters) == 0 { 53 return makeReturnedStatus(ESNone), nil 54 } 55 56 var funcs RollingUpgradeFuncs 57 switch params.WorkloadType() { 58 default: 59 return makeReturnedStatus(ESNotSupport), core.MakeError("not support component workload type[%s]", params.WorkloadType()) 60 case appsv1alpha1.Stateless: 61 funcs = GetDeploymentRollingUpgradeFuncs() 62 case appsv1alpha1.Consensus: 63 funcs = GetConsensusRollingUpgradeFuncs() 64 case appsv1alpha1.Stateful: 65 funcs = GetStatefulSetRollingUpgradeFuncs() 66 case appsv1alpha1.Replication: 67 funcs = GetReplicationRollingUpgradeFuncs() 68 } 69 70 pods, err := funcs.GetPodsFunc(params) 71 if err != nil { 72 return makeReturnedStatus(ESFailedAndRetry), err 73 } 74 return sync(params, updatedParameters, pods, funcs) 75 } 76 77 func matchLabel(pods []corev1.Pod, selector *metav1.LabelSelector) ([]corev1.Pod, error) { 78 var result []corev1.Pod 79 80 match, err := metav1.LabelSelectorAsSelector(selector) 81 if err != nil { 82 return nil, core.WrapError(err, "failed to convert selector: %v", selector) 83 } 84 for _, pod := range pods { 85 if match.Matches(labels.Set(pod.Labels)) { 86 result = append(result, pod) 87 } 88 } 89 return result, nil 90 } 91 92 func sync(params reconfigureParams, updatedParameters map[string]string, pods []corev1.Pod, funcs RollingUpgradeFuncs) (ReturnedStatus, error) { 93 var ( 94 r = ESNone 95 total = int32(len(pods)) 96 replicas = int32(params.getTargetReplicas()) 97 progress = core.NotStarted 98 99 err error 100 ctx = params.Ctx.Ctx 101 configKey = params.getConfigKey() 102 versionHash = params.getTargetVersionHash() 103 ) 104 105 if params.ConfigConstraint.Selector != nil { 106 pods, err = matchLabel(pods, params.ConfigConstraint.Selector) 107 } 108 if err != nil { 109 return makeReturnedStatus(ESFailedAndRetry), err 110 } 111 if len(pods) == 0 { 112 params.Ctx.Log.Info(fmt.Sprintf("no pods to update, and retry, selector: %s", params.ConfigConstraint.Selector.String())) 113 return makeReturnedStatus(ESRetry), nil 114 } 115 116 requireUpdatedCount := int32(len(pods)) 117 for _, pod := range pods { 118 params.Ctx.Log.V(1).Info(fmt.Sprintf("sync pod: %s", pod.Name)) 119 if podutil.IsMatchConfigVersion(&pod, configKey, versionHash) { 120 progress++ 121 continue 122 } 123 if !podutil.PodIsReady(&pod) { 124 continue 125 } 126 err = funcs.OnlineUpdatePodFunc(&pod, ctx, params.ReconfigureClientFactory, params.ConfigSpecName, updatedParameters) 127 if err != nil { 128 return makeReturnedStatus(ESFailedAndRetry), err 129 } 130 err = updatePodLabelsWithConfigVersion(&pod, configKey, versionHash, params.Client, ctx) 131 if err != nil { 132 return makeReturnedStatus(ESFailedAndRetry), err 133 } 134 progress++ 135 } 136 137 if requireUpdatedCount != progress || replicas != total { 138 r = ESRetry 139 } 140 return makeReturnedStatus(r, withExpected(requireUpdatedCount), withSucceed(progress)), nil 141 } 142 143 func getOnlineUpdateParams(configPatch *core.ConfigPatchInfo, formatConfig *appsv1alpha1.FormatterConfig) map[string]string { 144 r := make(map[string]string) 145 parameters := core.GenerateVisualizedParamsList(configPatch, formatConfig, nil) 146 for _, key := range parameters { 147 if key.UpdateType == core.UpdatedType { 148 for _, p := range key.Parameters { 149 if p.Value != nil { 150 r[p.Key] = *p.Value 151 } 152 } 153 } 154 } 155 return r 156 }