~bigkevmcd/goose/fix-for-swift-headers

« back to all changes in this revision

Viewing changes to nova/json.go

[r=wallyworld],[bug=1188815] Support string id for SecurityGroup et al

Openstack with Quantum/Grizzly uses string ids for SecurityGroup
and other similar data structures. Goose was written for deployments
that use int ids. This branch fixes that issue using the pattern
already in palce to deal with HP Cloud vs Canonistack for
ServerDetail et al ids.

https://codereview.appspot.com/10527043/

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
        "strconv"
15
15
)
16
16
 
17
 
type genericId struct {
18
 
        Id interface{} `json:"id"`
19
 
}
20
 
 
21
 
func (id genericId) String() string {
22
 
        if id.Id == nil {
23
 
                return ""
24
 
        }
25
 
        if fid, ok := id.Id.(float64); ok {
26
 
                return fmt.Sprint(int(fid))
27
 
        }
28
 
        return fmt.Sprint(id.Id)
29
 
}
 
17
const (
 
18
        idTag            = "id"
 
19
        instanceIdTag    = "instance_id"
 
20
        groupIdTag       = "group_id"
 
21
        parentGroupIdTag = "parent_group_id"
 
22
)
30
23
 
31
24
var useNumericIds bool = false
32
25
 
43
36
        return result
44
37
}
45
38
 
 
39
// getIdAsString extracts the field with the specified tag from the json data
 
40
// and returns it converted to a string.
 
41
func getIdAsString(b []byte, tag string) (string, error) {
 
42
        var out map[string]interface{}
 
43
        if err := json.Unmarshal(b, &out); err != nil {
 
44
                return "", err
 
45
        }
 
46
        if val, ok := out[tag]; !ok {
 
47
                return "", nil
 
48
        } else {
 
49
                if floatVal, ok := val.(float64); ok {
 
50
                        return fmt.Sprint(int(floatVal)), nil
 
51
                } else {
 
52
                        return fmt.Sprint(val), nil
 
53
                }
 
54
        }
 
55
        panic("unreachable")
 
56
}
 
57
 
46
58
// appendJSON marshals the given attribute value and appends it as an encoded value to the given json data.
47
59
// The newly encode (attr, value) is inserted just before the closing "}" in the json data.
48
60
func appendJSON(data []byte, attr string, value interface{}) ([]byte, error) {
59
71
 
60
72
func (entity *Entity) UnmarshalJSON(b []byte) error {
61
73
        var je jsonEntity = jsonEntity(*entity)
62
 
        if err := json.Unmarshal(b, &je); err != nil {
63
 
                return err
64
 
        }
65
 
        var id genericId
66
 
        if err := json.Unmarshal(b, &id); err != nil {
67
 
                return err
68
 
        }
69
 
        je.Id = id.String()
 
74
        var err error
 
75
        if err = json.Unmarshal(b, &je); err != nil {
 
76
                return err
 
77
        }
 
78
        if je.Id, err = getIdAsString(b, idTag); err != nil {
 
79
                return err
 
80
        }
70
81
        *entity = Entity(je)
71
82
        return nil
72
83
}
78
89
                return nil, err
79
90
        }
80
91
        id := convertId(entity.Id)
81
 
        return appendJSON(data, "Id", id)
 
92
        return appendJSON(data, idTag, id)
82
93
}
83
94
 
84
95
type jsonFlavorDetail FlavorDetail
85
96
 
86
97
func (flavorDetail *FlavorDetail) UnmarshalJSON(b []byte) error {
87
98
        var jfd jsonFlavorDetail = jsonFlavorDetail(*flavorDetail)
88
 
        if err := json.Unmarshal(b, &jfd); err != nil {
89
 
                return err
90
 
        }
91
 
        var id genericId
92
 
        if err := json.Unmarshal(b, &id); err != nil {
93
 
                return err
94
 
        }
95
 
        jfd.Id = id.String()
 
99
        var err error
 
100
        if err = json.Unmarshal(b, &jfd); err != nil {
 
101
                return err
 
102
        }
 
103
        if jfd.Id, err = getIdAsString(b, idTag); err != nil {
 
104
                return err
 
105
        }
96
106
        *flavorDetail = FlavorDetail(jfd)
97
107
        return nil
98
108
}
104
114
                return nil, err
105
115
        }
106
116
        id := convertId(flavorDetail.Id)
107
 
        return appendJSON(data, "Id", id)
 
117
        return appendJSON(data, idTag, id)
108
118
}
109
119
 
110
120
type jsonServerDetail ServerDetail
111
121
 
112
122
func (serverDetail *ServerDetail) UnmarshalJSON(b []byte) error {
113
123
        var jsd jsonServerDetail = jsonServerDetail(*serverDetail)
114
 
        if err := json.Unmarshal(b, &jsd); err != nil {
115
 
                return err
116
 
        }
117
 
        var id genericId
118
 
        if err := json.Unmarshal(b, &id); err != nil {
119
 
                return err
120
 
        }
121
 
        jsd.Id = id.String()
 
124
        var err error
 
125
        if err = json.Unmarshal(b, &jsd); err != nil {
 
126
                return err
 
127
        }
 
128
        if jsd.Id, err = getIdAsString(b, idTag); err != nil {
 
129
                return err
 
130
        }
122
131
        *serverDetail = ServerDetail(jsd)
123
132
        return nil
124
133
}
130
139
                return nil, err
131
140
        }
132
141
        id := convertId(serverDetail.Id)
133
 
        return appendJSON(data, "Id", id)
134
 
}
135
 
 
136
 
type genericInstanceId struct {
137
 
        InstanceId interface{} `json:"instance_id"`
138
 
}
139
 
 
140
 
func (id genericInstanceId) String() string {
141
 
        if id.InstanceId == nil {
142
 
                return ""
143
 
        }
144
 
        if fid, ok := id.InstanceId.(float64); ok {
145
 
                return fmt.Sprint(int(fid))
146
 
        }
147
 
        return fmt.Sprint(id.InstanceId)
 
142
        return appendJSON(data, idTag, id)
148
143
}
149
144
 
150
145
type jsonFloatingIP FloatingIP
151
146
 
152
147
func (floatingIP *FloatingIP) UnmarshalJSON(b []byte) error {
153
148
        var jfip jsonFloatingIP = jsonFloatingIP(*floatingIP)
154
 
        if err := json.Unmarshal(b, &jfip); err != nil {
155
 
                return err
156
 
        }
157
 
        var id genericInstanceId
158
 
        if err := json.Unmarshal(b, &id); err != nil {
159
 
                return err
160
 
        }
161
 
        instId := id.String()
162
 
        if instId != "" {
163
 
                strId := instId
 
149
        var err error
 
150
        if err = json.Unmarshal(b, &jfip); err != nil {
 
151
                return err
 
152
        }
 
153
        if instIdStr, err := getIdAsString(b, instanceIdTag); err != nil {
 
154
                return err
 
155
        } else if instIdStr != "" {
 
156
                strId := instIdStr
164
157
                jfip.InstanceId = &strId
165
158
        }
 
159
        if jfip.Id, err = getIdAsString(b, idTag); err != nil {
 
160
                return err
 
161
        }
166
162
        *floatingIP = FloatingIP(jfip)
167
163
        return nil
168
164
}
173
169
        if err != nil {
174
170
                return nil, err
175
171
        }
 
172
        id := convertId(floatingIP.Id)
 
173
        data, err = appendJSON(data, idTag, id)
 
174
        if err != nil {
 
175
                return nil, err
 
176
        }
176
177
        if floatingIP.InstanceId == nil {
177
178
                return data, nil
178
179
        }
179
 
        id := convertId(*floatingIP.InstanceId)
180
 
        return appendJSON(data, "instance_id", id)
 
180
        instId := convertId(*floatingIP.InstanceId)
 
181
        return appendJSON(data, instanceIdTag, instId)
 
182
}
 
183
 
 
184
type jsonSecurityGroup SecurityGroup
 
185
 
 
186
func (securityGroup *SecurityGroup) UnmarshalJSON(b []byte) error {
 
187
        var jsg jsonSecurityGroup = jsonSecurityGroup(*securityGroup)
 
188
        var err error
 
189
        if err = json.Unmarshal(b, &jsg); err != nil {
 
190
                return err
 
191
        }
 
192
        if jsg.Id, err = getIdAsString(b, idTag); err != nil {
 
193
                return err
 
194
        }
 
195
        *securityGroup = SecurityGroup(jsg)
 
196
        return nil
 
197
}
 
198
 
 
199
func (securityGroup SecurityGroup) MarshalJSON() ([]byte, error) {
 
200
        var jsg jsonSecurityGroup = jsonSecurityGroup(securityGroup)
 
201
        data, err := json.Marshal(&jsg)
 
202
        if err != nil {
 
203
                return nil, err
 
204
        }
 
205
        id := convertId(securityGroup.Id)
 
206
        return appendJSON(data, idTag, id)
 
207
}
 
208
 
 
209
type jsonSecurityGroupRule SecurityGroupRule
 
210
 
 
211
func (securityGroupRule *SecurityGroupRule) UnmarshalJSON(b []byte) error {
 
212
        var jsgr jsonSecurityGroupRule = jsonSecurityGroupRule(*securityGroupRule)
 
213
        var err error
 
214
        if err = json.Unmarshal(b, &jsgr); err != nil {
 
215
                return err
 
216
        }
 
217
        if jsgr.Id, err = getIdAsString(b, idTag); err != nil {
 
218
                return err
 
219
        }
 
220
        if jsgr.ParentGroupId, err = getIdAsString(b, parentGroupIdTag); err != nil {
 
221
                return err
 
222
        }
 
223
        *securityGroupRule = SecurityGroupRule(jsgr)
 
224
        return nil
 
225
}
 
226
 
 
227
func (securityGroupRule SecurityGroupRule) MarshalJSON() ([]byte, error) {
 
228
        var jsgr jsonSecurityGroupRule = jsonSecurityGroupRule(securityGroupRule)
 
229
        data, err := json.Marshal(&jsgr)
 
230
        if err != nil {
 
231
                return nil, err
 
232
        }
 
233
        id := convertId(securityGroupRule.Id)
 
234
        data, err = appendJSON(data, idTag, id)
 
235
        if err != nil {
 
236
                return nil, err
 
237
        }
 
238
        if securityGroupRule.ParentGroupId == "" {
 
239
                return data, nil
 
240
        }
 
241
        id = convertId(securityGroupRule.ParentGroupId)
 
242
        return appendJSON(data, parentGroupIdTag, id)
 
243
}
 
244
 
 
245
type jsonRuleInfo RuleInfo
 
246
 
 
247
func (ruleInfo *RuleInfo) UnmarshalJSON(b []byte) error {
 
248
        var jri jsonRuleInfo = jsonRuleInfo(*ruleInfo)
 
249
        var err error
 
250
        if err = json.Unmarshal(b, &jri); err != nil {
 
251
                return err
 
252
        }
 
253
        if jri.ParentGroupId, err = getIdAsString(b, parentGroupIdTag); err != nil {
 
254
                return err
 
255
        }
 
256
        if groupId, err := getIdAsString(b, groupIdTag); err != nil {
 
257
                return err
 
258
        } else if groupId != "" {
 
259
                strId := groupId
 
260
                jri.GroupId = &strId
 
261
        }
 
262
        *ruleInfo = RuleInfo(jri)
 
263
        return nil
 
264
}
 
265
 
 
266
func (ruleInfo RuleInfo) MarshalJSON() ([]byte, error) {
 
267
        var jri jsonRuleInfo = jsonRuleInfo(ruleInfo)
 
268
        data, err := json.Marshal(&jri)
 
269
        if err != nil {
 
270
                return nil, err
 
271
        }
 
272
        id := convertId(ruleInfo.ParentGroupId)
 
273
        data, err = appendJSON(data, parentGroupIdTag, id)
 
274
        if err != nil {
 
275
                return nil, err
 
276
        }
 
277
        if ruleInfo.GroupId == nil {
 
278
                return data, nil
 
279
        }
 
280
        id = convertId(*ruleInfo.GroupId)
 
281
        return appendJSON(data, groupIdTag, id)
181
282
}