github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/controllers/apps/configuration/revision.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 "encoding/json" 24 "sort" 25 "strconv" 26 "strings" 27 28 corev1 "k8s.io/api/core/v1" 29 30 appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1" 31 "github.com/1aal/kubeblocks/pkg/configuration/core" 32 "github.com/1aal/kubeblocks/pkg/constant" 33 intctrlutil "github.com/1aal/kubeblocks/pkg/controllerutil" 34 ) 35 36 type ConfigurationRevision struct { 37 Revision int64 38 StrRevision string 39 Phase appsv1alpha1.ConfigurationPhase 40 Result intctrlutil.Result 41 } 42 43 const revisionHistoryLimit = 10 44 45 func GcConfigRevision(configObj *corev1.ConfigMap) { 46 revisions := GcRevision(configObj.ObjectMeta.Annotations) 47 if len(revisions) > 0 { 48 for _, v := range revisions { 49 delete(configObj.ObjectMeta.Annotations, core.GenerateRevisionPhaseKey(v.StrRevision)) 50 } 51 } 52 } 53 54 func GcRevision(annotations map[string]string) []ConfigurationRevision { 55 revisions := RetrieveRevision(annotations) 56 if len(revisions) <= revisionHistoryLimit { 57 return nil 58 } 59 60 return revisions[0 : len(revisions)-revisionHistoryLimit] 61 } 62 63 func GetLastRevision(annotations map[string]string, revision int64) (ConfigurationRevision, bool) { 64 revisions := RetrieveRevision(annotations) 65 for i := len(revisions) - 1; i >= 0; i-- { 66 if revisions[i].Revision == revision { 67 return revisions[i], true 68 } 69 } 70 return ConfigurationRevision{}, false 71 } 72 73 func RetrieveRevision(annotations map[string]string) []ConfigurationRevision { 74 var revisions []ConfigurationRevision 75 var revisionPrefix = constant.LastConfigurationRevisionPhase + "-" 76 77 for key, value := range annotations { 78 if !strings.HasPrefix(key, revisionPrefix) { 79 continue 80 } 81 revision, err := parseRevision(strings.TrimPrefix(key, revisionPrefix), value) 82 if err == nil { 83 revisions = append(revisions, revision) 84 } 85 } 86 87 // for sort 88 sort.SliceStable(revisions, func(i, j int) bool { 89 return revisions[i].Revision < revisions[j].Revision 90 }) 91 return revisions 92 } 93 94 func parseRevision(revision string, data string) (ConfigurationRevision, error) { 95 v, err := strconv.ParseInt(revision, 10, 64) 96 if err != nil { 97 return ConfigurationRevision{}, err 98 } 99 result := parseResult(data, revision) 100 return ConfigurationRevision{ 101 StrRevision: revision, 102 Revision: v, 103 Phase: result.Phase, 104 Result: result, 105 }, nil 106 } 107 108 func parseResult(data string, revision string) intctrlutil.Result { 109 result := intctrlutil.Result{ 110 Revision: revision, 111 } 112 data = strings.TrimSpace(data) 113 if data == "" { 114 return result 115 } 116 err := json.Unmarshal([]byte(data), &result) 117 if err != nil { 118 result.Phase = appsv1alpha1.ConfigurationPhase(data) 119 } 120 return result 121 } 122 123 func GetCurrentRevision(annotations map[string]string) string { 124 if len(annotations) == 0 { 125 return "" 126 } 127 return annotations[constant.ConfigurationRevision] 128 }