From c2ef6386e230e601d66d474213401774e648e3c3 Mon Sep 17 00:00:00 2001 From: Suleiman Dibirov Date: Tue, 29 Oct 2024 20:50:52 +0200 Subject: [PATCH] fix(reset): Add cycle detection fix for services that are prefixed with the name of a preceding service Signed-off-by: Suleiman Dibirov --- loader/reset.go | 2 +- loader/reset_test.go | 77 ++++++++++++++++++++++++++++++++++++-------- 2 files changed, 64 insertions(+), 15 deletions(-) diff --git a/loader/reset.go b/loader/reset.go index 213d0e8f..8dd5e1bb 100644 --- a/loader/reset.go +++ b/loader/reset.go @@ -63,7 +63,7 @@ func (p *ResetProcessor) resolveReset(node *yaml.Node, path tree.Path) (*yaml.No } // Mark the current node as visited - p.visitedNodes[node] = pathStr + 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 { diff --git a/loader/reset_test.go b/loader/reset_test.go index 3b070c35..57a24d94 100644 --- a/loader/reset_test.go +++ b/loader/reset_test.go @@ -83,22 +83,71 @@ networks: } func TestResetCycle(t *testing.T) { - _, err := Load( - types.ConfigDetails{ - ConfigFiles: []types.ConfigFile{ - { - Filename: "(inline)", - Content: []byte(` + tests := []struct { + name string + config string + expectError bool + errorMsg string + }{ + { + name: "no cycle", + config: ` +name: test +services: + a: &a + image: alpine + a2: *a +`, + expectError: false, + errorMsg: "", + }, + { + name: "no cycle reversed", + config: ` +name: test +services: + a2: &a + image: alpine + a: *a +`, + expectError: false, + errorMsg: "", + }, + { + name: "healthcheck_cycle", + config: ` x-healthcheck: &healthcheck egress-service: <<: *healthcheck -`), - }, - }, - }, func(options *Options) { - options.SkipNormalization = true - options.SkipConsistencyCheck = true +`, + expectError: true, + errorMsg: "cycle detected at path: x-healthcheck.egress-service", }, - ) - assert.Error(t, err, "cycle detected at path: x-healthcheck.egress-service") + } + + for _, tt := range tests { + t.Run( + tt.name, func(t *testing.T) { + _, err := Load( + types.ConfigDetails{ + ConfigFiles: []types.ConfigFile{ + { + Filename: "(inline)", + Content: []byte(tt.config), + }, + }, + }, func(options *Options) { + options.SkipNormalization = true + options.SkipConsistencyCheck = true + }, + ) + + if tt.expectError { + assert.Error(t, err, tt.errorMsg) + } else { + assert.NilError(t, err) + } + }, + ) + } }