@@ -2191,39 +2191,86 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error
21912191 return err
21922192 }
21932193
2194- md := flattenMetadataBeta(instance.Metadata )
2194+ {{ if ne $ .TargetVersionName ` ga` -}}
2195+ // Read from state before calling the helper, which will overwrite scheduling with the API
2196+ // response. The API doesn't persist nanos, so we restore it afterward to avoid a diff.
2197+ savedNanos, hadNanos := d.GetOk (" scheduling.0.graceful_shutdown.0.max_duration.0.nanos" )
2198+ {{- end }}
2199+
2200+ zone := tpgresource.GetResourceNameFromSelfLink (instance.Zone )
2201+
2202+ if err := populateComputeInstanceResourceData(d, instance, project, zone, config); err != nil {
2203+ return err
2204+ }
21952205
21962206 // If the existing state contains " metadata_startup_script" instead of " metadata.startup-script" ,
21972207 // we should move the remote metadata.startup -script to metadata_startup_script to avoid
21982208 // specifying it in two places.
21992209 if _, ok := d.GetOk (" metadata_startup_script" ); ok {
2210+ md := d.Get (" metadata" ). (map[string]interface{})
22002211 if err := d.Set (" metadata_startup_script" , md[" startup-script" ]); err != nil {
22012212 return fmt.Errorf (" Error setting metadata_startup_script: %s " , err)
22022213 }
2203-
22042214 delete(md, " startup-script" )
2215+ if err := d.Set (" metadata" , md); err != nil {
2216+ return fmt.Errorf (" Error setting metadata: %s " , err)
2217+ }
22052218 }
22062219
2207- if err = d.Set (" metadata" , md); err != nil {
2208- return fmt.Errorf (" Error setting metadata: %s " , err)
2220+ // Fall back on internal ip if there is no external ip. This makes sense in the situation where
2221+ // terraform is being used on a cloud instance and can therefore access the instances it creates
2222+ // via their internal ips.
2223+ networkInterfacesRaw, err := networkInterfacesToInterface(instance.NetworkInterfaces )
2224+ if err != nil {
2225+ return err
22092226 }
2210-
2211- if err := d.Set (" metadata_fingerprint" , instance.Metadata.Fingerprint ); err != nil {
2212- return fmt.Errorf (" Error setting metadata_fingerprint: %s " , err)
2227+ _, _, internalIP, externalIP, err := flattenNetworkInterfaces(d, config, networkInterfacesRaw)
2228+ if err != nil {
2229+ return err
2230+ }
2231+ sshIP := externalIP
2232+ if sshIP == " " {
2233+ sshIP = internalIP
22132234 }
2235+ d.SetConnInfo (map[string]string{
2236+ " type" : " ssh" ,
2237+ " host" : sshIP,
2238+ })
22142239
22152240 {{ if ne $ .TargetVersionName ` ga` -}}
2216- if instance.PartnerMetadata != nil {
2217- partnerMetadata, err := flattenPartnerMetadata(convertPartnerMetadataFromCompute(instance.PartnerMetadata ))
2218- if err != nil {
2219- return fmt.Errorf (" Error parsing partner metadata: %s " , err)
2220- }
2221- if err = d.Set (" partner_metadata" , partnerMetadata); err != nil {
2222- return fmt.Errorf (" Error setting partner metadata: %s " , err)
2241+ // Workaround: restore nanos from state since the API doesn't persist it (see comment above).
2242+ if hadNanos {
2243+ scheduling := flattenScheduling(instance.Scheduling )
2244+ graceful_shutdown := scheduling[0][" graceful_shutdown" ]. ([]interface{})[0]. (map[string]interface{})
2245+ max_duration := graceful_shutdown[" max_duration" ]. ([]interface{})[0]. (map[string]interface{})
2246+ max_duration[" nanos" ] = int64(savedNanos. (int))
2247+
2248+ graceful_shutdown[" max_duration" ] = []interface{}{max_duration}
2249+ scheduling[0][" graceful_shutdown" ] = []interface{}{graceful_shutdown}
2250+ if err := d.Set (" scheduling" , scheduling); err != nil {
2251+ return fmt.Errorf (" Error setting scheduling: %s " , err)
22232252 }
22242253 }
22252254 {{- end }}
22262255
2256+ d.SetId (fmt.Sprintf (" projects/%s /zones/%s /instances/%s " , project, zone, instance.Name ))
2257+
2258+ if err := tpgresource.DeletionPolicyReadDefault (d, config, " DELETE" ); err != nil {
2259+ return err
2260+ }
2261+
2262+ return nil
2263+ }
2264+
2265+ func populateComputeInstanceResourceData(d *schema.ResourceData , instance *compute.Instance , project, zone string, config *transport_tpg.Config ) error {
2266+ if err := d.Set (" metadata" , flattenMetadataBeta(instance.Metadata )); err != nil {
2267+ return fmt.Errorf (" Error setting metadata: %s " , err)
2268+ }
2269+
2270+ if err := d.Set (" metadata_fingerprint" , instance.Metadata.Fingerprint ); err != nil {
2271+ return fmt.Errorf (" Error setting metadata_fingerprint: %s " , err)
2272+ }
2273+
22272274 if err := d.Set (" can_ip_forward" , instance.CanIpForward ); err != nil {
22282275 return fmt.Errorf (" Error setting can_ip_forward: %s " , err)
22292276 }
@@ -2242,33 +2289,18 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error
22422289 return err
22432290 }
22442291 // Set the networks
2245- // Use the first external IP found for the default connection info.
22462292 networkInterfacesRaw, err := networkInterfacesToInterface(instance.NetworkInterfaces )
22472293 if err != nil {
22482294 return err
22492295 }
2250- networkInterfaces, _, internalIP, externalIP , err := flattenNetworkInterfaces(d, config, networkInterfacesRaw)
2296+ networkInterfaces, _, _, _ , err := flattenNetworkInterfaces(d, config, networkInterfacesRaw)
22512297 if err != nil {
22522298 return err
22532299 }
22542300 if err := d.Set (" network_interface" , networkInterfaces); err != nil {
22552301 return err
22562302 }
22572303
2258- // Fall back on internal ip if there is no external ip. This makes sense in the situation where
2259- // terraform is being used on a cloud instance and can therefore access the instances it creates
2260- // via their internal ips.
2261- sshIP := externalIP
2262- if sshIP == " " {
2263- sshIP = internalIP
2264- }
2265-
2266- // Initialize the connection info
2267- d.SetConnInfo (map[string]string{
2268- " type" : " ssh" ,
2269- " host" : sshIP,
2270- })
2271-
22722304 // Set the tags fingerprint if there is one.
22732305 if instance.Tags != nil {
22742306 if err := d.Set (" tags_fingerprint" , instance.Tags.Fingerprint ); err != nil {
@@ -2399,14 +2431,11 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error
23992431 // Remove nils from map in case there were disks in the config that were not present on read;
24002432 // i.e. a disk was detached out of band
24012433 ads := []map[string]interface{}{}
2402- for _, d := range attachedDisks {
2403- if d != nil {
2404- ads = append(ads, d )
2434+ for _, ad := range attachedDisks {
2435+ if ad != nil {
2436+ ads = append(ads, ad )
24052437 }
24062438 }
2407-
2408- zone := tpgresource.GetResourceNameFromSelfLink (instance.Zone )
2409-
24102439 if err := d.Set (" service_account" , flattenServiceAccounts(serviceAccountsToInterface(instance.ServiceAccounts ))); err != nil {
24112440 return fmt.Errorf (" Error setting service_account: %s " , err)
24122441 }
@@ -2417,27 +2446,9 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error
24172446 return fmt.Errorf (" Error setting scratch_disk: %s " , err)
24182447 }
24192448
2420- {{ if eq $ .TargetVersionName ` ga` -}}
24212449 if err := d.Set (" scheduling" , flattenScheduling(instance.Scheduling )); err != nil {
24222450 return fmt.Errorf (" Error setting scheduling: %s " , err)
24232451 }
2424- {{ else -}}
2425- // Workaroud: API doesn't update the scheduling.graceful_shutdown.max_duration.nanos field.
2426- // To avoid diff, we need to set the value from the state not from API response.
2427- scheduling := flattenScheduling(instance.Scheduling )
2428- if nanos, ok := d.GetOk (" scheduling.0.graceful_shutdown.0.max_duration.0.nanos" ); ok {
2429- graceful_shutdown := scheduling[0][" graceful_shutdown" ]. ([]interface{})[0]. (map[string]interface{})
2430- max_duration := graceful_shutdown[" max_duration" ]. ([]interface{})[0]. (map[string]interface{})
2431- max_duration[" nanos" ] = int64(nanos. (int))
2432-
2433- graceful_shutdown[" max_duration" ] = []interface{}{max_duration}
2434- scheduling[0][" graceful_shutdown" ] = []interface{}{graceful_shutdown}
2435- }
2436- if err := d.Set (" scheduling" , scheduling); err != nil {
2437- return fmt.Errorf (" Error setting scheduling: %s " , err)
2438- }
2439- {{- end }}
2440-
24412452 if err := d.Set (" guest_accelerator" , flattenGuestAccelerators(guestAcceleratorsToInterface(instance.GuestAccelerators ))); err != nil {
24422453 return fmt.Errorf (" Error setting guest_accelerator: %s " , err)
24432454 }
@@ -2538,6 +2549,18 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error
25382549 return fmt.Errorf (" Error setting instance_encryption_key: %s " , err)
25392550 }
25402551
2552+ {{- if ne $ .TargetVersionName ` ga` }}
2553+ if instance.PartnerMetadata != nil {
2554+ partnerMetadata, err := flattenPartnerMetadata(convertPartnerMetadataFromCompute(instance.PartnerMetadata ))
2555+ if err != nil {
2556+ return fmt.Errorf (" Error parsing partner metadata: %s " , err)
2557+ }
2558+ if err = d.Set (" partner_metadata" , partnerMetadata); err != nil {
2559+ return fmt.Errorf (" Error setting partner metadata: %s " , err)
2560+ }
2561+ }
2562+ {{- end }}
2563+
25412564 {{- if ne $ .TargetVersionName ` ga` }}
25422565 // If not forced to false, upgrading to a new provider version and subsequently changing a vm property
25432566 // will trigger replacement when erase_windows_vss_signature = null in state is changed to false as part of a refresh
@@ -2548,13 +2571,6 @@ func resourceComputeInstanceRead(d *schema.ResourceData, meta interface{}) error
25482571 }
25492572 {{- end }}
25502573
2551- d.SetId (fmt.Sprintf (" projects/%s /zones/%s /instances/%s " , project, zone, instance.Name ))
2552-
2553-
2554- if err := tpgresource.DeletionPolicyReadDefault (d, config, " DELETE" ); err != nil {
2555- return err
2556- }
2557-
25582574 return nil
25592575}
25602576
0 commit comments