pkg/bundle/compare/patch.go (83 lines of code) (raw):
// Licensed to Elasticsearch B.V. under one or more contributor
// license agreements. See the NOTICE file distributed with
// this work for additional information regarding copyright
// ownership. Elasticsearch B.V. licenses this file to you under
// the Apache License, Version 2.0 (the "License"); you may
// not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
package compare
import (
"fmt"
"strings"
bundlev1 "github.com/elastic/harp/api/gen/go/harp/bundle/v1"
)
// ToPatch convert oplog to a bundle patch.
func ToPatch(oplog []DiffItem) (*bundlev1.Patch, error) {
// Check arguments
if len(oplog) == 0 {
return nil, fmt.Errorf("unable to generate a patch with an empty oplog")
}
res := &bundlev1.Patch{
ApiVersion: "harp.elastic.co/v1",
Kind: "BundlePatch",
Meta: &bundlev1.PatchMeta{
Name: "autogenerated-patch",
Description: "Patch generated from oplog",
},
Spec: &bundlev1.PatchSpec{
Rules: []*bundlev1.PatchRule{},
},
}
secretMap := map[string]*bundlev1.PatchRule{}
// Generate patch rules
for _, op := range oplog {
if op.Type == "package" {
if op.Operation == Remove {
res.Spec.Rules = append(res.Spec.Rules, &bundlev1.PatchRule{
Selector: &bundlev1.PatchSelector{
MatchPath: &bundlev1.PatchSelectorMatchPath{
Strict: op.Path,
},
},
Package: &bundlev1.PatchPackage{
Remove: true,
},
})
}
continue
}
if op.Type == "secret" {
pathParts := strings.SplitN(op.Path, "#", 2)
pkgRule, ok := secretMap[pathParts[0]]
if !ok {
secretMap[pathParts[0]] = &bundlev1.PatchRule{
Selector: &bundlev1.PatchSelector{
MatchPath: &bundlev1.PatchSelectorMatchPath{
Strict: pathParts[0],
},
},
Package: &bundlev1.PatchPackage{
Data: &bundlev1.PatchSecret{
Kv: &bundlev1.PatchOperation{},
},
},
}
pkgRule = secretMap[pathParts[0]]
}
switch op.Operation {
case Add:
if pkgRule.Package.Data.Kv.Add == nil {
pkgRule.Package.Data.Kv.Add = map[string]string{}
}
pkgRule.Package.Data.Kv.Add[pathParts[1]] = op.Value
case Replace:
if pkgRule.Package.Data.Kv.Update == nil {
pkgRule.Package.Data.Kv.Update = map[string]string{}
}
pkgRule.Package.Data.Kv.Update[pathParts[1]] = op.Value
case Remove:
if pkgRule.Package.Data.Kv.Remove == nil {
pkgRule.Package.Data.Kv.Remove = []string{}
}
pkgRule.Package.Data.Kv.Remove = append(pkgRule.Package.Data.Kv.Remove, pathParts[1])
}
}
}
// Add grouped secret patches
for _, r := range secretMap {
if r == nil {
continue
}
res.Spec.Rules = append(res.Spec.Rules, r)
}
// No error
return res, nil
}