6
6
7
7
"github.com/hashicorp/terraform/helper/schema"
8
8
strcase "github.com/stoewer/go-strcase"
9
+ computeBeta "google.golang.org/api/compute/v0.beta"
10
+ compute "google.golang.org/api/compute/v1"
9
11
)
10
12
11
13
func resourceComputeInstanceFromTemplate () * schema.Resource {
@@ -98,8 +100,26 @@ func resourceComputeInstanceFromTemplateCreate(d *schema.ResourceData, meta inte
98
100
return err
99
101
}
100
102
101
- // Force send all top-level fields in case they're overridden to zero values.
103
+ tpl , err := ParseInstanceTemplateFieldValue (d .Get ("source_instance_template" ).(string ), d , config )
104
+ if err != nil {
105
+ return err
106
+ }
107
+
108
+ it , err := config .clientComputeBeta .InstanceTemplates .Get (project , tpl .Name ).Do ()
109
+ if err != nil {
110
+ return err
111
+ }
112
+
113
+ instance .Disks , err = adjustInstanceFromTemplateDisks (d , config , it , zone , project )
114
+ if err != nil {
115
+ return err
116
+ }
117
+
118
+ // Force send all top-level fields that have been set in case they're overridden to zero values.
102
119
// TODO: consider doing so for nested fields as well.
120
+ // Initialize ForceSendFields to empty so we don't get things that the instance resource
121
+ // always force-sends.
122
+ instance .ForceSendFields = []string {}
103
123
for f , s := range computeInstanceFromTemplateSchema () {
104
124
// It seems that GetOkExists always returns true for sets.
105
125
// TODO: confirm this and file issue against Terraform core.
@@ -116,11 +136,6 @@ func resourceComputeInstanceFromTemplateCreate(d *schema.ResourceData, meta inte
116
136
}
117
137
}
118
138
119
- tpl , err := ParseInstanceTemplateFieldValue (d .Get ("source_instance_template" ).(string ), d , config )
120
- if err != nil {
121
- return err
122
- }
123
-
124
139
log .Printf ("[INFO] Requesting instance creation" )
125
140
op , err := config .clientComputeBeta .Instances .Insert (project , zone .Name , instance ).SourceInstanceTemplate (tpl .RelativeLink ()).Do ()
126
141
if err != nil {
@@ -140,3 +155,71 @@ func resourceComputeInstanceFromTemplateCreate(d *schema.ResourceData, meta inte
140
155
141
156
return resourceComputeInstanceRead (d , meta )
142
157
}
158
+
159
+ // Instances have disks spread across multiple schema properties. This function
160
+ // ensures that overriding one of these properties does not override the others.
161
+ func adjustInstanceFromTemplateDisks (d * schema.ResourceData , config * Config , it * computeBeta.InstanceTemplate , zone * compute.Zone , project string ) ([]* computeBeta.AttachedDisk , error ) {
162
+ disks := []* computeBeta.AttachedDisk {}
163
+ if _ , hasBootDisk := d .GetOk ("boot_disk" ); hasBootDisk {
164
+ bootDisk , err := expandBootDisk (d , config , zone , project )
165
+ if err != nil {
166
+ return nil , err
167
+ }
168
+ disks = append (disks , bootDisk )
169
+ } else {
170
+ // boot disk was not overridden, so use the one from the instance template
171
+ for _ , disk := range it .Properties .Disks {
172
+ if disk .Boot {
173
+ if dt := disk .InitializeParams .DiskType ; dt != "" {
174
+ // Instances need a URL for the disk type, but instance templates
175
+ // only have the name (since they're global).
176
+ disk .InitializeParams .DiskType = fmt .Sprintf ("zones/%s/diskTypes/%s" , zone .Name , dt )
177
+ }
178
+ disks = append (disks , disk )
179
+ break
180
+ }
181
+ }
182
+ }
183
+
184
+ if _ , hasScratchDisk := d .GetOk ("scratch_disk" ); hasScratchDisk {
185
+ scratchDisks , err := expandScratchDisks (d , config , zone , project )
186
+ if err != nil {
187
+ return nil , err
188
+ }
189
+ disks = append (disks , scratchDisks ... )
190
+ } else {
191
+ // scratch disks were not overridden, so use the ones from the instance template
192
+ for _ , disk := range it .Properties .Disks {
193
+ if disk .Type == "SCRATCH" {
194
+ disks = append (disks , disk )
195
+ }
196
+ }
197
+ }
198
+
199
+ attachedDisksCount := d .Get ("attached_disk.#" ).(int )
200
+ if attachedDisksCount > 0 {
201
+ for i := 0 ; i < attachedDisksCount ; i ++ {
202
+ diskConfig := d .Get (fmt .Sprintf ("attached_disk.%d" , i )).(map [string ]interface {})
203
+ disk , err := expandAttachedDisk (diskConfig , d , config )
204
+ if err != nil {
205
+ return nil , err
206
+ }
207
+
208
+ disks = append (disks , disk )
209
+ }
210
+ } else {
211
+ // attached disks were not overridden, so use the ones from the instance template
212
+ for _ , disk := range it .Properties .Disks {
213
+ if ! disk .Boot && disk .Type != "SCRATCH" {
214
+ if s := disk .Source ; s != "" {
215
+ // Instances need a URL for the disk source, but instance templates
216
+ // only have the name (since they're global).
217
+ disk .Source = fmt .Sprintf ("zones/%s/disks/%s" , zone .Name , s )
218
+ }
219
+ disks = append (disks , disk )
220
+ }
221
+ }
222
+ }
223
+
224
+ return disks , nil
225
+ }
0 commit comments