Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Turn Spot VMs to GA on GCE. #11552

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changelog/5960.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
```release-note:enhancement
compute: added `provisioning_model` field to `google_compute_instance` resource to support Spot VM
```
```release-note:enhancement
compute: added `provisioning_model` field to `google_compute_instance_template ` resource to support Spot VM
```
9 changes: 9 additions & 0 deletions google/compute_instance_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,10 @@ func expandScheduling(v interface{}) (*compute.Scheduling, error) {
if v, ok := original["min_node_cpus"]; ok {
scheduling.MinNodeCpus = int64(v.(int))
}
if v, ok := original["provisioning_model"]; ok {
scheduling.ProvisioningModel = v.(string)
scheduling.ForceSendFields = append(scheduling.ForceSendFields, "ProvisioningModel")
}
return scheduling, nil
}

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

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

if oScheduling["provisioning_model"] != newScheduling["provisioning_model"] {
return true
}

return false
}

Expand Down
9 changes: 9 additions & 0 deletions google/resource_compute_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ var (
"scheduling.0.preemptible",
"scheduling.0.node_affinities",
"scheduling.0.min_node_cpus",
"scheduling.0.provisioning_model",
}

shieldedInstanceConfigKeys = []string{
Expand Down Expand Up @@ -600,6 +601,14 @@ func resourceComputeInstance() *schema.Resource {
Optional: true,
AtLeastOneOf: schedulingKeys,
},
"provisioning_model": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
AtLeastOneOf: schedulingKeys,
Description: `Whether the instance is spot. If this is set as SPOT.`,
},
},
},
},
Expand Down
9 changes: 9 additions & 0 deletions google/resource_compute_instance_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ var (
"scheduling.0.preemptible",
"scheduling.0.node_affinities",
"scheduling.0.min_node_cpus",
"scheduling.0.provisioning_model",
}

shieldedInstanceTemplateConfigKeys = []string{
Expand Down Expand Up @@ -501,6 +502,14 @@ func resourceComputeInstanceTemplate() *schema.Resource {
AtLeastOneOf: schedulingInstTemplateKeys,
Description: `Minimum number of cpus for the instance.`,
},
"provisioning_model": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
AtLeastOneOf: schedulingInstTemplateKeys,
Description: `Whether the instance is spot. If this is set as SPOT.`,
},
},
},
},
Expand Down
78 changes: 78 additions & 0 deletions google/resource_compute_instance_template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,35 @@ func TestAccComputeInstanceTemplate_queueCount(t *testing.T) {
})
}

func TestAccComputeInstanceTemplate_spot(t *testing.T) {
t.Parallel()

var instanceTemplate compute.InstanceTemplate

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckComputeInstanceTemplateDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccComputeInstanceTemplate_spot(randString(t, 10)),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeInstanceTemplateExists(
t, "google_compute_instance_template.foobar", &instanceTemplate),
testAccCheckComputeInstanceTemplateAutomaticRestart(&instanceTemplate, false),
testAccCheckComputeInstanceTemplatePreemptible(&instanceTemplate, true),
testAccCheckComputeInstanceTemplateProvisioningModel(&instanceTemplate, "SPOT"),
),
},
{
ResourceName: "google_compute_instance_template.foobar",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccCheckComputeInstanceTemplateDestroyProducer(t *testing.T) func(s *terraform.State) error {
return func(s *terraform.State) error {
config := googleProviderConfig(t)
Expand Down Expand Up @@ -1200,6 +1229,15 @@ func testAccCheckComputeInstanceTemplatePreemptible(instanceTemplate *compute.In
}
}

func testAccCheckComputeInstanceTemplateProvisioningModel(instanceTemplate *compute.InstanceTemplate, provisioning_model string) resource.TestCheckFunc {
return func(s *terraform.State) error {
if instanceTemplate.Properties.Scheduling.ProvisioningModel != provisioning_model {
return fmt.Errorf("Expected provisioning_model %v, got %v", provisioning_model, instanceTemplate.Properties.Scheduling.ProvisioningModel)
}
return nil
}
}

func testAccCheckComputeInstanceTemplateAutomaticRestart(instanceTemplate *compute.InstanceTemplate, automaticRestart bool) resource.TestCheckFunc {
return func(s *terraform.State) error {
ar := instanceTemplate.Properties.Scheduling.AutomaticRestart
Expand Down Expand Up @@ -2634,3 +2672,43 @@ resource "google_compute_instance_template" "foobar" {
}
`, instanceTemplateName)
}

func testAccComputeInstanceTemplate_spot(suffix string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
family = "debian-9"
project = "debian-cloud"
}

resource "google_compute_instance_template" "foobar" {
name = "tf-test-instance-template-%s"
machine_type = "e2-medium"
can_ip_forward = false
tags = ["foo", "bar"]

disk {
source_image = data.google_compute_image.my_image.self_link
auto_delete = true
boot = true
}

network_interface {
network = "default"
}

scheduling {
preemptible = true
automatic_restart = false
provisioning_model = "SPOT"
}

metadata = {
foo = "bar"
}

service_account {
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}
}
`, suffix)
}
86 changes: 86 additions & 0 deletions google/resource_compute_instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2186,6 +2186,60 @@ func TestAccComputeInstance_queueCount(t *testing.T) {
})
}

func TestAccComputeInstance_spotVM(t *testing.T) {
t.Parallel()

var instance compute.Instance
var instanceName = fmt.Sprintf("tf-test-%s", randString(t, 10))

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckComputeInstanceDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccComputeInstance_spotVM(instanceName),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeInstanceExists(
t, "google_compute_instance.foobar", &instance),
),
},
computeInstanceImportStep("us-central1-a", instanceName, []string{}),
},
})
}

func TestAccComputeInstance_spotVM_update(t *testing.T) {
t.Parallel()

var instance compute.Instance
var instanceName = fmt.Sprintf("tf-test-%s", randString(t, 10))

vcrTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckComputeInstanceDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccComputeInstance_scheduling(instanceName),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeInstanceExists(
t, "google_compute_instance.foobar", &instance),
),
},
computeInstanceImportStep("us-central1-a", instanceName, []string{}),
{
Config: testAccComputeInstance_spotVM(instanceName),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeInstanceExists(
t, "google_compute_instance.foobar", &instance),
),
},
computeInstanceImportStep("us-central1-a", instanceName, []string{}),
},
})
}

func TestComputeInstance_networkIPCustomizedDiff(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -6084,3 +6138,35 @@ resource "google_compute_instance" "foobar" {
}
`, instance)
}

func testAccComputeInstance_spotVM(instance string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
family = "ubuntu-2004-lts"
project = "ubuntu-os-cloud"
}

resource "google_compute_instance" "foobar" {
name = "%s"
machine_type = "e2-medium"
zone = "us-central1-a"

boot_disk {
initialize_params {
image = data.google_compute_image.my_image.self_link
}
}

network_interface {
network = "default"
}

scheduling {
provisioning_model = "SPOT"
automatic_restart = false
preemptible = true
}

}
`, instance)
}