@@ -6,13 +6,15 @@ import (
66 "strings"
77
88 "github.com/hashicorp/terraform/terraform"
9+ "github.com/mitchellh/mapstructure"
910)
1011
1112// ResourceData is used to query and set the attributes of a resource.
1213type ResourceData struct {
1314 schema map [string ]* Schema
1415 state * terraform.ResourceState
1516 diff * terraform.ResourceDiff
17+ set map [string ]string
1618}
1719
1820// Get returns the data for the given key, or nil if the key doesn't exist.
@@ -29,6 +31,19 @@ func (d *ResourceData) Get(key string) interface{} {
2931 return d .getObject ("" , parts , d .schema )
3032}
3133
34+ // Set sets the value for the given key.
35+ //
36+ // If the key is invalid or the value is not a correct type, an error
37+ // will be returned.
38+ func (d * ResourceData ) Set (key string , value interface {}) error {
39+ if d .set == nil {
40+ d .set = make (map [string ]string )
41+ }
42+
43+ parts := strings .Split (key , "." )
44+ return d .setObject ("" , parts , d .schema , value )
45+ }
46+
3247func (d * ResourceData ) get (
3348 k string ,
3449 parts []string ,
@@ -85,7 +100,12 @@ func (d *ResourceData) getList(
85100 // Special case if we're accessing the count of the list
86101 if idx == "#" {
87102 schema := & Schema {Type : TypeInt }
88- return d .get (k + ".#" , parts , schema )
103+ result := d .get (k + ".#" , parts , schema )
104+ if result == nil {
105+ result = 0
106+ }
107+
108+ return result
89109 }
90110
91111 key := fmt .Sprintf ("%s.%s" , k , idx )
@@ -112,17 +132,30 @@ func (d *ResourceData) getPrimitive(
112132 parts []string ,
113133 schema * Schema ) interface {} {
114134 var result string
135+ var resultSet bool
115136 if d .state != nil {
116- result = d .state .Attributes [k ]
137+ result , resultSet = d .state .Attributes [k ]
117138 }
118139
119140 if d .diff != nil {
120141 attrD , ok := d .diff .Attributes [k ]
121142 if ok {
122143 result = attrD .New
144+ resultSet = true
123145 }
124146 }
125147
148+ if d .set != nil {
149+ if v , ok := d .set [k ]; ok {
150+ result = v
151+ resultSet = true
152+ }
153+ }
154+
155+ if ! resultSet {
156+ return nil
157+ }
158+
126159 switch schema .Type {
127160 case TypeString :
128161 // Use the value as-is. We just put this case here to be explicit.
@@ -142,3 +175,55 @@ func (d *ResourceData) getPrimitive(
142175 panic (fmt .Sprintf ("Unknown type: %s" , schema .Type ))
143176 }
144177}
178+
179+ func (d * ResourceData ) setObject (
180+ k string ,
181+ parts []string ,
182+ schema map [string ]* Schema ,
183+ value interface {}) error {
184+ if len (parts ) > 0 {
185+ // We're setting a specific key in an object
186+ key := parts [0 ]
187+ parts = parts [1 :]
188+
189+ s , ok := schema [key ]
190+ if ! ok {
191+ return fmt .Errorf ("%s (internal): unknown key to set: %s" , k , key )
192+ }
193+
194+ if k != "" {
195+ // If we're not at the root, then we need to append
196+ // the key to get the full key path.
197+ key = fmt .Sprintf ("%s.%s" , k , key )
198+ }
199+
200+ return d .setPrimitive (key , s , value )
201+ }
202+
203+ panic ("can't set full object yet" )
204+ }
205+
206+ func (d * ResourceData ) setPrimitive (
207+ k string ,
208+ schema * Schema ,
209+ v interface {}) error {
210+ var set string
211+ switch schema .Type {
212+ case TypeString :
213+ if err := mapstructure .Decode (v , & set ); err != nil {
214+ return fmt .Errorf ("%s: %s" , k , err )
215+ }
216+ case TypeInt :
217+ var n int
218+ if err := mapstructure .Decode (v , & n ); err != nil {
219+ return fmt .Errorf ("%s: %s" , k , err )
220+ }
221+
222+ set = strconv .FormatInt (int64 (n ), 10 )
223+ default :
224+ return fmt .Errorf ("Unknown type: %s" , schema .Type )
225+ }
226+
227+ d .set [k ] = set
228+ return nil
229+ }
0 commit comments