11package packet
22
33import (
4+ "errors"
45 "fmt"
5- "log"
66 "time"
77
88 "github.com/hashicorp/terraform/helper/resource"
@@ -146,22 +146,23 @@ func resourcePacketDeviceCreate(d *schema.ResourceData, meta interface{}) error
146146 }
147147 }
148148
149- log .Printf ("[DEBUG] Device create configuration: %#v" , createRequest )
150-
151149 newDevice , _ , err := client .Devices .Create (createRequest )
152150 if err != nil {
153- return fmt . Errorf ( "Error creating device: %s" , err )
151+ return friendlyError ( err )
154152 }
155153
156- // Assign the device id
157154 d .SetId (newDevice .ID )
158155
159- log .Printf ("[INFO] Device ID: %s" , d .Id ())
160-
161- _ , err = WaitForDeviceAttribute (d , "active" , []string {"queued" , "provisioning" }, "state" , meta )
156+ // Wait for the device so we can get the networking attributes that show up after a while.
157+ _ , err = waitForDeviceAttribute (d , "active" , []string {"queued" , "provisioning" }, "state" , meta )
162158 if err != nil {
163- return fmt .Errorf (
164- "Error waiting for device (%s) to become ready: %s" , d .Id (), err )
159+ if isForbidden (err ) {
160+ // If the device doesn't get to the active state, we can't recover it from here.
161+ d .SetId ("" )
162+
163+ return errors .New ("provisioning time limit exceeded; the Packet team will investigate" )
164+ }
165+ return err
165166 }
166167
167168 return resourcePacketDeviceRead (d , meta )
@@ -170,10 +171,17 @@ func resourcePacketDeviceCreate(d *schema.ResourceData, meta interface{}) error
170171func resourcePacketDeviceRead (d * schema.ResourceData , meta interface {}) error {
171172 client := meta .(* packngo.Client )
172173
173- // Retrieve the device properties for updating the state
174174 device , _ , err := client .Devices .Get (d .Id ())
175175 if err != nil {
176- return fmt .Errorf ("Error retrieving device: %s" , err )
176+ err = friendlyError (err )
177+
178+ // If the device somehow already destroyed, mark as succesfully gone.
179+ if isNotFound (err ) {
180+ d .SetId ("" )
181+ return nil
182+ }
183+
184+ return err
177185 }
178186
179187 d .Set ("name" , device .Hostname )
@@ -186,35 +194,36 @@ func resourcePacketDeviceRead(d *schema.ResourceData, meta interface{}) error {
186194 d .Set ("created" , device .Created )
187195 d .Set ("updated" , device .Updated )
188196
189- tags := make ([]string , 0 )
197+ tags := make ([]string , 0 , len ( device . Tags ) )
190198 for _ , tag := range device .Tags {
191199 tags = append (tags , tag )
192200 }
193201 d .Set ("tags" , tags )
194202
195- provisionerAddress := ""
196-
197- networks := make ([]map [string ]interface {}, 0 , 1 )
203+ var (
204+ host string
205+ networks = make ([]map [string ]interface {}, 0 , 1 )
206+ )
198207 for _ , ip := range device .Network {
199- network := make (map [string ]interface {})
200- network ["address" ] = ip .Address
201- network ["gateway" ] = ip .Gateway
202- network ["family" ] = ip .Family
203- network ["cidr" ] = ip .Cidr
204- network ["public" ] = ip .Public
208+ network := map [string ]interface {}{
209+ "address" : ip .Address ,
210+ "gateway" : ip .Gateway ,
211+ "family" : ip .Family ,
212+ "cidr" : ip .Cidr ,
213+ "public" : ip .Public ,
214+ }
205215 networks = append (networks , network )
216+
206217 if ip .Family == 4 && ip .Public == true {
207- provisionerAddress = ip .Address
218+ host = ip .Address
208219 }
209220 }
210221 d .Set ("network" , networks )
211222
212- log .Printf ("[DEBUG] Provisioner Address set to %v" , provisionerAddress )
213-
214- if provisionerAddress != "" {
223+ if host != "" {
215224 d .SetConnInfo (map [string ]string {
216225 "type" : "ssh" ,
217- "host" : provisionerAddress ,
226+ "host" : host ,
218227 })
219228 }
220229
@@ -224,19 +233,15 @@ func resourcePacketDeviceRead(d *schema.ResourceData, meta interface{}) error {
224233func resourcePacketDeviceUpdate (d * schema.ResourceData , meta interface {}) error {
225234 client := meta .(* packngo.Client )
226235
227- if d .HasChange ("locked" ) && d . Get ( "locked" ).( bool ) {
228- _ , err := client . Devices . Lock ( d . Id () )
229-
230- if err != nil {
231- return fmt . Errorf (
232- "Error locking device (%s): %s" , d . Id (), err )
236+ if d .HasChange ("locked" ) {
237+ var action func ( string ) ( * packngo. Response , error )
238+ if d . Get ( "locked" ).( bool ) {
239+ action = client . Devices . Lock
240+ } else {
241+ action = client . Devices . Unlock
233242 }
234- } else if d .HasChange ("locked" ) {
235- _ , err := client .Devices .Unlock (d .Id ())
236-
237- if err != nil {
238- return fmt .Errorf (
239- "Error unlocking device (%s): %s" , d .Id (), err )
243+ if _ , err := action (d .Id ()); err != nil {
244+ return friendlyError (err )
240245 }
241246 }
242247
@@ -246,22 +251,14 @@ func resourcePacketDeviceUpdate(d *schema.ResourceData, meta interface{}) error
246251func resourcePacketDeviceDelete (d * schema.ResourceData , meta interface {}) error {
247252 client := meta .(* packngo.Client )
248253
249- log .Printf ("[INFO] Deleting device: %s" , d .Id ())
250254 if _ , err := client .Devices .Delete (d .Id ()); err != nil {
251- return fmt . Errorf ( "Error deleting device: %s" , err )
255+ return friendlyError ( err )
252256 }
253257
254258 return nil
255259}
256260
257- func WaitForDeviceAttribute (
258- d * schema.ResourceData , target string , pending []string , attribute string , meta interface {}) (interface {}, error ) {
259- // Wait for the device so we can get the networking attributes
260- // that show up after a while
261- log .Printf (
262- "[INFO] Waiting for device (%s) to have %s of %s" ,
263- d .Id (), attribute , target )
264-
261+ func waitForDeviceAttribute (d * schema.ResourceData , target string , pending []string , attribute string , meta interface {}) (interface {}, error ) {
265262 stateConf := & resource.StateChangeConf {
266263 Pending : pending ,
267264 Target : target ,
@@ -270,47 +267,37 @@ func WaitForDeviceAttribute(
270267 Delay : 10 * time .Second ,
271268 MinTimeout : 3 * time .Second ,
272269 }
273-
274270 return stateConf .WaitForState ()
275271}
276272
277- func newDeviceStateRefreshFunc (
278- d * schema.ResourceData , attribute string , meta interface {}) resource.StateRefreshFunc {
273+ func newDeviceStateRefreshFunc (d * schema.ResourceData , attribute string , meta interface {}) resource.StateRefreshFunc {
279274 client := meta .(* packngo.Client )
275+
280276 return func () (interface {}, string , error ) {
281- err := resourcePacketDeviceRead (d , meta )
282- if err != nil {
277+ if err := resourcePacketDeviceRead (d , meta ); err != nil {
283278 return nil , "" , err
284279 }
285280
286- // See if we can access our attribute
287281 if attr , ok := d .GetOk (attribute ); ok {
288- // Retrieve the device properties
289282 device , _ , err := client .Devices .Get (d .Id ())
290283 if err != nil {
291- return nil , "" , fmt . Errorf ( "Error retrieving device: %s" , err )
284+ return nil , "" , friendlyError ( err )
292285 }
293-
294286 return & device , attr .(string ), nil
295287 }
296288
297289 return nil , "" , nil
298290 }
299291}
300292
301- // Powers on the device and waits for it to be active
293+ // powerOnAndWait Powers on the device and waits for it to be active.
302294func powerOnAndWait (d * schema.ResourceData , meta interface {}) error {
303295 client := meta .(* packngo.Client )
304296 _ , err := client .Devices .PowerOn (d .Id ())
305297 if err != nil {
306- return err
307- }
308-
309- // Wait for power on
310- _ , err = WaitForDeviceAttribute (d , "active" , []string {"off" }, "state" , client )
311- if err != nil {
312- return err
298+ return friendlyError (err )
313299 }
314300
315- return nil
301+ _ , err = waitForDeviceAttribute (d , "active" , []string {"off" }, "state" , client )
302+ return err
316303}
0 commit comments