@@ -19,9 +19,13 @@ package common
19
19
import (
20
20
"errors"
21
21
"fmt"
22
- "gopkg.in/yaml.v2"
23
22
"strings"
24
23
"time"
24
+
25
+ "encoding/json"
26
+ "sync"
27
+
28
+ "github.com/ghodss/yaml"
25
29
)
26
30
27
31
const (
@@ -38,7 +42,12 @@ const (
38
42
)
39
43
40
44
// UserData is a map of Name to user defined interface, serialized into a string
41
- type UserData map [string ]string
45
+ type UserData struct {
46
+ sync.Map
47
+ }
48
+
49
+ // UserDataMap is the standard Map version of UserMap, it is used to ease UserMap creation.
50
+ type UserDataMap map [string ]string
42
51
43
52
// LeasedResources is a list of resources name that used in order to create another resource by Mason
44
53
type LeasedResources []string
@@ -56,7 +65,7 @@ type Resource struct {
56
65
Owner string `json:"owner"`
57
66
LastUpdate time.Time `json:"lastupdate"`
58
67
// Customized UserData
59
- UserData UserData `json:"userdata"`
68
+ UserData * UserData `json:"userdata"`
60
69
}
61
70
62
71
// ResourceEntry is resource config format defined from config.yaml
@@ -87,7 +96,7 @@ func NewResource(name, rtype, state, owner string, t time.Time) Resource {
87
96
State : state ,
88
97
Owner : owner ,
89
98
LastUpdate : t ,
90
- UserData : map [ string ] string {},
99
+ UserData : & UserData {},
91
100
}
92
101
}
93
102
@@ -100,6 +109,15 @@ func NewResourcesFromConfig(e ResourceEntry) []Resource {
100
109
return resources
101
110
}
102
111
112
+ // UserDataFromMap returns a UserData from a map
113
+ func UserDataFromMap (m UserDataMap ) * UserData {
114
+ ud := & UserData {}
115
+ for k , v := range m {
116
+ ud .Store (k , v )
117
+ }
118
+ return ud
119
+ }
120
+
103
121
// UserDataNotFound will be returned if requested resource does not exist.
104
122
type UserDataNotFound struct {
105
123
ID string
@@ -144,40 +162,74 @@ func (r *ResTypes) Set(value string) error {
144
162
// GetName implements the Item interface used for storage
145
163
func (res Resource ) GetName () string { return res .Name }
146
164
165
+ // UnmarshalJSON implements JSON Unmarshaler interface
166
+ func (ud * UserData ) UnmarshalJSON (data []byte ) error {
167
+ tmpMap := UserDataMap {}
168
+ if err := json .Unmarshal (data , & tmpMap ); err != nil {
169
+ return err
170
+ }
171
+ ud .FromMap (tmpMap )
172
+ return nil
173
+ }
174
+
175
+ // MarshalJSON implents JSON Marshaler interface
176
+ func (ud * UserData ) MarshalJSON () ([]byte , error ) {
177
+ return json .Marshal (ud .ToMap ())
178
+ }
179
+
147
180
// Extract unmarshalls a string a given struct if it exists
148
- func (ud UserData ) Extract (id string , out interface {}) error {
149
- content , ok := ud [ id ]
181
+ func (ud * UserData ) Extract (id string , out interface {}) error {
182
+ content , ok := ud . Load ( id )
150
183
if ! ok {
151
184
return & UserDataNotFound {id }
152
185
}
153
- return yaml .Unmarshal ([]byte (content ), out )
186
+ return yaml .Unmarshal ([]byte (content .( string ) ), out )
154
187
}
155
188
156
189
// User Data are used to store custom information mainly by Mason and Masonable implementation.
157
190
// Mason used a LeasedResource keys to store information about other resources that used to
158
191
// create the given resource.
159
192
160
193
// Set marshalls a struct to a string into the UserData
161
- func (ud UserData ) Set (id string , in interface {}) error {
194
+ func (ud * UserData ) Set (id string , in interface {}) error {
162
195
b , err := yaml .Marshal (in )
163
196
if err != nil {
164
197
return err
165
198
}
166
- ud [ id ] = string (b )
199
+ ud . Store ( id , string (b ) )
167
200
return nil
168
201
}
169
202
170
203
// Update updates existing UserData with new UserData.
171
204
// If a key as an empty string, the key will be deleted
172
- func (ud UserData ) Update (new UserData ) {
173
- if new != nil {
174
- for id , content := range new {
175
- if content != "" {
176
- ud [id ] = content
177
- } else {
178
- delete (ud , id )
179
- }
205
+ func (ud * UserData ) Update (new * UserData ) {
206
+ if new == nil {
207
+ return
208
+ }
209
+ new .Range (func (key , value interface {}) bool {
210
+ if value .(string ) != "" {
211
+ ud .Store (key , value )
212
+ } else {
213
+ ud .Delete (key )
180
214
}
215
+ return true
216
+ })
217
+ }
218
+
219
+ // ToMap converts a UserData to UserDataMap
220
+ func (ud * UserData ) ToMap () UserDataMap {
221
+ m := UserDataMap {}
222
+ ud .Range (func (key , value interface {}) bool {
223
+ m [key .(string )] = value .(string )
224
+ return true
225
+ })
226
+ return m
227
+ }
228
+
229
+ // FromMap feels updates user data from a map
230
+ func (ud * UserData ) FromMap (m UserDataMap ) {
231
+ for key , value := range m {
232
+ ud .Store (key , value )
181
233
}
182
234
}
183
235
0 commit comments