Skip to content

Commit db9ff23

Browse files
committed
fix: patch with delete for LinkConfigs
There were two issues which prevented this patch from working: * `CommonLinkConfig` is an embedded struct, so we need to make selector descend into embedded structs properly * The previous `reflect.Value.String()` doesn't handle correctly complex values (like `netip.Prefix`) which have a custom `fmt.Stringer` See #12848 (reply in thread) Signed-off-by: Andrey Smirnov <andrey.smirnov@siderolabs.com> (cherry picked from commit c1d0a33)
1 parent e0c38e2 commit db9ff23

File tree

5 files changed

+88
-2
lines changed

5 files changed

+88
-2
lines changed

pkg/machinery/config/configloader/internal/decoder/selector.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ var searchForType = reflect.TypeFor[string]()
134134
// ErrLookupFailed is returned when the lookup failed.
135135
var ErrLookupFailed = errors.New("lookup failed")
136136

137-
//nolint:gocyclo
137+
//nolint:gocyclo,cyclop
138138
func deleteForPath(val reflect.Value, path []string, key, value string) error {
139139
if len(path) == 0 {
140140
return errors.New("path is empty")
@@ -173,6 +173,20 @@ func deleteForPath(val reflect.Value, path []string, key, value string) error {
173173

174174
return deleteForPath(val.Field(i), path, key, value)
175175
}
176+
177+
// if there is an embedded struct, descend into it
178+
if len(yamlTags) > 1 && yamlTags[0] == "" && yamlTags[1] == "inline" {
179+
err := deleteForPath(val.Field(i), append([]string{searchFor}, path...), key, value)
180+
if err == nil {
181+
// value found & deleted
182+
return nil
183+
}
184+
185+
// ignore lookup failed errors, we can continue with other fields
186+
if !errors.Is(err, ErrLookupFailed) {
187+
return err
188+
}
189+
}
176190
}
177191
case reflect.Map:
178192
if val.IsNil() {
@@ -246,7 +260,17 @@ func deleteStructFrom(searchIn reflect.Value, searchFor string, path []string, k
246260
continue
247261
}
248262

249-
if elem.Field(j).String() != value {
263+
fieldVal := elem.Field(j)
264+
fieldStr := fieldVal.String()
265+
266+
// if the field value implements Stringer, use it for comparison instead of the default string conversion
267+
if fieldVal.CanInterface() {
268+
if stringer, ok := fieldVal.Interface().(fmt.Stringer); ok {
269+
fieldStr = stringer.String()
270+
}
271+
}
272+
273+
if fieldStr != value {
250274
continue
251275
}
252276

pkg/machinery/config/configpatcher/apply_test.go

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// License, v. 2.0. If a copy of the MPL was not distributed with this
33
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
44

5+
//nolint:dupl
56
package configpatcher_test
67

78
import (
@@ -325,3 +326,43 @@ func TestPatchDeleteMissing(t *testing.T) {
325326
})
326327
}
327328
}
329+
330+
//go:embed testdata/patchlink/base.yaml
331+
var configPatchBase []byte
332+
333+
//go:embed testdata/patchlink/expected.yaml
334+
var configPatchExpected string
335+
336+
func TestPatchLink(t *testing.T) {
337+
patches, err := configpatcher.LoadPatches([]string{
338+
"@testdata/patchlink/patch.yaml",
339+
})
340+
require.NoError(t, err)
341+
342+
cfg, err := configloader.NewFromBytes(configPatchBase)
343+
require.NoError(t, err)
344+
345+
for _, tt := range []struct {
346+
name string
347+
input configpatcher.Input
348+
}{
349+
{
350+
name: "WithConfig",
351+
input: configpatcher.WithConfig(cfg),
352+
},
353+
{
354+
name: "WithBytes",
355+
input: configpatcher.WithBytes(configPatchBase),
356+
},
357+
} {
358+
t.Run(tt.name, func(t *testing.T) {
359+
out, err := configpatcher.Apply(tt.input, patches)
360+
require.NoError(t, err)
361+
362+
bytes, err := out.Bytes()
363+
require.NoError(t, err)
364+
365+
assert.Equal(t, configPatchExpected, string(bytes))
366+
})
367+
}
368+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: v1alpha1
2+
kind: LinkConfig
3+
name: eth0
4+
addresses:
5+
- address: 10.0.42.136/24
6+
routes:
7+
- gateway: 10.0.42.1
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: v1alpha1
2+
kind: LinkConfig
3+
name: eth0
4+
addresses:
5+
- address: 10.0.42.137/24
6+
routes:
7+
- gateway: 10.0.42.1
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
apiVersion: v1alpha1
2+
kind: LinkConfig
3+
name: eth0
4+
addresses:
5+
- address: 10.0.42.136/24
6+
$patch: delete
7+
- address: 10.0.42.137/24

0 commit comments

Comments
 (0)