in pkg/bundle/patch/package.go [85:196]
func Apply(spec *bundlev1.Patch, b *bundlev1.Bundle, values map[string]interface{}, o ...OptionFunc) (*bundlev1.Bundle, error) {
// Validate spec
if err := Validate(spec); err != nil {
return nil, fmt.Errorf("unable to validate spec: %w", err)
}
if b == nil {
return nil, fmt.Errorf("cannot process nil bundle")
}
// Prepare selectors
if len(spec.Spec.Rules) == 0 {
return nil, fmt.Errorf("empty bundle patch")
}
// Copy bundle
bCopy, ok := proto.Clone(b).(*bundlev1.Bundle)
if !ok {
return nil, fmt.Errorf("the cloned bundle does not have the expected type: %T", bCopy)
}
if bCopy.Packages == nil {
bCopy.Packages = []*bundlev1.Package{}
}
// Default evaluation options
dopts := &options{
stopAtRuleID: "",
stopAtRuleIndex: -1,
ignoreRuleIDs: []string{},
ignoreRuleIndexes: []int{},
}
// Apply functions
for _, opt := range o {
opt(dopts)
}
// Process all creation rule first
for i, r := range spec.Spec.Rules {
// Ignore nil rule
if r == nil {
continue
}
// Ignore non creation rules and non strict matcher
if !r.Package.Create || r.Selector.MatchPath.Strict == "" {
continue
}
if shouldIgnoreThisRule(i, r.Id, dopts) {
continue
}
if shouldStopAtThisRule(i, r.Id, dopts) {
break
}
// Create a package
p := &bundlev1.Package{
Name: r.Selector.MatchPath.Strict,
}
_, err := executeRule(r, p, values)
if err != nil {
return nil, fmt.Errorf("unable to execute rule index %d: %w", i, err)
}
// Add created package
bCopy.Packages = append(bCopy.Packages, p)
}
for ri, r := range spec.Spec.Rules {
// Ignore nil rule
if r == nil {
continue
}
if shouldIgnoreThisRule(ri, r.Id, dopts) {
continue
}
if shouldStopAtThisRule(ri, r.Id, dopts) {
break
}
// Process all packages
for i, p := range bCopy.Packages {
action, err := executeRule(r, p, values)
if err != nil {
return nil, fmt.Errorf("unable to execute rule index %d: %w", ri, err)
}
switch action {
case packagedRemoved:
bCopy.Packages = append(bCopy.Packages[:i], bCopy.Packages[i+1:]...)
case packageUpdated:
if WithAnnotations(spec) {
// Add annotations to mark package as patched.
bundle.Annotate(p, "patched", "true")
bundle.Annotate(p, spec.Meta.Name, "true")
}
bCopy.Packages[i] = p
case packageUnchanged:
// No changes
default:
}
}
}
// Sort packages
sort.SliceStable(bCopy.Packages, func(i, j int) bool {
return bCopy.Packages[i].Name < bCopy.Packages[j].Name
})
// No error
return bCopy, nil
}