github.com/zntrio/harp/v2@v2.0.9/pkg/bundle/compare/patch.go (about) 1 // Licensed to Elasticsearch B.V. under one or more contributor 2 // license agreements. See the NOTICE file distributed with 3 // this work for additional information regarding copyright 4 // ownership. Elasticsearch B.V. licenses this file to you under 5 // the Apache License, Version 2.0 (the "License"); you may 6 // not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, 12 // software distributed under the License is distributed on an 13 // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 // KIND, either express or implied. See the License for the 15 // specific language governing permissions and limitations 16 // under the License. 17 18 package compare 19 20 import ( 21 "fmt" 22 "strings" 23 24 bundlev1 "github.com/zntrio/harp/v2/api/gen/go/harp/bundle/v1" 25 ) 26 27 // ToPatch convert oplog to a bundle patch. 28 func ToPatch(oplog []DiffItem) (*bundlev1.Patch, error) { 29 // Check arguments 30 if len(oplog) == 0 { 31 return nil, fmt.Errorf("unable to generate a patch with an empty oplog") 32 } 33 34 res := &bundlev1.Patch{ 35 ApiVersion: "harp.elastic.co/v1", 36 Kind: "BundlePatch", 37 Meta: &bundlev1.PatchMeta{ 38 Name: "autogenerated-patch", 39 Description: "Patch generated from oplog", 40 }, 41 Spec: &bundlev1.PatchSpec{ 42 Rules: []*bundlev1.PatchRule{}, 43 }, 44 } 45 46 secretMap := map[string]*bundlev1.PatchRule{} 47 48 // Generate patch rules 49 for _, op := range oplog { 50 if op.Type == "package" { 51 if op.Operation == Remove { 52 res.Spec.Rules = append(res.Spec.Rules, &bundlev1.PatchRule{ 53 Selector: &bundlev1.PatchSelector{ 54 MatchPath: &bundlev1.PatchSelectorMatchPath{ 55 Strict: op.Path, 56 }, 57 }, 58 Package: &bundlev1.PatchPackage{ 59 Remove: true, 60 }, 61 }) 62 } 63 continue 64 } 65 if op.Type == "secret" { 66 pathParts := strings.SplitN(op.Path, "#", 2) 67 pkgRule, ok := secretMap[pathParts[0]] 68 if !ok { 69 secretMap[pathParts[0]] = &bundlev1.PatchRule{ 70 Selector: &bundlev1.PatchSelector{ 71 MatchPath: &bundlev1.PatchSelectorMatchPath{ 72 Strict: pathParts[0], 73 }, 74 }, 75 Package: &bundlev1.PatchPackage{ 76 Data: &bundlev1.PatchSecret{ 77 Kv: &bundlev1.PatchOperation{}, 78 }, 79 }, 80 } 81 pkgRule = secretMap[pathParts[0]] 82 } 83 84 switch op.Operation { 85 case Add: 86 if pkgRule.Package.Data.Kv.Add == nil { 87 pkgRule.Package.Data.Kv.Add = map[string]string{} 88 } 89 pkgRule.Package.Data.Kv.Add[pathParts[1]] = op.Value 90 case Replace: 91 if pkgRule.Package.Data.Kv.Update == nil { 92 pkgRule.Package.Data.Kv.Update = map[string]string{} 93 } 94 pkgRule.Package.Data.Kv.Update[pathParts[1]] = op.Value 95 case Remove: 96 if pkgRule.Package.Data.Kv.Remove == nil { 97 pkgRule.Package.Data.Kv.Remove = []string{} 98 } 99 pkgRule.Package.Data.Kv.Remove = append(pkgRule.Package.Data.Kv.Remove, pathParts[1]) 100 } 101 } 102 } 103 104 // Add grouped secret patches 105 for _, r := range secretMap { 106 if r == nil { 107 continue 108 } 109 110 res.Spec.Rules = append(res.Spec.Rules, r) 111 } 112 113 // No error 114 return res, nil 115 }