Skip to content

Commit

Permalink
allow vars with the same value to not conflict
Browse files Browse the repository at this point in the history
  • Loading branch information
Tyler committed Oct 15, 2019
1 parent fff4e67 commit 643fcd6
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 8 deletions.
31 changes: 30 additions & 1 deletion pkg/accumulator/resaccumulator.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,36 @@ func (ra *ResAccumulator) MergeAccumulator(other *ResAccumulator) (err error) {
if err != nil {
return err
}
return ra.varSet.MergeSet(other.varSet)
err = ra.varSet.MergeSet(other.varSet)
if errs, ok := err.(types.MergeSetError); ok {
return ra.resolveVarConflicts(other, errs)
}
return nil
}

// resolveVarConflicts iterates over all variable name conflicts found while
// merging VarSets from two ResAccumulator instances. Some apparent conflicts
// can be ignored, such as variables that appear more than once but which
// reference the same concrete value.
func (ra *ResAccumulator) resolveVarConflicts(other *ResAccumulator, conflict types.MergeSetError) error {
var badVars []string
for _, mergeErr := range conflict.Errs {
incomingValue, ierr := ra.findVarValueFromResources(mergeErr.Incoming)
if ierr != nil {
return ierr
}
conflictValue, cerr := other.findVarValueFromResources(mergeErr.Conflict)
if cerr != nil {
return cerr
}
if incomingValue != conflictValue {
badVars = append(badVars, mergeErr.Incoming.Name)
}
}
if len(badVars) == 0 {
return nil
}
return fmt.Errorf("found conflicting variable(s) named: %s", strings.Join(badVars, ", "))
}

func (ra *ResAccumulator) findVarValueFromResources(v types.Var) (interface{}, error) {
Expand Down
3 changes: 1 addition & 2 deletions pkg/target/kusttarget.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,7 @@ func (kt *KustTarget) shouldAddHashSuffixesToGeneratedResources() bool {
// holding customized resources and the data/rules used
// to do so. The name back references and vars are
// not yet fixed.
func (kt *KustTarget) AccumulateTarget() (
ra *accumulator.ResAccumulator, err error) {
func (kt *KustTarget) AccumulateTarget() (ra *accumulator.ResAccumulator, err error) {
ra = accumulator.MakeEmptyAccumulator()
err = kt.accumulateResources(ra, kt.kustomization.Resources)
if err != nil {
Expand Down
44 changes: 39 additions & 5 deletions pkg/types/var.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,34 @@ type FieldSelector struct {
FieldPath string `json:"fieldPath,omitempty" yaml:"fieldPath,omitempty"`
}

// defaulting sets reference to field used by default.
// VarMergeError annotates a variable merge conflict with a reference to the
// variable that encountered the conflict. This is used at higher levels of the
// API to determine if the conflict can be ignored (e.g. two sets of resources
// using the same variable name are not in conflict if the concrete values they
// reference are the same).
type VarMergeError struct {
msg string
Incoming Var
Conflict Var
}

func (vme VarMergeError) Error() string { return vme.msg }

// MergeSetError contains the aggregation of all errors encountered while
// trying to merge two VarSets.
type MergeSetError struct {
Errs []VarMergeError
}

func (mse MergeSetError) Error() string {
var result []string
for _, err := range mse.Errs {
result = append(result, err.Error())
}
return strings.Join(result, "\n")
}

// Defaulting sets reference to field used by default.
func (v *Var) Defaulting() {
if v.FieldRef.FieldPath == "" {
v.FieldRef.FieldPath = defaultFieldPath
Expand Down Expand Up @@ -117,11 +144,15 @@ func (vs *VarSet) Copy() VarSet {

// MergeSet absorbs other vars with error on name collision.
func (vs *VarSet) MergeSet(incoming VarSet) error {
var errs []VarMergeError
for _, incomingVar := range incoming.set {
if err := vs.Merge(incomingVar); err != nil {
return err
if mergeErr, ok := vs.Merge(incomingVar).(VarMergeError); ok {
errs = append(errs, mergeErr)
}
}
if len(errs) != 0 {
return MergeSetError{errs}
}
return nil
}

Expand All @@ -140,8 +171,11 @@ func (vs *VarSet) MergeSlice(incoming []Var) error {
// Empty fields in incoming Var is defaulted.
func (vs *VarSet) Merge(v Var) error {
if vs.Contains(v) {
return fmt.Errorf(
"var '%s' already encountered", v.Name)
return VarMergeError{
msg: fmt.Sprintf("var '%s' already encountered", v.Name),
Incoming: v,
Conflict: *vs.Get(v.Name),
}
}
v.Defaulting()
vs.set[v.Name] = v
Expand Down

0 comments on commit 643fcd6

Please sign in to comment.