Skip to content

Commit

Permalink
add availability domain field to instance and instance template resource
Browse files Browse the repository at this point in the history
  • Loading branch information
Timofey Yushchenko committed Dec 13, 2024
1 parent 3b3cb68 commit 0dc4b81
Show file tree
Hide file tree
Showing 11 changed files with 283 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,8 @@ func convertScheduling(sched *compute.Scheduling) []map[string]interface{} {
"preemptible": sched.Preemptible,
"on_host_maintenance": sched.OnHostMaintenance,
// node_affinities are not converted into cai
"node_affinities": convertSchedulingNodeAffinity(sched.NodeAffinities),
"node_affinities": convertSchedulingNodeAffinity(sched.NodeAffinities),
"availability_domain": sched.AvailabilityDomain,
}
if sched.MinNodeCpus > 0 {
data["min_node_cpus"] = sched.MinNodeCpus
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,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 @@ -282,6 +285,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 @@ -757,6 +761,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 ne $.TargetVersionName "ga" }}
if oScheduling["host_error_timeout_seconds"] != newScheduling["host_error_timeout_seconds"] {
return true
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,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",
{{- if ne $.TargetVersionName "ga" }}
Expand Down Expand Up @@ -901,6 +902,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 @@ -34,6 +34,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",
{{- if ne $.TargetVersionName "ga" }}
Expand Down Expand Up @@ -728,6 +729,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 @@ -738,6 +738,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 @@ -2235,6 +2263,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 @@ -3605,6 +3642,49 @@ 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
Original file line number Diff line number Diff line change
Expand Up @@ -2999,6 +2999,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 @@ -4436,6 +4461,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 @@ -9349,6 +9391,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 @@ -687,6 +687,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
Loading

0 comments on commit 0dc4b81

Please sign in to comment.