Skip to content

Commit

Permalink
Add availability domain field to instance and instance template resou…
Browse files Browse the repository at this point in the history
…rce (#12566) (hashicorp#8914)

[upstream:8765b378e648d65db401f302e4ec05a321dcdbf9]

Signed-off-by: Modular Magician <[email protected]>
  • Loading branch information
modular-magician authored Dec 13, 2024
1 parent 11e4df1 commit 0ff2db3
Show file tree
Hide file tree
Showing 11 changed files with 283 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .changelog/12566.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
compute: added `availability_domain` field to `google_compute_instance`, `google_compute_instance_template` and `google_compute_region_instance_template` resources.
```
7 changes: 7 additions & 0 deletions google-beta/services/compute/compute_instance_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ func expandScheduling(v interface{}) (*compute.Scheduling, error) {
scheduling.InstanceTerminationAction = v.(string)
scheduling.ForceSendFields = append(scheduling.ForceSendFields, "InstanceTerminationAction")
}
if v, ok := original["availability_domain"]; ok && v != nil {
scheduling.AvailabilityDomain = int64(v.(int))
}
if v, ok := original["max_run_duration"]; ok {
transformedMaxRunDuration, err := expandComputeMaxRunDuration(v)
if err != nil {
Expand Down Expand Up @@ -278,6 +281,7 @@ func flattenScheduling(resp *compute.Scheduling) []map[string]interface{} {
"min_node_cpus": resp.MinNodeCpus,
"provisioning_model": resp.ProvisioningModel,
"instance_termination_action": resp.InstanceTerminationAction,
"availability_domain": resp.AvailabilityDomain,
}

if resp.AutomaticRestart != nil {
Expand Down Expand Up @@ -729,6 +733,9 @@ func schedulingHasChangeWithoutReboot(d *schema.ResourceData) bool {
if oScheduling["instance_termination_action"] != newScheduling["instance_termination_action"] {
return true
}
if oScheduling["availability_domain"] != newScheduling["availability_domain"] {
return true
}
if oScheduling["host_error_timeout_seconds"] != newScheduling["host_error_timeout_seconds"] {
return true
}
Expand Down
7 changes: 7 additions & 0 deletions google-beta/services/compute/resource_compute_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ var (
"scheduling.0.min_node_cpus",
"scheduling.0.provisioning_model",
"scheduling.0.instance_termination_action",
"scheduling.0.availability_domain",
"scheduling.0.max_run_duration",
"scheduling.0.on_instance_stop_action",
"scheduling.0.maintenance_interval",
Expand Down Expand Up @@ -882,6 +883,12 @@ func ResourceComputeInstance() *schema.Resource {
AtLeastOneOf: schedulingKeys,
Description: `Specifies the action GCE should take when SPOT VM is preempted.`,
},
"availability_domain": {
Type: schema.TypeInt,
Optional: true,
AtLeastOneOf: schedulingKeys,
Description: `Specifies the availability domain, which this instance should be scheduled on.`,
},
"max_run_duration": {
Type: schema.TypeList,
Optional: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ var (
"scheduling.0.min_node_cpus",
"scheduling.0.provisioning_model",
"scheduling.0.instance_termination_action",
"scheduling.0.availability_domain",
"scheduling.0.max_run_duration",
"scheduling.0.on_instance_stop_action",
"scheduling.0.maintenance_interval",
Expand Down Expand Up @@ -712,6 +713,13 @@ Google Cloud KMS.`,
AtLeastOneOf: schedulingInstTemplateKeys,
Description: `Specifies the action GCE should take when SPOT VM is preempted.`,
},
"availability_domain": {
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
AtLeastOneOf: schedulingInstTemplateKeys,
Description: `Specifies the availability domain, which this instance should be scheduled on.`,
},
"max_run_duration": {
Type: schema.TypeList,
Optional: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -727,6 +727,34 @@ func TestAccComputeInstanceTemplate_instanceResourcePolicies(t *testing.T) {
})
}

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

var template compute.InstanceTemplate
var policyName = "tf-test-policy-" + acctest.RandString(t, 10)

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckComputeInstanceTemplateDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccComputeInstanceTemplate_instanceResourcePolicySpread(acctest.RandString(t, 10), policyName),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeInstanceTemplateExists(t, "google_compute_instance_template.foobar", &template),
testAccCheckComputeInstanceTemplateHasInstanceResourcePolicies(&template, policyName),
testAccCheckComputeInstanceTemplateHasAvailabilityDomain(&template, 3),
),
},
{
ResourceName: "google_compute_instance_template.foobar",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

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

Expand Down Expand Up @@ -2202,6 +2230,15 @@ func testAccCheckComputeInstanceTemplateHasInstanceResourcePolicies(instanceTemp

}

func testAccCheckComputeInstanceTemplateHasAvailabilityDomain(instanceTemplate *compute.InstanceTemplate, availabilityDomain int64) resource.TestCheckFunc {
return func(s *terraform.State) error {
if instanceTemplate.Properties.Scheduling.AvailabilityDomain != availabilityDomain {
return fmt.Errorf("Expected availability_domain %d, got %d", availabilityDomain, instanceTemplate.Properties.Scheduling.AvailabilityDomain)
}
return nil
}
}

func testAccCheckComputeInstanceTemplateHasReservationAffinity(instanceTemplate *compute.InstanceTemplate, consumeReservationType string, specificReservationNames ...string) resource.TestCheckFunc {
if len(specificReservationNames) > 1 {
panic("too many specificReservationNames in test")
Expand Down Expand Up @@ -3569,6 +3606,48 @@ resource "google_compute_instance_template" "foobar" {
`, policyName, suffix)
}

func testAccComputeInstanceTemplate_instanceResourcePolicySpread(suffix string, policyName string) string {
return fmt.Sprintf(`
resource "google_compute_resource_policy" "foo" {
name = "%s"
region = "us-central1"
group_placement_policy {
availability_domain_count = 5
}
}
data "google_compute_image" "my_image" {
family = "debian-11"
project = "debian-cloud"
}
resource "google_compute_instance_template" "foobar" {
name = "tf-test-instance-template-%s"
machine_type = "e2-standard-4"
disk {
source_image = data.google_compute_image.my_image.self_link
auto_delete = true
boot = true
}
network_interface {
network = "default"
}
scheduling {
availability_domain = 3
}
resource_policies = [google_compute_resource_policy.foo.self_link]
service_account {
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}
}
`, policyName, suffix)
}

func testAccComputeInstanceTemplate_reservationAffinityInstanceTemplate_nonSpecificReservation(templateName, consumeReservationType string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
Expand Down
86 changes: 86 additions & 0 deletions google-beta/services/compute/resource_compute_instance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2986,6 +2986,31 @@ func TestAccComputeInstance_resourcePolicyCollocate(t *testing.T) {
})
}

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

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

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckComputeInstanceDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccComputeInstance_resourcePolicySpread(instanceName, acctest.RandString(t, 10)),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeInstanceExists(
t, "google_compute_instance.foobar", &instance),
testAccCheckComputeInstanceHasStatus(&instance, "RUNNING"),
testAccCheckComputeInstanceHasAvailabilityDomain(&instance, 3),
),
},
computeInstanceImportStep("us-east4-b", instanceName, []string{"allow_stopping_for_update"}),
},
})
}

func TestAccComputeInstance_subnetworkUpdate(t *testing.T) {
t.Parallel()
instanceName := fmt.Sprintf("tf-test-%s", acctest.RandString(t, 10))
Expand Down Expand Up @@ -4408,6 +4433,23 @@ func testAccCheckComputeInstanceMaxRunDuration(instance *compute.Instance, insta
}
}

func testAccCheckComputeInstanceHasAvailabilityDomain(instance *compute.Instance, availabilityDomain int64) resource.TestCheckFunc {
return func(s *terraform.State) error {
if instance == nil {
return fmt.Errorf("instance is nil")
}
if instance.Scheduling == nil {
return fmt.Errorf("no scheduling")
}

if instance.Scheduling.AvailabilityDomain != availabilityDomain {
return fmt.Errorf("got the wrong availability domain: have %d; want %d", instance.Scheduling.AvailabilityDomain, availabilityDomain)
}

return nil
}
}

func testAccCheckComputeInstanceLocalSsdRecoveryTimeout(instance *compute.Instance, instanceLocalSsdRecoveryTiemoutWant compute.Duration) resource.TestCheckFunc {
return func(s *terraform.State) error {
if instance == nil {
Expand Down Expand Up @@ -9309,6 +9351,50 @@ resource "google_compute_resource_policy" "foo" {
`, instance, instance, suffix)
}

func testAccComputeInstance_resourcePolicySpread(instance, suffix string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
family = "debian-11"
project = "debian-cloud"
}
resource "google_compute_instance" "foobar" {
name = "%s"
machine_type = "e2-standard-4"
zone = "us-east4-b"
can_ip_forward = false
tags = ["foo", "bar"]
//deletion_protection = false is implicit in this config due to default value
boot_disk {
initialize_params {
image = data.google_compute_image.my_image.self_link
}
}
network_interface {
network = "default"
}
scheduling {
availability_domain = 3
}
resource_policies = [google_compute_resource_policy.foo.self_link]
}
resource "google_compute_resource_policy" "foo" {
name = "tf-test-policy-%s"
region = "us-east4"
group_placement_policy {
availability_domain_count = 3
}
}
`, instance, suffix)
}

func testAccComputeInstance_subnetworkUpdate(suffix, instance string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -675,6 +675,13 @@ Google Cloud KMS.`,
AtLeastOneOf: schedulingInstTemplateKeys,
Description: `Specifies the action GCE should take when SPOT VM is preempted.`,
},
"availability_domain": {
Type: schema.TypeInt,
Optional: true,
ForceNew: true,
AtLeastOneOf: schedulingInstTemplateKeys,
Description: `Specifies the availability domain, which this instance should be scheduled on.`,
},
"max_run_duration": {
Type: schema.TypeList,
Optional: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,34 @@ func TestAccComputeRegionInstanceTemplate_instanceResourcePolicies(t *testing.T)
})
}

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

var template compute.InstanceTemplate
var policyName = "tf-test-policy-" + acctest.RandString(t, 10)

acctest.VcrTest(t, resource.TestCase{
PreCheck: func() { acctest.AccTestPreCheck(t) },
ProtoV5ProviderFactories: acctest.ProtoV5ProviderFactories(t),
CheckDestroy: testAccCheckComputeRegionInstanceTemplateDestroyProducer(t),
Steps: []resource.TestStep{
{
Config: testAccComputeRegionInstanceTemplate_instanceResourcePolicySpread(acctest.RandString(t, 10), policyName),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeRegionInstanceTemplateExists(t, "google_compute_region_instance_template.foobar", &template),
testAccCheckComputeRegionInstanceTemplateHasInstanceResourcePolicies(&template, policyName),
testAccCheckComputeRegionInstanceTemplateHasAvailabilityDomain(&template, 3),
),
},
{
ResourceName: "google_compute_region_instance_template.foobar",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

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

Expand Down Expand Up @@ -1838,6 +1866,15 @@ func testAccCheckComputeRegionInstanceTemplateHasInstanceResourcePolicies(instan

}

func testAccCheckComputeRegionInstanceTemplateHasAvailabilityDomain(instanceTemplate *compute.InstanceTemplate, availabilityDomain int64) resource.TestCheckFunc {
return func(s *terraform.State) error {
if instanceTemplate.Properties.Scheduling.AvailabilityDomain != availabilityDomain {
return fmt.Errorf("Expected availability_domain %d, got %d", availabilityDomain, instanceTemplate.Properties.Scheduling.AvailabilityDomain)
}
return nil
}
}

func testAccCheckComputeRegionInstanceTemplateHasReservationAffinity(instanceTemplate *compute.InstanceTemplate, consumeReservationType string, specificReservationNames ...string) resource.TestCheckFunc {
if len(specificReservationNames) > 1 {
panic("too many specificReservationNames in test")
Expand Down Expand Up @@ -2960,6 +2997,49 @@ resource "google_compute_region_instance_template" "foobar" {
`, policyName, suffix)
}

func testAccComputeRegionInstanceTemplate_instanceResourcePolicySpread(suffix string, policyName string) string {
return fmt.Sprintf(`
resource "google_compute_resource_policy" "foo" {
name = "%s"
region = "us-central1"
group_placement_policy {
availability_domain_count = 5
}
}
data "google_compute_image" "my_image" {
family = "debian-11"
project = "debian-cloud"
}
resource "google_compute_region_instance_template" "foobar" {
name = "tf-test-instance-template-%s"
machine_type = "e2-standard-4"
region = "us-central1"
disk {
source_image = data.google_compute_image.my_image.self_link
auto_delete = true
boot = true
}
network_interface {
network = "default"
}
scheduling {
availability_domain = 3
}
resource_policies = [google_compute_resource_policy.foo.self_link]
service_account {
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}
}
`, policyName, suffix)
}

func testAccComputeRegionInstanceTemplate_reservationAffinityInstanceTemplate_nonSpecificReservation(templateName, consumeReservationType string) string {
return fmt.Sprintf(`
data "google_compute_image" "my_image" {
Expand Down
Loading

0 comments on commit 0ff2db3

Please sign in to comment.