Skip to content

Commit 2f85d39

Browse files
committed
Convert ServerMetadata from a map to a list
While we're changing it, we also add validation that keys and values don't exceed 255 characters.
1 parent 5786940 commit 2f85d39

15 files changed

+311
-28
lines changed

api/v1alpha5/zz_generated.conversion.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/v1alpha6/conversion.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,24 @@ func restorev1alpha6MachineSpec(previous *OpenStackMachineSpec, dst *OpenStackMa
4040
dst.Networks = previous.Networks
4141
dst.Ports = previous.Ports
4242
dst.SecurityGroups = previous.SecurityGroups
43+
44+
// Conversion to v1alpha8 truncates keys and values to 255 characters
45+
for k, v := range previous.ServerMetadata {
46+
kd := k
47+
if len(k) > 255 {
48+
kd = k[:255]
49+
}
50+
51+
vd := v
52+
if len(v) > 255 {
53+
vd = v[:255]
54+
}
55+
56+
if kd != k || vd != v {
57+
delete(dst.ServerMetadata, kd)
58+
dst.ServerMetadata[k] = v
59+
}
60+
}
4361
}
4462

4563
func restorev1alpha6ClusterStatus(previous *OpenStackClusterStatus, dst *OpenStackClusterStatus) {
@@ -403,6 +421,23 @@ func Convert_v1alpha6_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *
403421
}
404422
out.Image = imageFilter
405423

424+
if len(in.ServerMetadata) > 0 {
425+
serverMetadata := make([]infrav1.ServerMetadata, 0, len(in.ServerMetadata))
426+
for k, v := range in.ServerMetadata {
427+
// Truncate key and value to 255 characters if required, as this
428+
// was not validated prior to v1alpha8
429+
if len(k) > 255 {
430+
k = k[:255]
431+
}
432+
if len(v) > 255 {
433+
v = v[:255]
434+
}
435+
436+
serverMetadata = append(serverMetadata, infrav1.ServerMetadata{Key: k, Value: v})
437+
}
438+
out.ServerMetadata = serverMetadata
439+
}
440+
406441
return nil
407442
}
408443

@@ -739,6 +774,16 @@ func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha6_OpenStackMachineSpec(in *
739774
out.ImageUUID = in.Image.ID
740775
}
741776

777+
if len(in.ServerMetadata) > 0 {
778+
serverMetadata := make(map[string]string, len(in.ServerMetadata))
779+
for i := range in.ServerMetadata {
780+
key := in.ServerMetadata[i].Key
781+
value := in.ServerMetadata[i].Value
782+
serverMetadata[key] = value
783+
}
784+
out.ServerMetadata = serverMetadata
785+
}
786+
742787
return nil
743788
}
744789

api/v1alpha6/conversion_test.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,37 @@ func TestFuzzyConversion(t *testing.T) {
8888
status.ExternalNetwork.APIServerLoadBalancer = nil
8989
}
9090
},
91+
92+
func(spec *OpenStackMachineSpec, c fuzz.Continue) {
93+
c.FuzzNoCustom(spec)
94+
95+
// RandString() generates strings up to 20
96+
// characters long. To exercise truncation of
97+
// long server metadata keys and values we need
98+
// the possibility of strings > 255 chars.
99+
genLongString := func() string {
100+
var ret string
101+
for len(ret) < 255 {
102+
ret += c.RandString()
103+
}
104+
return ret
105+
}
106+
107+
// Existing server metadata keys will be short. Add a random number of long ones.
108+
for c.RandBool() {
109+
if spec.ServerMetadata == nil {
110+
spec.ServerMetadata = map[string]string{}
111+
}
112+
spec.ServerMetadata[genLongString()] = c.RandString()
113+
}
114+
115+
// Randomly make some server metadata values long.
116+
for k := range spec.ServerMetadata {
117+
if c.RandBool() {
118+
spec.ServerMetadata[k] = genLongString()
119+
}
120+
}
121+
},
91122
}
92123
}
93124

api/v1alpha6/zz_generated.conversion.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/v1alpha7/conversion.go

Lines changed: 67 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,38 @@ func (r *OpenStackClusterTemplate) ConvertFrom(srcRaw ctrlconversion.Hub) error
169169

170170
var _ ctrlconversion.Convertible = &OpenStackMachine{}
171171

172-
var v1alpha7OpenStackMachineRestorer = conversion.RestorerFor[*OpenStackMachine]{}
172+
func restorev1alpha7ServerMetadata(previous *map[string]string, dst *map[string]string) { //nolint:gocritic
173+
if previous == nil || dst == nil {
174+
return
175+
}
176+
177+
// Conversion to v1alpha8 truncates keys and values to 255 characters
178+
for k, v := range *previous {
179+
kd := k
180+
if len(k) > 255 {
181+
kd = k[:255]
182+
}
183+
184+
vd := v
185+
if len(v) > 255 {
186+
vd = v[:255]
187+
}
188+
189+
if kd != k || vd != v {
190+
delete(*dst, kd)
191+
(*dst)[k] = v
192+
}
193+
}
194+
}
195+
196+
var v1alpha7OpenStackMachineRestorer = conversion.RestorerFor[*OpenStackMachine]{
197+
"serverMetadata": conversion.HashedFieldRestorer(
198+
func(c *OpenStackMachine) *map[string]string {
199+
return &c.Spec.ServerMetadata
200+
},
201+
restorev1alpha7ServerMetadata,
202+
),
203+
}
173204

174205
var v1alpha8OpenStackMachineRestorer = conversion.RestorerFor[*infrav1.OpenStackMachine]{
175206
"spec": conversion.HashedFieldRestorer(
@@ -221,7 +252,14 @@ func (r *OpenStackMachineList) ConvertFrom(srcRaw ctrlconversion.Hub) error {
221252

222253
var _ ctrlconversion.Convertible = &OpenStackMachineTemplate{}
223254

224-
var v1alpha7OpenStackMachineTemplateRestorer = conversion.RestorerFor[*OpenStackMachineTemplate]{}
255+
var v1alpha7OpenStackMachineTemplateRestorer = conversion.RestorerFor[*OpenStackMachineTemplate]{
256+
"serverMetadata": conversion.HashedFieldRestorer(
257+
func(c *OpenStackMachineTemplate) *map[string]string {
258+
return &c.Spec.Template.Spec.ServerMetadata
259+
},
260+
restorev1alpha7ServerMetadata,
261+
),
262+
}
225263

226264
var v1alpha8OpenStackMachineTemplateRestorer = conversion.RestorerFor[*infrav1.OpenStackMachineTemplate]{
227265
"spec": conversion.HashedFieldRestorer(
@@ -282,6 +320,16 @@ func Convert_v1alpha8_OpenStackMachineSpec_To_v1alpha7_OpenStackMachineSpec(in *
282320
out.ImageUUID = in.Image.ID
283321
}
284322

323+
if len(in.ServerMetadata) > 0 {
324+
serverMetadata := make(map[string]string, len(in.ServerMetadata))
325+
for i := range in.ServerMetadata {
326+
key := in.ServerMetadata[i].Key
327+
value := in.ServerMetadata[i].Value
328+
serverMetadata[key] = value
329+
}
330+
out.ServerMetadata = serverMetadata
331+
}
332+
285333
return nil
286334
}
287335

@@ -306,6 +354,23 @@ func Convert_v1alpha7_OpenStackMachineSpec_To_v1alpha8_OpenStackMachineSpec(in *
306354
}
307355
out.Image = imageFilter
308356

357+
if len(in.ServerMetadata) > 0 {
358+
serverMetadata := make([]infrav1.ServerMetadata, 0, len(in.ServerMetadata))
359+
for k, v := range in.ServerMetadata {
360+
// Truncate key and value to 255 characters if required, as this
361+
// was not validated prior to v1alpha8
362+
if len(k) > 255 {
363+
k = k[:255]
364+
}
365+
if len(v) > 255 {
366+
v = v[:255]
367+
}
368+
369+
serverMetadata = append(serverMetadata, infrav1.ServerMetadata{Key: k, Value: v})
370+
}
371+
out.ServerMetadata = serverMetadata
372+
}
373+
309374
return nil
310375
}
311376

api/v1alpha7/conversion_test.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@ package v1alpha7
1919
import (
2020
"testing"
2121

22+
fuzz "github.com/google/gofuzz"
2223
"github.com/onsi/gomega"
24+
"k8s.io/apimachinery/pkg/api/apitesting/fuzzer"
2325
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2426
runtime "k8s.io/apimachinery/pkg/runtime"
27+
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
2528
"k8s.io/utils/pointer"
2629
utilconversion "sigs.k8s.io/cluster-api/util/conversion"
2730
"sigs.k8s.io/controller-runtime/pkg/conversion"
@@ -80,31 +83,70 @@ func TestFuzzyConversion(t *testing.T) {
8083
},
8184
})))
8285

86+
fuzzerFuncs := func(_ runtimeserializer.CodecFactory) []interface{} {
87+
return []interface{}{
88+
func(spec *OpenStackMachineSpec, c fuzz.Continue) {
89+
c.FuzzNoCustom(spec)
90+
91+
// RandString() generates strings up to 20
92+
// characters long. To exercise truncation of
93+
// long server metadata keys and values we need
94+
// the possibility of strings > 255 chars.
95+
genLongString := func() string {
96+
var ret string
97+
for len(ret) < 255 {
98+
ret += c.RandString()
99+
}
100+
return ret
101+
}
102+
103+
// Existing server metadata keys will be short. Add a random number of long ones.
104+
for c.RandBool() {
105+
if spec.ServerMetadata == nil {
106+
spec.ServerMetadata = map[string]string{}
107+
}
108+
spec.ServerMetadata[genLongString()] = c.RandString()
109+
}
110+
111+
// Randomly make some server metadata values long.
112+
for k := range spec.ServerMetadata {
113+
if c.RandBool() {
114+
spec.ServerMetadata[k] = genLongString()
115+
}
116+
}
117+
},
118+
}
119+
}
120+
83121
t.Run("for OpenStackMachine", runParallel(utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{
84122
Hub: &infrav1.OpenStackMachine{},
85123
Spoke: &OpenStackMachine{},
86124
HubAfterMutation: ignoreDataAnnotation,
125+
FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs},
87126
})))
88127

89128
t.Run("for OpenStackMachine with mutate", runParallel(testhelpers.FuzzMutateTestFunc(testhelpers.FuzzMutateTestFuncInput{
90129
FuzzTestFuncInput: utilconversion.FuzzTestFuncInput{
91130
Hub: &infrav1.OpenStackMachine{},
92131
Spoke: &OpenStackMachine{},
93132
HubAfterMutation: ignoreDataAnnotation,
133+
FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs},
94134
},
95135
})))
96136

97137
t.Run("for OpenStackMachineTemplate", runParallel(utilconversion.FuzzTestFunc(utilconversion.FuzzTestFuncInput{
98138
Hub: &infrav1.OpenStackMachineTemplate{},
99139
Spoke: &OpenStackMachineTemplate{},
100140
HubAfterMutation: ignoreDataAnnotation,
141+
FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs},
101142
})))
102143

103144
t.Run("for OpenStackMachineTemplate with mutate", runParallel(testhelpers.FuzzMutateTestFunc(testhelpers.FuzzMutateTestFuncInput{
104145
FuzzTestFuncInput: utilconversion.FuzzTestFuncInput{
105146
Hub: &infrav1.OpenStackMachineTemplate{},
106147
Spoke: &OpenStackMachineTemplate{},
107148
HubAfterMutation: ignoreDataAnnotation,
149+
FuzzerFuncs: []fuzzer.FuzzerFuncs{fuzzerFuncs},
108150
},
109151
})))
110152
}

api/v1alpha7/zz_generated.conversion.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

api/v1alpha8/openstackmachine_types.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,9 @@ type OpenStackMachineSpec struct {
7272
Tags []string `json:"tags,omitempty"`
7373

7474
// Metadata mapping. Allows you to create a map of key value pairs to add to the server instance.
75-
ServerMetadata map[string]string `json:"serverMetadata,omitempty"`
75+
// +listType=map
76+
// +listMapKey=key
77+
ServerMetadata []ServerMetadata `json:"serverMetadata,omitempty"`
7678

7779
// Config Drive support
7880
ConfigDrive *bool `json:"configDrive,omitempty"`
@@ -95,6 +97,16 @@ type OpenStackMachineSpec struct {
9597
IdentityRef *OpenStackIdentityReference `json:"identityRef,omitempty"`
9698
}
9799

100+
type ServerMetadata struct {
101+
// Key is the server metadata key
102+
// kubebuilder:validation:MaxLength:=255
103+
Key string `json:"key"`
104+
105+
// Value is the server metadata value
106+
// kubebuilder:validation:MaxLength:=255
107+
Value string `json:"value"`
108+
}
109+
98110
// OpenStackMachineStatus defines the observed state of OpenStackMachine.
99111
type OpenStackMachineStatus struct {
100112
// Ready is true when the provider resource is ready.

0 commit comments

Comments
 (0)