Skip to content

Commit ecd619d

Browse files
committed
feat: Update variable getter to handle nested fields
1 parent 32fb1d6 commit ecd619d

File tree

2 files changed

+77
-1
lines changed

2 files changed

+77
-1
lines changed

pkg/capi/clustertopology/variables/variable.go

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,41 @@ import (
77
"encoding/json"
88

99
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
10+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1011
"sigs.k8s.io/cluster-api/exp/runtime/topologymutation"
1112
)
1213

1314
// Get finds and parses variable to given type.
1415
func Get[T any](
1516
variables map[string]apiextensionsv1.JSON,
1617
name string,
18+
fields ...string,
1719
) (value T, found bool, err error) {
1820
variable, found, err := topologymutation.GetVariable(variables, name)
1921
if err != nil || !found {
2022
return value, found, err
2123
}
2224

23-
err = json.Unmarshal(variable.Raw, &value)
25+
jsonValue := variable.Raw
26+
27+
if len(fields) > 0 {
28+
var unstr map[string]interface{}
29+
err = json.Unmarshal(jsonValue, &unstr)
30+
if err != nil {
31+
return value, found, err
32+
}
33+
34+
nestedField, found, err := unstructured.NestedFieldCopy(unstr, fields...)
35+
if err != nil || !found {
36+
return value, found, err
37+
}
38+
39+
jsonValue, err = json.Marshal(nestedField)
40+
if err != nil {
41+
return value, found, err
42+
}
43+
}
44+
45+
err = json.Unmarshal(jsonValue, &value)
2446
return value, err == nil, err
2547
}

pkg/capi/clustertopology/variables/variables_test.go

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,57 @@ func TestGetVariable_ParseError(t *testing.T) {
5151
g.Expect(found).To(BeFalse())
5252
g.Expect(parsed).To(BeEmpty())
5353
}
54+
55+
func TestGet_ValidNestedFieldAsStruct(t *testing.T) {
56+
g := NewWithT(t)
57+
58+
type nestedStruct struct {
59+
Bar string `json:"bar"`
60+
}
61+
sampleValue := []byte(`{"foo": {"bar": "baz"}}`)
62+
vars := map[string]apiextensionsv1.JSON{
63+
"sampleVar": {Raw: sampleValue},
64+
}
65+
parsed, found, err := variables.Get[nestedStruct](vars, "sampleVar", "foo")
66+
g.Expect(err).NotTo(HaveOccurred())
67+
g.Expect(found).To(BeTrue())
68+
g.Expect(parsed).To(Equal(nestedStruct{
69+
Bar: "baz",
70+
}))
71+
}
72+
73+
func TestGet_ValidNestedFieldAsScalar(t *testing.T) {
74+
g := NewWithT(t)
75+
76+
sampleValue := []byte(`{"foo": {"bar": "baz"}}`)
77+
vars := map[string]apiextensionsv1.JSON{
78+
"sampleVar": {Raw: sampleValue},
79+
}
80+
parsed, found, err := variables.Get[string](vars, "sampleVar", "foo", "bar")
81+
g.Expect(err).NotTo(HaveOccurred())
82+
g.Expect(found).To(BeTrue())
83+
g.Expect(parsed).To(Equal("baz"))
84+
}
85+
86+
func TestGet_InvalidNestedFieldType(t *testing.T) {
87+
g := NewWithT(t)
88+
89+
sampleValue := []byte(`{"foo": {"bar": "baz"}}`)
90+
vars := map[string]apiextensionsv1.JSON{
91+
"sampleVar": {Raw: sampleValue},
92+
}
93+
_, _, err := variables.Get[int](vars, "sampleVar", "foo", "bar")
94+
g.Expect(err).To(HaveOccurred())
95+
}
96+
97+
func TestGet_MissingNestedField(t *testing.T) {
98+
g := NewWithT(t)
99+
100+
sampleValue := []byte(`{"foo": {"bar": "baz"}}`)
101+
vars := map[string]apiextensionsv1.JSON{
102+
"sampleVar": {Raw: sampleValue},
103+
}
104+
_, found, err := variables.Get[string](vars, "sampleVar", "foo", "nonexistent")
105+
g.Expect(err).NotTo(HaveOccurred())
106+
g.Expect(found).To(BeFalse())
107+
}

0 commit comments

Comments
 (0)