From 85eaa2070810c2c83f11fab192c6ffab0534ebbe Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Mon, 9 Oct 2023 15:26:42 +0200 Subject: [PATCH] overlays from different profiles are merged If a node contains several profiles and these profiles have overlays attached, these profiles are now merged. Overlays can't be excluded as this can not be displayed to the user Signed-off-by: Christian Goll --- CHANGELOG.md | 1 + internal/pkg/node/constuctors_test.go | 57 +++++++++++++++++++++++++++ internal/pkg/node/methods.go | 22 +++++++---- 3 files changed, 72 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f9215162..73d389f5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -134,6 +134,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 warewulf.grubboot: true in warewulf.conf. For unknown nodes, grub.efi and shim.efi are extracted from the Warewulf host. If the booted node has a container these binaries are extracted from the container image. +- overlays from different profiles for one node are now merged #885 ## [4.4.0] 2023-01-18 diff --git a/internal/pkg/node/constuctors_test.go b/internal/pkg/node/constuctors_test.go index 406dad9d..1e5a3b42 100644 --- a/internal/pkg/node/constuctors_test.go +++ b/internal/pkg/node/constuctors_test.go @@ -138,3 +138,60 @@ func Test_FindDiscoverableNode(t *testing.T) { }) } } + +func Test_Profile_Overlay_Merge(t *testing.T) { + nodesconf := ` +nodeprofiles: + profile1: + runtime overlay: + - p1o1 + - p1o2 + profile2: + runtime overlay: + - p2o1 + - p2o2 +nodes: + node1: + profiles: + - profile1 + node2: + profiles: + - profile1 + - profile2 + node3: + runtime overlay: + - n1o1 + - n1o2 + profiles: + - profile1 + node4: + runtime overlay: + - n1o1 + - n1o2 + profiles: + - profile1 + - profile2 +` + assert := assert.New(t) + var ymlSrc NodeYaml + err := yaml.Unmarshal([]byte(nodesconf), &ymlSrc) + assert.NoError(err) + nodes, err := ymlSrc.FindAllNodes() + assert.NoError(err) + nodemap := make(map[string]*NodeInfo) + for i := range nodes { + nodemap[nodes[i].Id.Get()] = &nodes[i] + } + assert.Contains(nodemap, "node1") + assert.ElementsMatch(nodemap["node1"].RuntimeOverlay.GetSlice(), []string{"p1o1", "p1o2"}) + assert.Equal(nodemap["node1"].RuntimeOverlay.Print(), "p1o1,p1o2") + assert.Contains(nodemap, "node2") + assert.ElementsMatch(nodemap["node2"].RuntimeOverlay.GetSlice(), []string{"p1o1", "p1o2", "p2o1", "p2o2"}) + assert.Equal(nodemap["node2"].RuntimeOverlay.Print(), "p1o1,p1o2,p2o1,p2o2") + assert.Contains(nodemap, "node3") + assert.ElementsMatch(nodemap["node3"].RuntimeOverlay.GetSlice(), []string{"p1o1", "p1o2", "n1o1", "n1o2"}) + assert.Equal(nodemap["node3"].RuntimeOverlay.Print(), "n1o1,n1o2,p1o1,p1o2") + assert.Contains(nodemap, "node4") + assert.ElementsMatch(nodemap["node4"].RuntimeOverlay.GetSlice(), []string{"p1o1", "p1o2", "p2o1", "p2o2", "n1o1", "n1o2"}) + assert.Equal(nodemap["node4"].RuntimeOverlay.Print(), "n1o1,n1o2,p1o1,p1o2,p2o1,p2o2") +} diff --git a/internal/pkg/node/methods.go b/internal/pkg/node/methods.go index 4d768ddb..3414a44e 100644 --- a/internal/pkg/node/methods.go +++ b/internal/pkg/node/methods.go @@ -152,8 +152,8 @@ func (ent *Entry) SetAltSlice(val []string, from string) { if len(val) == 0 { return } - ent.altvalue = val - ent.from = from + ent.altvalue = append(ent.altvalue, val...) + ent.from = ent.from + "," + from } /* @@ -200,7 +200,7 @@ func (ent *Entry) SliceRemoveElement(val string) { * *********/ /* -Gets the the entry of the value in folowing order +Gets the the entry of the value in following order * node value if set * profile value if set * default value if set @@ -244,10 +244,13 @@ Returns a string slice created from a comma seperated list of the value. func (ent *Entry) GetSlice() []string { var retval []string if len(ent.value) != 0 { - return ent.value + retval = ent.value } if len(ent.altvalue) != 0 { - return ent.altvalue + retval = append(retval, ent.altvalue...) + } + if len(retval) != 0 { + return retval } if len(ent.def) != 0 { return ent.def @@ -324,12 +327,15 @@ Returns the value of Entry if it was defined set or alternative is presend. Default value is in '()'. If nothing is defined '--' is returned. */ -func (ent *Entry) Print() string { +func (ent *Entry) Print() (ret string) { if len(ent.value) != 0 { - return strings.Join(ent.value, ",") + ret = strings.Join(ent.value, ",") } if len(ent.altvalue) != 0 { - return strings.Join(ent.altvalue, ",") + ret = strings.Join(append(ent.value, ent.altvalue...), ",") + } + if ret != "" { + return ret } if len(ent.def) != 0 { return "(" + strings.Join(ent.def, ",") + ")"