8000 Allow BuildRequestBody() to work with collection of structs · gophercloud/gophercloud@04387f1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 04387f1

Browse files
authored
Allow BuildRequestBody() to work with collection of structs
When passing an array or a slice to `BuildRequestBody()`, the `parent` string becomes mandatory. This makes it possible to build requests for bulk operations.
1 parent 335a41f commit 04387f1

File tree

1 file changed

+45
-7
lines changed

1 file changed

+45
-7
lines changed

params.go

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,11 @@ import (
1111
)
1212

1313
/*
14-
BuildRequestBody builds a map[string]interface from the given `struct`. If
15-
parent is not an empty string, the final map[string]interface returned will
16-
encapsulate the built one. For example:
14+
BuildRequestBody builds a map[string]interface from the given `struct`, or
15+
collection of `structs`. If parent is not an empty string, the final
16+
map[string]interface returned will encapsulate the built one. Parent is
17+
required when passing a list of `structs`.
18+
For example:
1719
1820
disk := 1
1921
createOpts := flavors.CreateOpts{
@@ -27,7 +29,29 @@ encapsulate the built one. For example:
2729
2830
body, err := gophercloud.BuildRequestBody(createOpts, "flavor")
2931
30-
The above example can be run as-is, however it is recommended to look at how
32+
33+
opts := []rules.CreateOpts{
34+
{
35+
Direction: "ingress",
36+
PortRangeMin: 80,
37+
EtherType: rules.EtherType4,
38+
PortRangeMax: 80,
39+
Protocol: "tcp",
40+
SecGroupID: "a7734e61-b545-452d-a3cd-0189cbd9747a",
41+
},
42+
{
43+
Direction: "ingress",
44+
PortRangeMin: 443,
45+
EtherType: rules.EtherType4,
46+
PortRangeMax: 443,
47+
Protocol: "tcp",
48+
SecGroupID: "a7734e61-b545-452d-a3cd-0189cbd9747a",
49+
},
50+
}
51+
52+
body, err := gophercloud.BuildRequestBody(opts, "security_group_rules")
53+
54+
The above examples can be run as-is, however it is recommended to look at how
3155
BuildRequestBody is used within Gophercloud to more fully understand how it
3256
fits within the request process as a whole rather than use it directly as shown
3357
above.
@@ -44,7 +68,8 @@ func BuildRequestBody(opts any, parent string) (map[string]any, error) {
4468
}
4569

4670
optsMap := make(map[string]any)
47-
if optsValue.Kind() == reflect.Struct {
71+
switch optsValue.Kind() {
72+
case reflect.Struct:
4873
//fmt.Printf("optsValue.Kind() is a reflect.Struct: %+v\n", optsValue.Kind())
4974
for i := 0; i < optsValue.NumField(); i++ {
5075
v := optsValue.Field(i)
@@ -184,9 +209,22 @@ func BuildRequestBody(opts any, parent string) (map[string]any, error) {
184209
}
185210
//fmt.Printf("optsMap after parent added: %+v\n", optsMap)
186211
return optsMap, nil
212+
case reflect.Slice, reflect.Array:
213+
optsMaps := make([]map[string]any, optsValue.Len())
214+
for i := 0; i < optsValue.Len(); i++ {
215+
b, err := BuildRequestBody(optsValue.Index(i).Interface(), "")
216+
if err != nil {
217+
return nil, err
218+
}
219+
optsMaps[i] = b
220+
}
221+
if parent == "" {
222+
return nil, fmt.Errorf("Parent is required when passing an array or a slice.")
223+
}
224+
return map[string]any{parent: optsMaps}, nil
187225
}
188-
// Return an error if the underlying type of 'opts' isn't a struct.
189-
return nil, fmt.Errorf("Options type is not a struct.")
226+
// Return an error if we can't work with the underlying type of 'opts'
227+
return nil, fmt.Errorf("Options type is not a struct, a slice, or an array.")
190228
}
191229

192230
// EnabledState is a convenience type, mostly used in Create and Update

0 commit comments

Comments
 (0)
0