Skip to content

Commit 233a368

Browse files
add gVNIC support for instance template (#4655) (#3123)
Signed-off-by: Modular Magician <[email protected]>
1 parent fd67708 commit 233a368

File tree

4 files changed

+100
-74
lines changed

4 files changed

+100
-74
lines changed

.changelog/4655.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
```release-note:enhancement
2+
compute: added gVNIC support for `google_compute_instance_template`
3+
```

google-beta/resource_compute_instance_template.go

Lines changed: 9 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,13 @@ func resourceComputeInstanceTemplate() *schema.Resource {
326326
Computed: true,
327327
Description: `The name of the network_interface.`,
328328
},
329+
"nic_type": {
330+
Type: schema.TypeString,
331+
Optional: true,
332+
ForceNew: true,
333+
ValidateFunc: validation.StringInSlice([]string{"GVNIC", "VIRTIO_NET"}, false),
334+
Description: `The type of vNIC to be used on this interface. Possible values:GVNIC, VIRTIO_NET`,
335+
},
329336
"access_config": {
330337
Type: schema.TypeList,
331338
Optional: true,
@@ -854,7 +861,7 @@ func resourceComputeInstanceTemplateCreate(d *schema.ResourceData, meta interfac
854861
return err
855862
}
856863

857-
networks, err := expandComputeInstanceTemplateNetworkInterfaces(d, config)
864+
networks, err := expandNetworkInterfaces(d, config)
858865
if err != nil {
859866
return err
860867
}
@@ -1218,7 +1225,7 @@ func resourceComputeInstanceTemplateRead(d *schema.ResourceData, meta interface{
12181225
return fmt.Errorf("Error setting project: %s", err)
12191226
}
12201227
if instanceTemplate.Properties.NetworkInterfaces != nil {
1221-
networkInterfaces, region, _, _, err := flattenComputeInstanceTemplateNetworkInterfaces(d, config, instanceTemplate.Properties.NetworkInterfaces)
1228+
networkInterfaces, region, _, _, err := flattenNetworkInterfaces(d, config, instanceTemplate.Properties.NetworkInterfaces)
12221229
if err != nil {
12231230
return err
12241231
}
@@ -1343,75 +1350,3 @@ func resourceComputeInstanceTemplateImportState(d *schema.ResourceData, meta int
13431350

13441351
return []*schema.ResourceData{d}, nil
13451352
}
1346-
1347-
// this func could be replaced by flattenNetworkInterfaces once NicType is supported
1348-
func flattenComputeInstanceTemplateNetworkInterfaces(d *schema.ResourceData, config *Config, networkInterfaces []*computeBeta.NetworkInterface) ([]map[string]interface{}, string, string, string, error) {
1349-
flattened := make([]map[string]interface{}, len(networkInterfaces))
1350-
var region, internalIP, externalIP string
1351-
1352-
for i, iface := range networkInterfaces {
1353-
var ac []map[string]interface{}
1354-
ac, externalIP = flattenAccessConfigs(iface.AccessConfigs)
1355-
1356-
subnet, err := ParseSubnetworkFieldValue(iface.Subnetwork, d, config)
1357-
if err != nil {
1358-
return nil, "", "", "", err
1359-
}
1360-
region = subnet.Region
1361-
1362-
flattened[i] = map[string]interface{}{
1363-
"network_ip": iface.NetworkIP,
1364-
"network": ConvertSelfLinkToV1(iface.Network),
1365-
"subnetwork": ConvertSelfLinkToV1(iface.Subnetwork),
1366-
"subnetwork_project": subnet.Project,
1367-
"access_config": ac,
1368-
"alias_ip_range": flattenAliasIpRange(iface.AliasIpRanges),
1369-
}
1370-
// Instance template interfaces never have names, so they're absent
1371-
// in the instance template network_interface schema. We want to use the
1372-
// same flattening code for both resource types, so we avoid trying to
1373-
// set the name field when it's not set at the GCE end.
1374-
if iface.Name != "" {
1375-
flattened[i]["name"] = iface.Name
1376-
}
1377-
if internalIP == "" {
1378-
internalIP = iface.NetworkIP
1379-
}
1380-
}
1381-
return flattened, region, internalIP, externalIP, nil
1382-
}
1383-
1384-
// this func could be replaced by expandNetworkInterfaces once NicType is supported
1385-
func expandComputeInstanceTemplateNetworkInterfaces(d TerraformResourceData, config *Config) ([]*computeBeta.NetworkInterface, error) {
1386-
configs := d.Get("network_interface").([]interface{})
1387-
ifaces := make([]*computeBeta.NetworkInterface, len(configs))
1388-
for i, raw := range configs {
1389-
data := raw.(map[string]interface{})
1390-
1391-
network := data["network"].(string)
1392-
subnetwork := data["subnetwork"].(string)
1393-
if network == "" && subnetwork == "" {
1394-
return nil, fmt.Errorf("exactly one of network or subnetwork must be provided")
1395-
}
1396-
1397-
nf, err := ParseNetworkFieldValue(network, d, config)
1398-
if err != nil {
1399-
return nil, fmt.Errorf("cannot determine self_link for network %q: %s", network, err)
1400-
}
1401-
1402-
subnetProjectField := fmt.Sprintf("network_interface.%d.subnetwork_project", i)
1403-
sf, err := ParseSubnetworkFieldValueWithProjectField(subnetwork, subnetProjectField, d, config)
1404-
if err != nil {
1405-
return nil, fmt.Errorf("cannot determine self_link for subnetwork %q: %s", subnetwork, err)
1406-
}
1407-
1408-
ifaces[i] = &computeBeta.NetworkInterface{
1409-
NetworkIP: data["network_ip"].(string),
1410-
Network: nf.RelativeLink(),
1411-
Subnetwork: sf.RelativeLink(),
1412-
AccessConfigs: expandAccessConfigs(data["access_config"].([]interface{})),
1413-
AliasIpRanges: expandAliasIpRanges(data["alias_ip_range"].([]interface{})),
1414-
}
1415-
}
1416-
return ifaces, nil
1417-
}

google-beta/resource_compute_instance_template_test.go

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -925,6 +925,35 @@ func TestAccComputeInstanceTemplate_resourcePolicies(t *testing.T) {
925925
})
926926
}
927927

928+
func TestAccComputeInstanceTemplate_nictype_update(t *testing.T) {
929+
t.Parallel()
930+
931+
var instanceTemplate computeBeta.InstanceTemplate
932+
var instanceTemplateName = fmt.Sprintf("tf-test-%s", randString(t, 10))
933+
934+
vcrTest(t, resource.TestCase{
935+
PreCheck: func() { testAccPreCheck(t) },
936+
Providers: testAccProviders,
937+
CheckDestroy: testAccCheckComputeInstanceDestroyProducer(t),
938+
Steps: []resource.TestStep{
939+
{
940+
Config: testAccComputeInstanceTemplate_nictype(instanceTemplateName, instanceTemplateName, "GVNIC"),
941+
Check: resource.ComposeTestCheckFunc(
942+
testAccCheckComputeInstanceTemplateExists(
943+
t, "google_compute_instance_template.foobar", &instanceTemplate),
944+
),
945+
},
946+
{
947+
Config: testAccComputeInstanceTemplate_nictype(instanceTemplateName, instanceTemplateName, "VIRTIO_NET"),
948+
Check: resource.ComposeTestCheckFunc(
949+
testAccCheckComputeInstanceTemplateExists(
950+
t, "google_compute_instance_template.foobar", &instanceTemplate),
951+
),
952+
},
953+
},
954+
})
955+
}
956+
928957
func testAccCheckComputeInstanceTemplateDestroyProducer(t *testing.T) func(s *terraform.State) error {
929958
return func(s *terraform.State) error {
930959
config := googleProviderConfig(t)
@@ -2302,3 +2331,60 @@ resource "google_compute_resource_policy" "foo" {
23022331
}
23032332
`, suffix, policyName)
23042333
}
2334+
2335+
func testAccComputeInstanceTemplate_nictype(image, instance, nictype string) string {
2336+
return fmt.Sprintf(`
2337+
resource "google_compute_image" "example" {
2338+
name = "%s"
2339+
raw_disk {
2340+
source = "https://storage.googleapis.com/bosh-gce-raw-stemcells/bosh-stemcell-97.98-google-kvm-ubuntu-xenial-go_agent-raw-1557960142.tar.gz"
2341+
}
2342+
2343+
guest_os_features {
2344+
type = "SECURE_BOOT"
2345+
}
2346+
2347+
guest_os_features {
2348+
type = "MULTI_IP_SUBNET"
2349+
}
2350+
2351+
guest_os_features {
2352+
type = "GVNIC"
2353+
}
2354+
}
2355+
resource "google_compute_instance_template" "foobar" {
2356+
name = "instancet-test-%s"
2357+
machine_type = "e2-medium"
2358+
can_ip_forward = false
2359+
tags = ["foo", "bar"]
2360+
2361+
disk {
2362+
source_image = google_compute_image.example.name
2363+
auto_delete = true
2364+
boot = true
2365+
}
2366+
2367+
network_interface {
2368+
network = "default"
2369+
nic_type = "%s"
2370+
}
2371+
2372+
scheduling {
2373+
preemptible = false
2374+
automatic_restart = true
2375+
}
2376+
2377+
metadata = {
2378+
foo = "bar"
2379+
}
2380+
2381+
service_account {
2382+
scopes = ["userinfo-email", "compute-ro", "storage-ro"]
2383+
}
2384+
2385+
labels = {
2386+
my_label = "foobar"
2387+
}
2388+
}
2389+
`, image, instance, nictype)
2390+
}

website/docs/r/compute_instance_template.html.markdown

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,8 @@ The `network_interface` block supports:
359359
array of alias IP ranges for this network interface. Can only be specified for network
360360
interfaces on subnet-mode networks. Structure documented below.
361361

362+
* `nic_type` - (Optional) The type of vNIC to be used on this interface. Possible values: GVNIC, VIRTIO_NET.
363+
362364
The `access_config` block supports:
363365

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

0 commit comments

Comments
 (0)