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

Add node_affinities to instance/template #1713

Merged
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
2 changes: 1 addition & 1 deletion build/terraform
2 changes: 1 addition & 1 deletion build/terraform-beta
2 changes: 1 addition & 1 deletion build/terraform-mapper
46 changes: 19 additions & 27 deletions third_party/terraform/resources/resource_compute_instance.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ import (
"github.com/mitchellh/hashstructure"
computeBeta "google.golang.org/api/compute/v0.beta"
"google.golang.org/api/compute/v1"
"google.golang.org/api/googleapi"
)

func resourceComputeInstance() *schema.Resource {
Expand Down Expand Up @@ -441,6 +440,14 @@ func resourceComputeInstance() *schema.Resource {
Default: false,
ForceNew: true,
},

"node_affinities": {
Type: schema.TypeSet,
Optional: true,
ForceNew: true,
Elem: instanceSchedulingNodeAffinitiesElemSchema(),
DiffSuppressFunc: emptyOrDefaultStringSuppress(""),
},
},
},
},
Expand Down Expand Up @@ -625,22 +632,9 @@ func expandComputeInstance(project string, zone *compute.Zone, d *schema.Resourc
disks = append(disks, disk)
}

sch := d.Get("scheduling").([]interface{})
var scheduling *computeBeta.Scheduling
if len(sch) == 0 {
// TF doesn't do anything about defaults inside of nested objects, so if
// scheduling hasn't been set, then send it with its default values.
scheduling = &computeBeta.Scheduling{
AutomaticRestart: googleapi.Bool(true),
}
} else {
prefix := "scheduling.0"
scheduling = &computeBeta.Scheduling{
AutomaticRestart: googleapi.Bool(d.Get(prefix + ".automatic_restart").(bool)),
Preemptible: d.Get(prefix + ".preemptible").(bool),
OnHostMaintenance: d.Get(prefix + ".on_host_maintenance").(string),
ForceSendFields: []string{"AutomaticRestart", "Preemptible"},
}
scheduling, err := expandScheduling(d.Get("scheduling"))
if err != nil {
return nil, fmt.Errorf("Error creating scheduling: %s", err)
}

metadata, err := resourceInstanceMetadata(d)
Expand Down Expand Up @@ -1005,22 +999,20 @@ func resourceComputeInstanceUpdate(d *schema.ResourceData, meta interface{}) err
}

if d.HasChange("scheduling") {
prefix := "scheduling.0"
scheduling := &compute.Scheduling{
AutomaticRestart: googleapi.Bool(d.Get(prefix + ".automatic_restart").(bool)),
Preemptible: d.Get(prefix + ".preemptible").(bool),
OnHostMaintenance: d.Get(prefix + ".on_host_maintenance").(string),
ForceSendFields: []string{"AutomaticRestart", "Preemptible"},
scheduling, err := expandScheduling(d.Get("scheduling"))
if err != nil {
return fmt.Errorf("Error creating request data to update scheduling: %s", err)
}

op, err := config.clientCompute.Instances.SetScheduling(project,
zone, d.Id(), scheduling).Do()

op, err := config.clientComputeBeta.Instances.SetScheduling(
project, zone, d.Id(), scheduling).Do()
if err != nil {
return fmt.Errorf("Error updating scheduling policy: %s", err)
}

opErr := computeOperationWaitTime(config.clientCompute, op, project, "scheduling policy update", int(d.Timeout(schema.TimeoutUpdate).Minutes()))
opErr := computeBetaOperationWaitTime(
config.clientCompute, op, project, "scheduling policy update",
int(d.Timeout(schema.TimeoutUpdate).Minutes()))
if opErr != nil {
return opErr
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"github.com/hashicorp/terraform/helper/schema"
"github.com/hashicorp/terraform/helper/validation"
computeBeta "google.golang.org/api/compute/v0.beta"
"google.golang.org/api/googleapi"
)

func resourceComputeInstanceTemplate() *schema.Resource {
Expand Down Expand Up @@ -320,6 +319,7 @@ func resourceComputeInstanceTemplate() *schema.Resource {
Optional: true,
Computed: true,
ForceNew: true,
MaxItems: 1,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"preemptible": {
Expand All @@ -342,6 +342,14 @@ func resourceComputeInstanceTemplate() *schema.Resource {
Computed: true,
ForceNew: true,
},

"node_affinities": {
Type: schema.TypeSet,
Optional: true,
ForceNew: true,
Elem: instanceSchedulingNodeAffinitiesElemSchema(),
DiffSuppressFunc: emptyOrDefaultStringSuppress(""),
},
},
},
},
Expand Down Expand Up @@ -604,70 +612,40 @@ func resourceComputeInstanceTemplateCreate(d *schema.ResourceData, meta interfac
return err
}

instanceProperties := &computeBeta.InstanceProperties{
CanIpForward: d.Get("can_ip_forward").(bool),
Description: d.Get("instance_description").(string),
MachineType: d.Get("machine_type").(string),
MinCpuPlatform: d.Get("min_cpu_platform").(string),
}

disks, err := buildDisks(d, config)
if err != nil {
return err
}
instanceProperties.Disks = disks

metadata, err := resourceInstanceMetadata(d)
if err != nil {
return err
}
instanceProperties.Metadata = metadata

networks, err := expandNetworkInterfaces(d, config)
if err != nil {
return err
}
instanceProperties.NetworkInterfaces = networks

instanceProperties.Scheduling = &computeBeta.Scheduling{}
instanceProperties.Scheduling.OnHostMaintenance = "MIGRATE"

forceSendFieldsScheduling := make([]string, 0, 3)
var hasSendMaintenance bool
hasSendMaintenance = false
if v, ok := d.GetOk("scheduling"); ok {
_schedulings := v.([]interface{})
if len(_schedulings) > 1 {
return fmt.Errorf("Error, at most one `scheduling` block can be defined")
}
_scheduling := _schedulings[0].(map[string]interface{})

// "automatic_restart" has a default value and is always safe to dereference
automaticRestart := _scheduling["automatic_restart"].(bool)
instanceProperties.Scheduling.AutomaticRestart = googleapi.Bool(automaticRestart)
forceSendFieldsScheduling = append(forceSendFieldsScheduling, "AutomaticRestart")

if vp, okp := _scheduling["on_host_maintenance"]; okp {
instanceProperties.Scheduling.OnHostMaintenance = vp.(string)
forceSendFieldsScheduling = append(forceSendFieldsScheduling, "OnHostMaintenance")
hasSendMaintenance = true
}

if vp, okp := _scheduling["preemptible"]; okp {
instanceProperties.Scheduling.Preemptible = vp.(bool)
forceSendFieldsScheduling = append(forceSendFieldsScheduling, "Preemptible")
if vp.(bool) && !hasSendMaintenance {
instanceProperties.Scheduling.OnHostMaintenance = "TERMINATE"
forceSendFieldsScheduling = append(forceSendFieldsScheduling, "OnHostMaintenance")
}
}
scheduling, err := expandResourceComputeInstanceTemplateScheduling(d, config)
if err != nil {
return err
}
instanceProperties.Scheduling.ForceSendFields = forceSendFieldsScheduling

instanceProperties.ServiceAccounts = expandServiceAccounts(d.Get("service_account").([]interface{}))

instanceProperties.GuestAccelerators = expandInstanceTemplateGuestAccelerators(d, config)
instanceProperties := &computeBeta.InstanceProperties{
CanIpForward: d.Get("can_ip_forward").(bool),
Description: d.Get("instance_description").(string),
GuestAccelerators: expandInstanceTemplateGuestAccelerators(d, config),
MachineType: d.Get("machine_type").(string),
MinCpuPlatform: d.Get("min_cpu_platform").(string),
Disks: disks,
Metadata: metadata,
NetworkInterfaces: networks,
Scheduling: scheduling,
ServiceAccounts: expandServiceAccounts(d.Get("service_account").([]interface{})),
Tags: resourceInstanceTags(d),
}

instanceProperties.Tags = resourceInstanceTags(d)
if _, ok := d.GetOk("labels"); ok {
instanceProperties.Labels = expandLabels(d)
}
Expand Down Expand Up @@ -888,3 +866,27 @@ func resourceComputeInstanceTemplateDelete(d *schema.ResourceData, meta interfac
d.SetId("")
return nil
}

// This wraps the general compute instance helper expandScheduling.
// Default value of OnHostMaintenance depends on the value of Preemptible,
// so we can't set a default in schema
func expandResourceComputeInstanceTemplateScheduling(d *schema.ResourceData, meta interface{}) (*computeBeta.Scheduling, error) {
v, ok := d.GetOk("scheduling")
if !ok || v == nil {
// We can't set defaults for lists (e.g. scheduling)
return &computeBeta.Scheduling{
OnHostMaintenance: "MIGRATE",
emilymye marked this conversation as resolved.
Show resolved Hide resolved
}, nil
}

expanded, err := expandScheduling(v)
if err != nil {
return nil, err
}

// Make sure we have an appropriate value for OnHostMaintenance if Preemptible
if expanded.Preemptible && expanded.OnHostMaintenance == "" {
expanded.OnHostMaintenance = "TERMINATE"
}
return expanded, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,7 @@ func TestAccComputeInstanceTemplate_networkIP(t *testing.T) {
},
})
}

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

Expand Down Expand Up @@ -345,6 +346,7 @@ func TestAccComputeInstanceTemplate_metadata_startup_script(t *testing.T) {
},
})
}

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

Expand Down Expand Up @@ -498,6 +500,26 @@ func TestAccComputeInstanceTemplate_EncryptKMS(t *testing.T) {
})
}

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

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckComputeInstanceTemplateDestroy,
Steps: []resource.TestStep{
{
Config: testAccComputeInstanceTemplate_soleTenantInstanceTemplate(),
},
{
ResourceName: "google_compute_instance_template.foobar",
ImportState: true,
ImportStateVerify: true,
},
},
})
}

func testAccCheckComputeInstanceTemplateDestroy(s *terraform.State) error {
config := testAccProvider.Meta().(*Config)

Expand Down Expand Up @@ -1449,3 +1471,40 @@ resource "google_compute_instance_template" "foobar" {
}
}`, acctest.RandString(10), kmsLink)
}

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

resource "google_compute_instance_template" "foobar" {
name = "instancet-test-%s"
machine_type = "n1-standard-1"

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

network_interface {
network = "default"
}

scheduling {
preemptible = false
automatic_restart = true
node_affinities {
key = "tfacc"
operator = "IN"
values = ["testinstancetemplate"]
}
}

service_account {
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}
}`, acctest.RandString(10))
}
Loading