github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/controllers/apps/configuration/reconcile_task.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 "strconv" 24 25 corev1 "k8s.io/api/core/v1" 26 27 appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1" 28 "github.com/1aal/kubeblocks/pkg/configuration/core" 29 cfgutil "github.com/1aal/kubeblocks/pkg/configuration/util" 30 "github.com/1aal/kubeblocks/pkg/controller/component" 31 "github.com/1aal/kubeblocks/pkg/controller/configuration" 32 intctrlutil "github.com/1aal/kubeblocks/pkg/controllerutil" 33 ) 34 35 type Task struct { 36 intctrlutil.ResourceFetcher[Task] 37 38 Status *appsv1alpha1.ConfigurationItemDetailStatus 39 Name string 40 41 Do func(fetcher *Task, component *component.SynthesizedComponent, revision string) error 42 } 43 44 type TaskContext struct { 45 configuration *appsv1alpha1.Configuration 46 reqCtx intctrlutil.RequestCtx 47 fetcher *Task 48 } 49 50 func NewTask(item appsv1alpha1.ConfigurationItemDetail, status *appsv1alpha1.ConfigurationItemDetailStatus) Task { 51 return Task{ 52 Name: item.Name, 53 Do: func(fetcher *Task, synComponent *component.SynthesizedComponent, revision string) error { 54 configSpec := item.ConfigSpec 55 if configSpec == nil { 56 return core.MakeError("not found config spec: %s", item.Name) 57 } 58 if err := fetcher.ConfigMap(item.Name).Complete(); err != nil { 59 return err 60 } 61 // Do reconcile for config template 62 configMap := fetcher.ConfigMapObj 63 switch intctrlutil.GetConfigSpecReconcilePhase(configMap, item, status) { 64 default: 65 return syncStatus(configMap, status) 66 case appsv1alpha1.CPendingPhase, 67 appsv1alpha1.CMergeFailedPhase: 68 return syncImpl(fetcher, item, status, synComponent, revision, configSpec) 69 case appsv1alpha1.CCreatingPhase: 70 return nil 71 } 72 }, 73 Status: status, 74 } 75 } 76 77 func syncImpl(fetcher *Task, 78 item appsv1alpha1.ConfigurationItemDetail, 79 status *appsv1alpha1.ConfigurationItemDetailStatus, 80 component *component.SynthesizedComponent, 81 revision string, 82 configSpec *appsv1alpha1.ComponentConfigSpec) (err error) { 83 err = configuration.NewReconcilePipeline(configuration.ReconcileCtx{ 84 ResourceCtx: fetcher.ResourceCtx, 85 Cluster: fetcher.ClusterObj, 86 ClusterVer: fetcher.ClusterVerObj, 87 Component: component, 88 PodSpec: component.PodSpec, 89 }, item, status, configSpec). 90 ConfigMap(item.Name). 91 ConfigConstraints(configSpec.ConfigConstraintRef). 92 PrepareForTemplate(). 93 RerenderTemplate(). 94 ApplyParameters(). 95 UpdateConfigVersion(revision). 96 Sync(). 97 Complete() 98 99 if err != nil { 100 status.Message = cfgutil.ToPointer(err.Error()) 101 status.Phase = appsv1alpha1.CMergeFailedPhase 102 } else { 103 status.Message = nil 104 status.Phase = appsv1alpha1.CMergedPhase 105 } 106 status.UpdateRevision = revision 107 return err 108 } 109 110 func syncStatus(configMap *corev1.ConfigMap, status *appsv1alpha1.ConfigurationItemDetailStatus) (err error) { 111 annotations := configMap.GetAnnotations() 112 // status.CurrentRevision = GetCurrentRevision(annotations) 113 revisions := RetrieveRevision(annotations) 114 if len(revisions) == 0 { 115 return 116 } 117 118 for i := 0; i < len(revisions); i++ { 119 updateRevision(revisions[i], status) 120 updateLastDoneRevision(revisions[i], status) 121 } 122 123 return 124 } 125 126 func updateLastDoneRevision(revision ConfigurationRevision, status *appsv1alpha1.ConfigurationItemDetailStatus) { 127 if revision.Phase == appsv1alpha1.CFinishedPhase { 128 status.LastDoneRevision = strconv.FormatInt(revision.Revision, 10) 129 } 130 } 131 132 func updateRevision(revision ConfigurationRevision, status *appsv1alpha1.ConfigurationItemDetailStatus) { 133 if revision.StrRevision == status.UpdateRevision { 134 status.Phase = revision.Phase 135 status.ReconcileDetail = &appsv1alpha1.ReconcileDetail{ 136 CurrentRevision: revision.StrRevision, 137 Policy: revision.Result.Policy, 138 SucceedCount: revision.Result.SucceedCount, 139 ExpectedCount: revision.Result.ExpectedCount, 140 ExecResult: revision.Result.ExecResult, 141 ErrMessage: revision.Result.Message, 142 } 143 } 144 }