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  }