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 gVNIC support for instance template #8842

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
3 changes: 3 additions & 0 deletions .changelog/4655.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
compute: added gVNIC support for `google_compute_instance_template`
```
83 changes: 9 additions & 74 deletions google/resource_compute_instance_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,13 @@ func resourceComputeInstanceTemplate() *schema.Resource {
Computed: true,
Description: `The name of the network_interface.`,
},
"nic_type": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ValidateFunc: validation.StringInSlice([]string{"GVNIC", "VIRTIO_NET"}, false),
Description: `The type of vNIC to be used on this interface. Possible values:GVNIC, VIRTIO_NET`,
},
"access_config": {
Type: schema.TypeList,
Optional: true,
Expand Down Expand Up @@ -847,7 +854,7 @@ func resourceComputeInstanceTemplateCreate(d *schema.ResourceData, meta interfac
return err
}

networks, err := expandComputeInstanceTemplateNetworkInterfaces(d, config)
networks, err := expandNetworkInterfaces(d, config)
if err != nil {
return err
}
Expand Down Expand Up @@ -1211,7 +1218,7 @@ func resourceComputeInstanceTemplateRead(d *schema.ResourceData, meta interface{
return fmt.Errorf("Error setting project: %s", err)
}
if instanceTemplate.Properties.NetworkInterfaces != nil {
networkInterfaces, region, _, _, err := flattenComputeInstanceTemplateNetworkInterfaces(d, config, instanceTemplate.Properties.NetworkInterfaces)
networkInterfaces, region, _, _, err := flattenNetworkInterfaces(d, config, instanceTemplate.Properties.NetworkInterfaces)
if err != nil {
return err
}
Expand Down Expand Up @@ -1336,75 +1343,3 @@ func resourceComputeInstanceTemplateImportState(d *schema.ResourceData, meta int

return []*schema.ResourceData{d}, nil
}

// this func could be replaced by flattenNetworkInterfaces once NicType is supported
func flattenComputeInstanceTemplateNetworkInterfaces(d *schema.ResourceData, config *Config, networkInterfaces []*computeBeta.NetworkInterface) ([]map[string]interface{}, string, string, string, error) {
flattened := make([]map[string]interface{}, len(networkInterfaces))
var region, internalIP, externalIP string

for i, iface := range networkInterfaces {
var ac []map[string]interface{}
ac, externalIP = flattenAccessConfigs(iface.AccessConfigs)

subnet, err := ParseSubnetworkFieldValue(iface.Subnetwork, d, config)
if err != nil {
return nil, "", "", "", err
}
region = subnet.Region

flattened[i] = map[string]interface{}{
"network_ip": iface.NetworkIP,
"network": ConvertSelfLinkToV1(iface.Network),
"subnetwork": ConvertSelfLinkToV1(iface.Subnetwork),
"subnetwork_project": subnet.Project,
"access_config": ac,
"alias_ip_range": flattenAliasIpRange(iface.AliasIpRanges),
}
// Instance template interfaces never have names, so they're absent
// in the instance template network_interface schema. We want to use the
// same flattening code for both resource types, so we avoid trying to
// set the name field when it's not set at the GCE end.
if iface.Name != "" {
flattened[i]["name"] = iface.Name
}
if internalIP == "" {
internalIP = iface.NetworkIP
}
}
return flattened, region, internalIP, externalIP, nil
}

// this func could be replaced by expandNetworkInterfaces once NicType is supported
func expandComputeInstanceTemplateNetworkInterfaces(d TerraformResourceData, config *Config) ([]*computeBeta.NetworkInterface, error) {
configs := d.Get("network_interface").([]interface{})
ifaces := make([]*computeBeta.NetworkInterface, len(configs))
for i, raw := range configs {
data := raw.(map[string]interface{})

network := data["network"].(string)
subnetwork := data["subnetwork"].(string)
if network == "" && subnetwork == "" {
return nil, fmt.Errorf("exactly one of network or subnetwork must be provided")
}

nf, err := ParseNetworkFieldValue(network, d, config)
if err != nil {
return nil, fmt.Errorf("cannot determine self_link for network %q: %s", network, err)
}

subnetProjectField := fmt.Sprintf("network_interface.%d.subnetwork_project", i)
sf, err := ParseSubnetworkFieldValueWithProjectField(subnetwork, subnetProjectField, d, config)
if err != nil {
return nil, fmt.Errorf("cannot determine self_link for subnetwork %q: %s", subnetwork, err)
}

ifaces[i] = &computeBeta.NetworkInterface{
NetworkIP: data["network_ip"].(string),
Network: nf.RelativeLink(),
Subnetwork: sf.RelativeLink(),
AccessConfigs: expandAccessConfigs(data["access_config"].([]interface{})),
AliasIpRanges: expandAliasIpRanges(data["alias_ip_range"].([]interface{})),
}
}
return ifaces, nil
}
86 changes: 86 additions & 0 deletions google/resource_compute_instance_template_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -925,6 +925,35 @@ func TestAccComputeInstanceTemplate_resourcePolicies(t *testing.T) {
})
}

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

var instanceTemplate computeBeta.InstanceTemplate
var instanceTemplateName = 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: testAccComputeInstanceTemplate_nictype(instanceTemplateName, instanceTemplateName, "GVNIC"),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeInstanceTemplateExists(
t, "google_compute_instance_template.foobar", &instanceTemplate),
),
},
{
Config: testAccComputeInstanceTemplate_nictype(instanceTemplateName, instanceTemplateName, "VIRTIO_NET"),
Check: resource.ComposeTestCheckFunc(
testAccCheckComputeInstanceTemplateExists(
t, "google_compute_instance_template.foobar", &instanceTemplate),
),
},
},
})
}

func testAccCheckComputeInstanceTemplateDestroyProducer(t *testing.T) func(s *terraform.State) error {
return func(s *terraform.State) error {
config := googleProviderConfig(t)
Expand Down Expand Up @@ -2301,3 +2330,60 @@ resource "google_compute_resource_policy" "foo" {
}
`, suffix, policyName)
}

func testAccComputeInstanceTemplate_nictype(image, instance, nictype string) string {
return fmt.Sprintf(`
resource "google_compute_image" "example" {
name = "%s"
raw_disk {
source = "https://storage.googleapis.com/bosh-gce-raw-stemcells/bosh-stemcell-97.98-google-kvm-ubuntu-xenial-go_agent-raw-1557960142.tar.gz"
}

guest_os_features {
type = "SECURE_BOOT"
}

guest_os_features {
type = "MULTI_IP_SUBNET"
}

guest_os_features {
type = "GVNIC"
}
}
resource "google_compute_instance_template" "foobar" {
name = "instancet-test-%s"
machine_type = "e2-medium"
can_ip_forward = false
tags = ["foo", "bar"]

disk {
source_image = google_compute_image.example.name
auto_delete = true
boot = true
}

network_interface {
network = "default"
nic_type = "%s"
}

scheduling {
preemptible = false
automatic_restart = true
}

metadata = {
foo = "bar"
}

service_account {
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
}

labels = {
my_label = "foobar"
}
}
`, image, instance, nictype)
}
2 changes: 2 additions & 0 deletions website/docs/r/compute_instance_template.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -359,6 +359,8 @@ The `network_interface` block supports:
array of alias IP ranges for this network interface. Can only be specified for network
interfaces on subnet-mode networks. Structure documented below.

* `nic_type` - (Optional) The type of vNIC to be used on this interface. Possible values: GVNIC, VIRTIO_NET.

The `access_config` block supports:

* `nat_ip` - (Optional) The IP address that will be 1:1 mapped to the instance's
Expand Down