Skip to content

Commit 82c36e4

Browse files
Turn Spot VMs to GA on GCE. (#5960) (#11552)
Signed-off-by: Modular Magician <[email protected]>
1 parent e03b1f8 commit 82c36e4

6 files changed

+197
-0
lines changed

.changelog/5960.txt

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
```release-note:enhancement
2+
compute: added `provisioning_model` field to `google_compute_instance` resource to support Spot VM
3+
```
4+
```release-note:enhancement
5+
compute: added `provisioning_model` field to `google_compute_instance_template ` resource to support Spot VM
6+
```

google/compute_instance_helpers.go

+9
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ func expandScheduling(v interface{}) (*compute.Scheduling, error) {
118118
if v, ok := original["min_node_cpus"]; ok {
119119
scheduling.MinNodeCpus = int64(v.(int))
120120
}
121+
if v, ok := original["provisioning_model"]; ok {
122+
scheduling.ProvisioningModel = v.(string)
123+
scheduling.ForceSendFields = append(scheduling.ForceSendFields, "ProvisioningModel")
124+
}
121125
return scheduling, nil
122126
}
123127

@@ -126,6 +130,7 @@ func flattenScheduling(resp *compute.Scheduling) []map[string]interface{} {
126130
"on_host_maintenance": resp.OnHostMaintenance,
127131
"preemptible": resp.Preemptible,
128132
"min_node_cpus": resp.MinNodeCpus,
133+
"provisioning_model": resp.ProvisioningModel,
129134
}
130135

131136
if resp.AutomaticRestart != nil {
@@ -470,6 +475,10 @@ func schedulingHasChangeWithoutReboot(d *schema.ResourceData) bool {
470475
return true
471476
}
472477

478+
if oScheduling["provisioning_model"] != newScheduling["provisioning_model"] {
479+
return true
480+
}
481+
473482
return false
474483
}
475484

google/resource_compute_instance.go

+9
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ var (
4545
"scheduling.0.preemptible",
4646
"scheduling.0.node_affinities",
4747
"scheduling.0.min_node_cpus",
48+
"scheduling.0.provisioning_model",
4849
}
4950

5051
shieldedInstanceConfigKeys = []string{
@@ -600,6 +601,14 @@ func resourceComputeInstance() *schema.Resource {
600601
Optional: true,
601602
AtLeastOneOf: schedulingKeys,
602603
},
604+
"provisioning_model": {
605+
Type: schema.TypeString,
606+
Optional: true,
607+
Computed: true,
608+
ForceNew: true,
609+
AtLeastOneOf: schedulingKeys,
610+
Description: `Whether the instance is spot. If this is set as SPOT.`,
611+
},
603612
},
604613
},
605614
},

google/resource_compute_instance_template.go

+9
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ var (
2323
"scheduling.0.preemptible",
2424
"scheduling.0.node_affinities",
2525
"scheduling.0.min_node_cpus",
26+
"scheduling.0.provisioning_model",
2627
}
2728

2829
shieldedInstanceTemplateConfigKeys = []string{
@@ -501,6 +502,14 @@ func resourceComputeInstanceTemplate() *schema.Resource {
501502
AtLeastOneOf: schedulingInstTemplateKeys,
502503
Description: `Minimum number of cpus for the instance.`,
503504
},
505+
"provisioning_model": {
506+
Type: schema.TypeString,
507+
Optional: true,
508+
Computed: true,
509+
ForceNew: true,
510+
AtLeastOneOf: schedulingInstTemplateKeys,
511+
Description: `Whether the instance is spot. If this is set as SPOT.`,
512+
},
504513
},
505514
},
506515
},

google/resource_compute_instance_template_test.go

+78
Original file line numberDiff line numberDiff line change
@@ -1053,6 +1053,35 @@ func TestAccComputeInstanceTemplate_queueCount(t *testing.T) {
10531053
})
10541054
}
10551055

1056+
func TestAccComputeInstanceTemplate_spot(t *testing.T) {
1057+
t.Parallel()
1058+
1059+
var instanceTemplate compute.InstanceTemplate
1060+
1061+
vcrTest(t, resource.TestCase{
1062+
PreCheck: func() { testAccPreCheck(t) },
1063+
Providers: testAccProviders,
1064+
CheckDestroy: testAccCheckComputeInstanceTemplateDestroyProducer(t),
1065+
Steps: []resource.TestStep{
1066+
{
1067+
Config: testAccComputeInstanceTemplate_spot(randString(t, 10)),
1068+
Check: resource.ComposeTestCheckFunc(
1069+
testAccCheckComputeInstanceTemplateExists(
1070+
t, "google_compute_instance_template.foobar", &instanceTemplate),
1071+
testAccCheckComputeInstanceTemplateAutomaticRestart(&instanceTemplate, false),
1072+
testAccCheckComputeInstanceTemplatePreemptible(&instanceTemplate, true),
1073+
testAccCheckComputeInstanceTemplateProvisioningModel(&instanceTemplate, "SPOT"),
1074+
),
1075+
},
1076+
{
1077+
ResourceName: "google_compute_instance_template.foobar",
1078+
ImportState: true,
1079+
ImportStateVerify: true,
1080+
},
1081+
},
1082+
})
1083+
}
1084+
10561085
func testAccCheckComputeInstanceTemplateDestroyProducer(t *testing.T) func(s *terraform.State) error {
10571086
return func(s *terraform.State) error {
10581087
config := googleProviderConfig(t)
@@ -1200,6 +1229,15 @@ func testAccCheckComputeInstanceTemplatePreemptible(instanceTemplate *compute.In
12001229
}
12011230
}
12021231

1232+
func testAccCheckComputeInstanceTemplateProvisioningModel(instanceTemplate *compute.InstanceTemplate, provisioning_model string) resource.TestCheckFunc {
1233+
return func(s *terraform.State) error {
1234+
if instanceTemplate.Properties.Scheduling.ProvisioningModel != provisioning_model {
1235+
return fmt.Errorf("Expected provisioning_model %v, got %v", provisioning_model, instanceTemplate.Properties.Scheduling.ProvisioningModel)
1236+
}
1237+
return nil
1238+
}
1239+
}
1240+
12031241
func testAccCheckComputeInstanceTemplateAutomaticRestart(instanceTemplate *compute.InstanceTemplate, automaticRestart bool) resource.TestCheckFunc {
12041242
return func(s *terraform.State) error {
12051243
ar := instanceTemplate.Properties.Scheduling.AutomaticRestart
@@ -2634,3 +2672,43 @@ resource "google_compute_instance_template" "foobar" {
26342672
}
26352673
`, instanceTemplateName)
26362674
}
2675+
2676+
func testAccComputeInstanceTemplate_spot(suffix string) string {
2677+
return fmt.Sprintf(`
2678+
data "google_compute_image" "my_image" {
2679+
family = "debian-9"
2680+
project = "debian-cloud"
2681+
}
2682+
2683+
resource "google_compute_instance_template" "foobar" {
2684+
name = "tf-test-instance-template-%s"
2685+
machine_type = "e2-medium"
2686+
can_ip_forward = false
2687+
tags = ["foo", "bar"]
2688+
2689+
disk {
2690+
source_image = data.google_compute_image.my_image.self_link
2691+
auto_delete = true
2692+
boot = true
2693+
}
2694+
2695+
network_interface {
2696+
network = "default"
2697+
}
2698+
2699+
scheduling {
2700+
preemptible = true
2701+
automatic_restart = false
2702+
provisioning_model = "SPOT"
2703+
}
2704+
2705+
metadata = {
2706+
foo = "bar"
2707+
}
2708+
2709+
service_account {
2710+
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
2711+
}
2712+
}
2713+
`, suffix)
2714+
}

google/resource_compute_instance_test.go

+86
Original file line numberDiff line numberDiff line change
@@ -2186,6 +2186,60 @@ func TestAccComputeInstance_queueCount(t *testing.T) {
21862186
})
21872187
}
21882188

2189+
func TestAccComputeInstance_spotVM(t *testing.T) {
2190+
t.Parallel()
2191+
2192+
var instance compute.Instance
2193+
var instanceName = fmt.Sprintf("tf-test-%s", randString(t, 10))
2194+
2195+
vcrTest(t, resource.TestCase{
2196+
PreCheck: func() { testAccPreCheck(t) },
2197+
Providers: testAccProviders,
2198+
CheckDestroy: testAccCheckComputeInstanceDestroyProducer(t),
2199+
Steps: []resource.TestStep{
2200+
{
2201+
Config: testAccComputeInstance_spotVM(instanceName),
2202+
Check: resource.ComposeTestCheckFunc(
2203+
testAccCheckComputeInstanceExists(
2204+
t, "google_compute_instance.foobar", &instance),
2205+
),
2206+
},
2207+
computeInstanceImportStep("us-central1-a", instanceName, []string{}),
2208+
},
2209+
})
2210+
}
2211+
2212+
func TestAccComputeInstance_spotVM_update(t *testing.T) {
2213+
t.Parallel()
2214+
2215+
var instance compute.Instance
2216+
var instanceName = fmt.Sprintf("tf-test-%s", randString(t, 10))
2217+
2218+
vcrTest(t, resource.TestCase{
2219+
PreCheck: func() { testAccPreCheck(t) },
2220+
Providers: testAccProviders,
2221+
CheckDestroy: testAccCheckComputeInstanceDestroyProducer(t),
2222+
Steps: []resource.TestStep{
2223+
{
2224+
Config: testAccComputeInstance_scheduling(instanceName),
2225+
Check: resource.ComposeTestCheckFunc(
2226+
testAccCheckComputeInstanceExists(
2227+
t, "google_compute_instance.foobar", &instance),
2228+
),
2229+
},
2230+
computeInstanceImportStep("us-central1-a", instanceName, []string{}),
2231+
{
2232+
Config: testAccComputeInstance_spotVM(instanceName),
2233+
Check: resource.ComposeTestCheckFunc(
2234+
testAccCheckComputeInstanceExists(
2235+
t, "google_compute_instance.foobar", &instance),
2236+
),
2237+
},
2238+
computeInstanceImportStep("us-central1-a", instanceName, []string{}),
2239+
},
2240+
})
2241+
}
2242+
21892243
func TestComputeInstance_networkIPCustomizedDiff(t *testing.T) {
21902244
t.Parallel()
21912245

@@ -6084,3 +6138,35 @@ resource "google_compute_instance" "foobar" {
60846138
}
60856139
`, instance)
60866140
}
6141+
6142+
func testAccComputeInstance_spotVM(instance string) string {
6143+
return fmt.Sprintf(`
6144+
data "google_compute_image" "my_image" {
6145+
family = "ubuntu-2004-lts"
6146+
project = "ubuntu-os-cloud"
6147+
}
6148+
6149+
resource "google_compute_instance" "foobar" {
6150+
name = "%s"
6151+
machine_type = "e2-medium"
6152+
zone = "us-central1-a"
6153+
6154+
boot_disk {
6155+
initialize_params {
6156+
image = data.google_compute_image.my_image.self_link
6157+
}
6158+
}
6159+
6160+
network_interface {
6161+
network = "default"
6162+
}
6163+
6164+
scheduling {
6165+
provisioning_model = "SPOT"
6166+
automatic_restart = false
6167+
preemptible = true
6168+
}
6169+
6170+
}
6171+
`, instance)
6172+
}

0 commit comments

Comments
 (0)