Skip to content

Commit

Permalink
fix(reset): Add cycle detection fix
Browse files Browse the repository at this point in the history
Signed-off-by: Suleiman Dibirov <[email protected]>
  • Loading branch information
idsulik authored and glours committed Nov 1, 2024
1 parent 0e87616 commit b9d3b1d
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 16 deletions.
39 changes: 23 additions & 16 deletions loader/reset.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,24 +49,12 @@ func (p *ResetProcessor) resolveReset(node *yaml.Node, path tree.Path) (*yaml.No
path = tree.NewPath(strings.Replace(pathStr, ".<<", "", 1))
}

// Check for cycle
if p.visitedNodes == nil {
p.visitedNodes = make(map[*yaml.Node]string)
}

// Check for cycle by seeing if the node has already been visited at this path
if previousPath, found := p.visitedNodes[node]; found {
// If the current node has been visited, we have a cycle if the previous path is a prefix
if strings.HasPrefix(pathStr, previousPath) {
return nil, fmt.Errorf("cycle detected at path: %s", pathStr)
}
}

// Mark the current node as visited
p.visitedNodes[node] = pathStr + "."

// If the node is an alias, We need to process the alias field in order to consider the !override and !reset tags
if node.Kind == yaml.AliasNode {
if err := p.checkForCycle(node.Alias, path); err != nil {
return nil, err
}

return p.resolveReset(node.Alias, path)
}

Expand Down Expand Up @@ -154,3 +142,22 @@ func (p *ResetProcessor) applyNullOverrides(target any, path tree.Path) error {
}
return nil
}

func (p *ResetProcessor) checkForCycle(node *yaml.Node, path tree.Path) error {
if p.visitedNodes == nil {
p.visitedNodes = make(map[*yaml.Node]string)
}

// Check for cycle by seeing if the node has already been visited at this path
if previousPath, found := p.visitedNodes[node]; found {
// If the current node has been visited, we have a cycle if the previous path is a prefix
if strings.HasPrefix(path.String(), strings.TrimRight(previousPath, "<<")) {
return fmt.Errorf("cycle detected at path: %s", previousPath)
}
}

// Mark the current node as visited
p.visitedNodes[node] = path.String()

return nil
}
20 changes: 20 additions & 0 deletions loader/reset_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,26 @@ services:
a2: &a
image: alpine
a: *a
`,
expectError: false,
errorMsg: "",
},
{
name: "no cycle 2",
config: `
name: blah
x-templates:
x-gluetun: &gluetun
environment: &gluetun_env
a: b
x-gluetun-pia: &gluetun_pia
<<: *gluetun
x-gluetun-env-pia: &gluetun_env_pia
<<: *gluetun_env
vp0:
<<: *gluetun_pia
environment:
<<: *gluetun_env_pia
`,
expectError: false,
errorMsg: "",
Expand Down

0 comments on commit b9d3b1d

Please sign in to comment.