terraform-provider-google/google/resource_compute_instance_migrate_test.go
Nic Cope 94a405d179 Add Alias IP and Guest Accelerator support to Instance Templates (#639)
* Move AliasIpRange helpers into utils

To reflect the fact they'll be used by multiple resources.

* Pass Config to build helpers, not meta

It's the only thing meta is used for.

* Refactor getNetwork util methods to return early for the happy path.

* Update compute APIs

compute.Instance.MinCpuPlatform is now GA.

* Fix panic in TestComputeInstanceMigrateState

This seemed to be a pre-existing issue, i.e. I could repro it in master.

--- FAIL: TestComputeInstanceMigrateState (0.00s)
panic: interface conversion: interface {} is nil, not *google.Config [recovered]
        panic: interface conversion: interface {} is nil, not *google.Config

goroutine 85 [running]:
testing.tRunner.func1(0xc4205d60f0)
        /usr/local/Cellar/go/1.9.1/libexec/src/testing/testing.go:711 +0x2d2
panic(0x203acc0, 0xc4205d2080)
        /usr/local/Cellar/go/1.9.1/libexec/src/runtime/panic.go:491 +0x283
github.com/terraform-providers/terraform-provider-google/google.migrateStateV3toV4(0xc4205f2000, 0x0, 0x0, 0x0, 0x48, 0xc4205f2000)
        /Users/negz/control/go/src/github.com/terraform-providers/terraform-provider-google/google/resource_compute_instance_migrate.go:182 +0x2405
github.com/terraform-providers/terraform-provider-google/google.resourceComputeInstanceMigrateState(0x2, 0xc4205f2000, 0x0, 0x0, 0x0, 0x0, 0xe0000000000)
        /Users/negz/control/go/src/github.com/terraform-providers/terraform-provider-google/google/resource_compute_instance_migrate.go:48 +0x21a
github.com/terraform-providers/terraform-provider-google/google.runInstanceMigrateTest(0xc4205d60f0, 0x2260816, 0x8, 0x227d23a, 0x20, 0x2, 0xc4205ec0f0, 0xc4205ec120, 0x0,
 0x0)
        /Users/negz/control/go/src/github.com/terraform-providers/terraform-provider-google/google/resource_compute_instance_migrate_test.go:803 +0xc1
github.com/terraform-providers/terraform-provider-google/google.TestComputeInstanceMigrateState(0xc4205d60f0)
        /Users/negz/control/go/src/github.com/terraform-providers/terraform-provider-google/google/resource_compute_instance_migrate_test.go:71 +0xc84
testing.tRunner(0xc4205d60f0, 0x22d81c0)
        /usr/local/Cellar/go/1.9.1/libexec/src/testing/testing.go:746 +0xd0
created by testing.(*T).Run
        /usr/local/Cellar/go/1.9.1/libexec/src/testing/testing.go:789 +0x2de
FAIL    github.com/terraform-providers/terraform-provider-google/google 0.035s

* Use only the v1 API for resource_compute_instance

Alias IP ranges, Accelerators, and min CPU platform are now GA.

* Move common instance code into utils.go

Methods used by both resource_compute_instance and
resource_compute_instance_template are currently spread between their respective
files, and utils.go.

This commit moves them all into utils.go for the sake of consistency. It may be
worth considering an instance_common.go file or similar.

* Unify compute_instance and compute_instance_template network_interface and service_account code

This has the side effect of enabling Alias IP range support for
compute_instance_templates.

* Add tests for compute instance template Alias IP ranges

* Mark instance template region as computed

We compute it from the subnet its network interfaces are in. Note this
is not new behaviour - I believe it was erroneously missing the computed
flag.

* Support guest accelerators for instance templates

Since most of the code is already there.

* Add a test for using 'address' rather than 'network_ip' for instance templates

* Don't mark assigned_nat_ip as deprecated

* Remove network_interface schema fields that don't make sense for a compute instance template

* Add newline after count in instance template docs

* Don't try to dedupe guest accelerator expansion code

The API calls to Google to create guest accelerators take different values
for instances and instance templates. Instance templates don't have a zone
and can thus *only* be passed a guest accelerator name.

* Use ParseNetworkFieldValue instead of getNetworkLink

* Add support for parsing regional fields, and subnetworks specifically

Currently unused because subnetworks may have a separate project from that
of the instance using them, which complicates looking up the project field.

* Fall back to provider region when parsing regional field values

Also slightly refactors getXFromSchema field helper functions for readability.

* Revert to assigned_nat_ip in compute instance docs

* Add beta scaffolding to compute instance and compute instance template

Note these resources don't currently use beta features - this is futureproofing.

* Fix indentation in comment about instance template alias IP ranges

* Consolidate metadata helper functions in metadata.go

* Move compute instance (and template) related helpers into their own file
2017-11-28 10:01:27 -08:00

878 lines
29 KiB
Go

package google
import (
"fmt"
"log"
"os"
"testing"
"google.golang.org/api/compute/v1"
"github.com/hashicorp/terraform/helper/acctest"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/terraform"
)
func TestComputeInstanceMigrateState(t *testing.T) {
if os.Getenv(resource.TestEnvVar) == "" {
t.Skip(fmt.Sprintf("Network access not allowed; use %s=1 to enable", resource.TestEnvVar))
}
cases := map[string]struct {
StateVersion int
Attributes map[string]string
Expected map[string]string
}{
"v0.4.2 and earlier": {
StateVersion: 0,
Attributes: map[string]string{
"metadata.#": "2",
"metadata.0.foo": "bar",
"metadata.1.baz": "qux",
"metadata.2.with.dots": "should.work",
},
Expected: map[string]string{
"metadata.foo": "bar",
"metadata.baz": "qux",
"metadata.with.dots": "should.work",
},
},
"change scope from list to set": {
StateVersion: 1,
Attributes: map[string]string{
"service_account.#": "1",
"service_account.0.email": "xxxxxx-compute@developer.gserviceaccount.com",
"service_account.0.scopes.#": "4",
"service_account.0.scopes.0": "https://www.googleapis.com/auth/compute",
"service_account.0.scopes.1": "https://www.googleapis.com/auth/datastore",
"service_account.0.scopes.2": "https://www.googleapis.com/auth/devstorage.full_control",
"service_account.0.scopes.3": "https://www.googleapis.com/auth/logging.write",
},
Expected: map[string]string{
"service_account.#": "1",
"service_account.0.email": "xxxxxx-compute@developer.gserviceaccount.com",
"service_account.0.scopes.#": "4",
"service_account.0.scopes.1693978638": "https://www.googleapis.com/auth/devstorage.full_control",
"service_account.0.scopes.172152165": "https://www.googleapis.com/auth/logging.write",
"service_account.0.scopes.299962681": "https://www.googleapis.com/auth/compute",
"service_account.0.scopes.3435931483": "https://www.googleapis.com/auth/datastore",
},
},
"add new create_timeout attribute": {
StateVersion: 2,
Attributes: map[string]string{},
Expected: map[string]string{
"create_timeout": "4",
},
},
"remove empty initialize_params": {
StateVersion: 5,
Attributes: map[string]string{
"boot_disk.0.initialize_params.#": "1",
"boot_disk.0.initialize_params.0.size": "0",
},
Expected: map[string]string{
"boot_disk.0.initialize_params.#": "0",
},
},
}
config := getInitializedConfig(t)
for tn, tc := range cases {
runInstanceMigrateTest(t, "i-abc123", tn, tc.StateVersion, tc.Attributes, tc.Expected, config)
}
}
func TestComputeInstanceMigrateState_empty(t *testing.T) {
if os.Getenv(resource.TestEnvVar) == "" {
t.Skip(fmt.Sprintf("Network access not allowed; use %s=1 to enable", resource.TestEnvVar))
}
var is *terraform.InstanceState
var meta interface{}
// should handle nil
is, err := resourceComputeInstanceMigrateState(0, is, meta)
if err != nil {
t.Fatalf("err: %#v", err)
}
if is != nil {
t.Fatalf("expected nil instancestate, got: %#v", is)
}
// should handle non-nil but empty
is = &terraform.InstanceState{}
is, err = resourceComputeInstanceMigrateState(0, is, meta)
if err != nil {
t.Fatalf("err: %#v", err)
}
}
func TestAccComputeInstanceMigrateState_bootDisk(t *testing.T) {
t.Parallel()
if os.Getenv(resource.TestEnvVar) == "" {
t.Skip(fmt.Sprintf("Network access not allowed; use %s=1 to enable", resource.TestEnvVar))
}
config := getInitializedConfig(t)
zone := "us-central1-f"
// Seed test data
instanceName := fmt.Sprintf("instance-test-%s", acctest.RandString(10))
instance := &compute.Instance{
Name: instanceName,
Disks: []*compute.AttachedDisk{
{
Boot: true,
InitializeParams: &compute.AttachedDiskInitializeParams{
SourceImage: "projects/debian-cloud/global/images/family/debian-8",
},
},
},
MachineType: "zones/" + zone + "/machineTypes/n1-standard-1",
NetworkInterfaces: []*compute.NetworkInterface{
{
Network: "global/networks/default",
},
},
}
op, err := config.clientCompute.Instances.Insert(config.Project, zone, instance).Do()
if err != nil {
t.Fatalf("Error creating instance: %s", err)
}
waitErr := computeSharedOperationWait(config.clientCompute, op, config.Project, "instance to create")
if waitErr != nil {
t.Fatal(waitErr)
}
defer cleanUpInstance(config, instanceName, zone)
attributes := map[string]string{
"disk.#": "1",
"disk.0.disk": "disk-1",
"disk.0.type": "pd-ssd",
"disk.0.auto_delete": "false",
"disk.0.size": "12",
"disk.0.device_name": "persistent-disk-0",
"disk.0.disk_encryption_key_raw": "encrypt-key",
"disk.0.disk_encryption_key_sha256": "encrypt-key-sha",
"zone": zone,
}
expected := map[string]string{
"boot_disk.#": "1",
"boot_disk.0.auto_delete": "false",
"boot_disk.0.device_name": "persistent-disk-0",
"boot_disk.0.disk_encryption_key_raw": "encrypt-key",
"boot_disk.0.disk_encryption_key_sha256": "encrypt-key-sha",
"boot_disk.0.initialize_params.#": "1",
"boot_disk.0.initialize_params.0.size": "12",
"boot_disk.0.initialize_params.0.type": "pd-ssd",
"boot_disk.0.source": instanceName,
"zone": zone,
"create_timeout": "4",
}
runInstanceMigrateTest(t, instanceName, "migrate disk to boot disk", 2 /* state version */, attributes, expected, config)
}
func TestAccComputeInstanceMigrateState_v4FixBootDisk(t *testing.T) {
t.Parallel()
if os.Getenv(resource.TestEnvVar) == "" {
t.Skip(fmt.Sprintf("Network access not allowed; use %s=1 to enable", resource.TestEnvVar))
}
config := getInitializedConfig(t)
zone := "us-central1-f"
// Seed test data
instanceName := fmt.Sprintf("instance-test-%s", acctest.RandString(10))
instance := &compute.Instance{
Name: instanceName,
Disks: []*compute.AttachedDisk{
{
Boot: true,
InitializeParams: &compute.AttachedDiskInitializeParams{
SourceImage: "projects/debian-cloud/global/images/family/debian-8",
},
},
},
MachineType: "zones/" + zone + "/machineTypes/n1-standard-1",
NetworkInterfaces: []*compute.NetworkInterface{
{
Network: "global/networks/default",
},
},
}
op, err := config.clientCompute.Instances.Insert(config.Project, zone, instance).Do()
if err != nil {
t.Fatalf("Error creating instance: %s", err)
}
waitErr := computeSharedOperationWait(config.clientCompute, op, config.Project, "instance to create")
if waitErr != nil {
t.Fatal(waitErr)
}
defer cleanUpInstance(config, instanceName, zone)
attributes := map[string]string{
"disk.#": "1",
"disk.0.disk": "disk-1",
"disk.0.type": "pd-ssd",
"disk.0.auto_delete": "false",
"disk.0.size": "12",
"disk.0.device_name": "persistent-disk-0",
"disk.0.disk_encryption_key_raw": "encrypt-key",
"disk.0.disk_encryption_key_sha256": "encrypt-key-sha",
"zone": zone,
}
expected := map[string]string{
"boot_disk.#": "1",
"boot_disk.0.auto_delete": "false",
"boot_disk.0.device_name": "persistent-disk-0",
"boot_disk.0.disk_encryption_key_raw": "encrypt-key",
"boot_disk.0.disk_encryption_key_sha256": "encrypt-key-sha",
"boot_disk.0.initialize_params.#": "1",
"boot_disk.0.initialize_params.0.size": "12",
"boot_disk.0.initialize_params.0.type": "pd-ssd",
"boot_disk.0.source": instanceName,
"zone": zone,
}
runInstanceMigrateTest(t, instanceName, "migrate disk to boot disk", 4 /* state version */, attributes, expected, config)
}
func TestAccComputeInstanceMigrateState_attachedDiskFromSource(t *testing.T) {
t.Parallel()
if os.Getenv(resource.TestEnvVar) == "" {
t.Skip(fmt.Sprintf("Network access not allowed; use %s=1 to enable", resource.TestEnvVar))
}
config := getInitializedConfig(t)
zone := "us-central1-f"
// Seed test data
diskName := fmt.Sprintf("instance-test-%s", acctest.RandString(10))
disk := &compute.Disk{
Name: diskName,
SourceImage: "projects/debian-cloud/global/images/family/debian-8",
Zone: zone,
}
op, err := config.clientCompute.Disks.Insert(config.Project, zone, disk).Do()
if err != nil {
t.Fatalf("Error creating disk: %s", err)
}
waitErr := computeSharedOperationWait(config.clientCompute, op, config.Project, "disk to create")
if waitErr != nil {
t.Fatal(waitErr)
}
defer cleanUpDisk(config, diskName, zone)
instanceName := fmt.Sprintf("instance-test-%s", acctest.RandString(10))
instance := &compute.Instance{
Name: instanceName,
Disks: []*compute.AttachedDisk{
{
Boot: true,
InitializeParams: &compute.AttachedDiskInitializeParams{
SourceImage: "projects/debian-cloud/global/images/family/debian-8",
},
},
{
Source: "projects/" + config.Project + "/zones/" + zone + "/disks/" + diskName,
},
},
MachineType: "zones/" + zone + "/machineTypes/n1-standard-1",
NetworkInterfaces: []*compute.NetworkInterface{
{
Network: "global/networks/default",
},
},
}
op, err = config.clientCompute.Instances.Insert(config.Project, zone, instance).Do()
if err != nil {
t.Fatalf("Error creating instance: %s", err)
}
waitErr = computeSharedOperationWait(config.clientCompute, op, config.Project, "instance to create")
if waitErr != nil {
t.Fatal(waitErr)
}
defer cleanUpInstance(config, instanceName, zone)
attributes := map[string]string{
"boot_disk.#": "1",
"disk.#": "1",
"disk.0.disk": diskName,
"disk.0.device_name": "persistent-disk-1",
"disk.0.disk_encryption_key_raw": "encrypt-key",
"disk.0.disk_encryption_key_sha256": "encrypt-key-sha",
"zone": zone,
}
expected := map[string]string{
"boot_disk.#": "1",
"attached_disk.#": "1",
"attached_disk.0.source": "https://www.googleapis.com/compute/v1/projects/" + config.Project + "/zones/" + zone + "/disks/" + diskName,
"attached_disk.0.device_name": "persistent-disk-1",
"attached_disk.0.disk_encryption_key_raw": "encrypt-key",
"attached_disk.0.disk_encryption_key_sha256": "encrypt-key-sha",
"zone": zone,
"create_timeout": "4",
}
runInstanceMigrateTest(t, instanceName, "migrate disk to attached disk", 2 /* state version */, attributes, expected, config)
}
func TestAccComputeInstanceMigrateState_v4FixAttachedDiskFromSource(t *testing.T) {
t.Parallel()
if os.Getenv(resource.TestEnvVar) == "" {
t.Skip(fmt.Sprintf("Network access not allowed; use %s=1 to enable", resource.TestEnvVar))
}
config := getInitializedConfig(t)
zone := "us-central1-f"
// Seed test data
diskName := fmt.Sprintf("instance-test-%s", acctest.RandString(10))
disk := &compute.Disk{
Name: diskName,
SourceImage: "projects/debian-cloud/global/images/family/debian-8",
Zone: zone,
}
op, err := config.clientCompute.Disks.Insert(config.Project, zone, disk).Do()
if err != nil {
t.Fatalf("Error creating disk: %s", err)
}
waitErr := computeSharedOperationWait(config.clientCompute, op, config.Project, "disk to create")
if waitErr != nil {
t.Fatal(waitErr)
}
defer cleanUpDisk(config, diskName, zone)
instanceName := fmt.Sprintf("instance-test-%s", acctest.RandString(10))
instance := &compute.Instance{
Name: instanceName,
Disks: []*compute.AttachedDisk{
{
Boot: true,
InitializeParams: &compute.AttachedDiskInitializeParams{
SourceImage: "projects/debian-cloud/global/images/family/debian-8",
},
},
{
Source: "projects/" + config.Project + "/zones/" + zone + "/disks/" + diskName,
},
},
MachineType: "zones/" + zone + "/machineTypes/n1-standard-1",
NetworkInterfaces: []*compute.NetworkInterface{
{
Network: "global/networks/default",
},
},
}
op, err = config.clientCompute.Instances.Insert(config.Project, zone, instance).Do()
if err != nil {
t.Fatalf("Error creating instance: %s", err)
}
waitErr = computeSharedOperationWait(config.clientCompute, op, config.Project, "instance to create")
if waitErr != nil {
t.Fatal(waitErr)
}
defer cleanUpInstance(config, instanceName, zone)
attributes := map[string]string{
"boot_disk.#": "1",
"disk.#": "1",
"disk.0.disk": diskName,
"disk.0.device_name": "persistent-disk-1",
"disk.0.disk_encryption_key_raw": "encrypt-key",
"disk.0.disk_encryption_key_sha256": "encrypt-key-sha",
"zone": zone,
}
expected := map[string]string{
"boot_disk.#": "1",
"attached_disk.#": "1",
"attached_disk.0.source": "https://www.googleapis.com/compute/v1/projects/" + config.Project + "/zones/" + zone + "/disks/" + diskName,
"attached_disk.0.device_name": "persistent-disk-1",
"attached_disk.0.disk_encryption_key_raw": "encrypt-key",
"attached_disk.0.disk_encryption_key_sha256": "encrypt-key-sha",
"zone": zone,
}
runInstanceMigrateTest(t, instanceName, "migrate disk to attached disk", 4 /* state version */, attributes, expected, config)
}
func TestAccComputeInstanceMigrateState_attachedDiskFromEncryptionKey(t *testing.T) {
t.Parallel()
if os.Getenv(resource.TestEnvVar) == "" {
t.Skip(fmt.Sprintf("Network access not allowed; use %s=1 to enable", resource.TestEnvVar))
}
config := getInitializedConfig(t)
zone := "us-central1-f"
instanceName := fmt.Sprintf("instance-test-%s", acctest.RandString(10))
instance := &compute.Instance{
Name: instanceName,
Disks: []*compute.AttachedDisk{
{
Boot: true,
InitializeParams: &compute.AttachedDiskInitializeParams{
SourceImage: "projects/debian-cloud/global/images/family/debian-8",
},
},
{
AutoDelete: true,
InitializeParams: &compute.AttachedDiskInitializeParams{
SourceImage: "projects/debian-cloud/global/images/family/debian-8",
},
DiskEncryptionKey: &compute.CustomerEncryptionKey{
RawKey: "SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=",
},
},
},
MachineType: "zones/" + zone + "/machineTypes/n1-standard-1",
NetworkInterfaces: []*compute.NetworkInterface{
{
Network: "global/networks/default",
},
},
}
op, err := config.clientCompute.Instances.Insert(config.Project, zone, instance).Do()
if err != nil {
t.Fatalf("Error creating instance: %s", err)
}
waitErr := computeSharedOperationWait(config.clientCompute, op, config.Project, "instance to create")
if waitErr != nil {
t.Fatal(waitErr)
}
defer cleanUpInstance(config, instanceName, zone)
attributes := map[string]string{
"boot_disk.#": "1",
"disk.#": "1",
"disk.0.image": "projects/debian-cloud/global/images/family/debian-8",
"disk.0.disk_encryption_key_raw": "SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=",
"disk.0.disk_encryption_key_sha256": "esTuF7d4eatX4cnc4JsiEiaI+Rff78JgPhA/v1zxX9E=",
"zone": zone,
}
expected := map[string]string{
"boot_disk.#": "1",
"attached_disk.#": "1",
"attached_disk.0.source": "https://www.googleapis.com/compute/v1/projects/" + config.Project + "/zones/" + zone + "/disks/" + instanceName + "-1",
"attached_disk.0.device_name": "persistent-disk-1",
"attached_disk.0.disk_encryption_key_raw": "SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=",
"attached_disk.0.disk_encryption_key_sha256": "esTuF7d4eatX4cnc4JsiEiaI+Rff78JgPhA/v1zxX9E=",
"zone": zone,
"create_timeout": "4",
}
runInstanceMigrateTest(t, instanceName, "migrate disk to attached disk", 2 /* state version */, attributes, expected, config)
}
func TestAccComputeInstanceMigrateState_v4FixAttachedDiskFromEncryptionKey(t *testing.T) {
t.Parallel()
if os.Getenv(resource.TestEnvVar) == "" {
t.Skip(fmt.Sprintf("Network access not allowed; use %s=1 to enable", resource.TestEnvVar))
}
config := getInitializedConfig(t)
zone := "us-central1-f"
instanceName := fmt.Sprintf("instance-test-%s", acctest.RandString(10))
instance := &compute.Instance{
Name: instanceName,
Disks: []*compute.AttachedDisk{
{
Boot: true,
InitializeParams: &compute.AttachedDiskInitializeParams{
SourceImage: "projects/debian-cloud/global/images/family/debian-8",
},
},
{
AutoDelete: true,
InitializeParams: &compute.AttachedDiskInitializeParams{
SourceImage: "projects/debian-cloud/global/images/family/debian-8",
},
DiskEncryptionKey: &compute.CustomerEncryptionKey{
RawKey: "SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=",
},
},
},
MachineType: "zones/" + zone + "/machineTypes/n1-standard-1",
NetworkInterfaces: []*compute.NetworkInterface{
{
Network: "global/networks/default",
},
},
}
op, err := config.clientCompute.Instances.Insert(config.Project, zone, instance).Do()
if err != nil {
t.Fatalf("Error creating instance: %s", err)
}
waitErr := computeSharedOperationWait(config.clientCompute, op, config.Project, "instance to create")
if waitErr != nil {
t.Fatal(waitErr)
}
defer cleanUpInstance(config, instanceName, zone)
attributes := map[string]string{
"boot_disk.#": "1",
"disk.#": "1",
"disk.0.image": "projects/debian-cloud/global/images/family/debian-8",
"disk.0.disk_encryption_key_raw": "SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=",
"disk.0.disk_encryption_key_sha256": "esTuF7d4eatX4cnc4JsiEiaI+Rff78JgPhA/v1zxX9E=",
"zone": zone,
}
expected := map[string]string{
"boot_disk.#": "1",
"attached_disk.#": "1",
"attached_disk.0.source": "https://www.googleapis.com/compute/v1/projects/" + config.Project + "/zones/" + zone + "/disks/" + instanceName + "-1",
"attached_disk.0.device_name": "persistent-disk-1",
"attached_disk.0.disk_encryption_key_raw": "SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=",
"attached_disk.0.disk_encryption_key_sha256": "esTuF7d4eatX4cnc4JsiEiaI+Rff78JgPhA/v1zxX9E=",
"zone": zone,
}
runInstanceMigrateTest(t, instanceName, "migrate disk to attached disk", 4 /* state version */, attributes, expected, config)
}
func TestAccComputeInstanceMigrateState_attachedDiskFromAutoDeleteAndImage(t *testing.T) {
t.Parallel()
if os.Getenv(resource.TestEnvVar) == "" {
t.Skip(fmt.Sprintf("Network access not allowed; use %s=1 to enable", resource.TestEnvVar))
}
config := getInitializedConfig(t)
zone := "us-central1-f"
instanceName := fmt.Sprintf("instance-test-%s", acctest.RandString(10))
instance := &compute.Instance{
Name: instanceName,
Disks: []*compute.AttachedDisk{
{
Boot: true,
InitializeParams: &compute.AttachedDiskInitializeParams{
SourceImage: "projects/debian-cloud/global/images/family/debian-8",
},
},
{
AutoDelete: true,
InitializeParams: &compute.AttachedDiskInitializeParams{
SourceImage: "projects/debian-cloud/global/images/family/debian-8",
},
},
{
AutoDelete: true,
InitializeParams: &compute.AttachedDiskInitializeParams{
SourceImage: "projects/debian-cloud/global/images/debian-8-jessie-v20170110",
},
},
},
MachineType: "zones/" + zone + "/machineTypes/n1-standard-1",
NetworkInterfaces: []*compute.NetworkInterface{
{
Network: "global/networks/default",
},
},
}
op, err := config.clientCompute.Instances.Insert(config.Project, zone, instance).Do()
if err != nil {
t.Fatalf("Error creating instance: %s", err)
}
waitErr := computeSharedOperationWait(config.clientCompute, op, config.Project, "instance to create")
if waitErr != nil {
t.Fatal(waitErr)
}
defer cleanUpInstance(config, instanceName, zone)
attributes := map[string]string{
"boot_disk.#": "1",
"disk.#": "2",
"disk.0.image": "projects/debian-cloud/global/images/debian-8-jessie-v20170110",
"disk.0.auto_delete": "true",
"disk.1.image": "global/images/family/debian-8",
"disk.1.auto_delete": "true",
"zone": zone,
}
expected := map[string]string{
"boot_disk.#": "1",
"attached_disk.#": "2",
"attached_disk.0.source": "https://www.googleapis.com/compute/v1/projects/" + config.Project + "/zones/" + zone + "/disks/" + instanceName + "-2",
"attached_disk.0.device_name": "persistent-disk-2",
"attached_disk.1.source": "https://www.googleapis.com/compute/v1/projects/" + config.Project + "/zones/" + zone + "/disks/" + instanceName + "-1",
"attached_disk.1.device_name": "persistent-disk-1",
"zone": zone,
"create_timeout": "4",
}
runInstanceMigrateTest(t, instanceName, "migrate disk to attached disk", 2 /* state version */, attributes, expected, config)
}
func TestAccComputeInstanceMigrateState_v4FixAttachedDiskFromAutoDeleteAndImage(t *testing.T) {
t.Parallel()
if os.Getenv(resource.TestEnvVar) == "" {
t.Skip(fmt.Sprintf("Network access not allowed; use %s=1 to enable", resource.TestEnvVar))
}
config := getInitializedConfig(t)
zone := "us-central1-f"
instanceName := fmt.Sprintf("instance-test-%s", acctest.RandString(10))
instance := &compute.Instance{
Name: instanceName,
Disks: []*compute.AttachedDisk{
{
Boot: true,
InitializeParams: &compute.AttachedDiskInitializeParams{
SourceImage: "projects/debian-cloud/global/images/family/debian-8",
},
},
{
AutoDelete: true,
InitializeParams: &compute.AttachedDiskInitializeParams{
SourceImage: "projects/debian-cloud/global/images/family/debian-8",
},
},
{
AutoDelete: true,
InitializeParams: &compute.AttachedDiskInitializeParams{
SourceImage: "projects/debian-cloud/global/images/debian-8-jessie-v20170110",
},
},
},
MachineType: "zones/" + zone + "/machineTypes/n1-standard-1",
NetworkInterfaces: []*compute.NetworkInterface{
{
Network: "global/networks/default",
},
},
}
op, err := config.clientCompute.Instances.Insert(config.Project, zone, instance).Do()
if err != nil {
t.Fatalf("Error creating instance: %s", err)
}
waitErr := computeSharedOperationWait(config.clientCompute, op, config.Project, "instance to create")
if waitErr != nil {
t.Fatal(waitErr)
}
defer cleanUpInstance(config, instanceName, zone)
attributes := map[string]string{
"boot_disk.#": "1",
"disk.#": "2",
"disk.0.image": "projects/debian-cloud/global/images/debian-8-jessie-v20170110",
"disk.0.auto_delete": "true",
"disk.1.image": "global/images/family/debian-8",
"disk.1.auto_delete": "true",
"zone": zone,
}
expected := map[string]string{
"boot_disk.#": "1",
"attached_disk.#": "2",
"attached_disk.0.source": "https://www.googleapis.com/compute/v1/projects/" + config.Project + "/zones/" + zone + "/disks/" + instanceName + "-2",
"attached_disk.0.device_name": "persistent-disk-2",
"attached_disk.1.source": "https://www.googleapis.com/compute/v1/projects/" + config.Project + "/zones/" + zone + "/disks/" + instanceName + "-1",
"attached_disk.1.device_name": "persistent-disk-1",
"zone": zone,
}
runInstanceMigrateTest(t, instanceName, "migrate disk to attached disk", 4 /* state version */, attributes, expected, config)
}
func TestAccComputeInstanceMigrateState_scratchDisk(t *testing.T) {
t.Parallel()
if os.Getenv(resource.TestEnvVar) == "" {
t.Skip(fmt.Sprintf("Network access not allowed; use %s=1 to enable", resource.TestEnvVar))
}
config := getInitializedConfig(t)
zone := "us-central1-f"
// Seed test data
instanceName := fmt.Sprintf("instance-test-%s", acctest.RandString(10))
instance := &compute.Instance{
Name: instanceName,
Disks: []*compute.AttachedDisk{
{
Boot: true,
InitializeParams: &compute.AttachedDiskInitializeParams{
SourceImage: "projects/debian-cloud/global/images/family/debian-8",
},
},
{
AutoDelete: true,
Type: "SCRATCH",
InitializeParams: &compute.AttachedDiskInitializeParams{
DiskType: "zones/" + zone + "/diskTypes/local-ssd",
},
},
},
MachineType: "zones/" + zone + "/machineTypes/n1-standard-1",
NetworkInterfaces: []*compute.NetworkInterface{
{
Network: "global/networks/default",
},
},
}
op, err := config.clientCompute.Instances.Insert(config.Project, zone, instance).Do()
if err != nil {
t.Fatalf("Error creating instance: %s", err)
}
waitErr := computeSharedOperationWait(config.clientCompute, op, config.Project, "instance to create")
if waitErr != nil {
t.Fatal(waitErr)
}
defer cleanUpInstance(config, instanceName, zone)
attributes := map[string]string{
"boot_disk.#": "1",
"disk.#": "1",
"disk.0.auto_delete": "true",
"disk.0.type": "local-ssd",
"disk.0.scratch": "true",
"zone": zone,
}
expected := map[string]string{
"boot_disk.#": "1",
"scratch_disk.#": "1",
"scratch_disk.0.interface": "SCSI",
"zone": zone,
"create_timeout": "4",
}
runInstanceMigrateTest(t, instanceName, "migrate disk to scratch disk", 2 /* state version */, attributes, expected, config)
}
func TestAccComputeInstanceMigrateState_v4FixScratchDisk(t *testing.T) {
t.Parallel()
if os.Getenv(resource.TestEnvVar) == "" {
t.Skip(fmt.Sprintf("Network access not allowed; use %s=1 to enable", resource.TestEnvVar))
}
config := getInitializedConfig(t)
zone := "us-central1-f"
// Seed test data
instanceName := fmt.Sprintf("instance-test-%s", acctest.RandString(10))
instance := &compute.Instance{
Name: instanceName,
Disks: []*compute.AttachedDisk{
{
Boot: true,
InitializeParams: &compute.AttachedDiskInitializeParams{
SourceImage: "projects/debian-cloud/global/images/family/debian-8",
},
},
{
AutoDelete: true,
Type: "SCRATCH",
InitializeParams: &compute.AttachedDiskInitializeParams{
DiskType: "zones/" + zone + "/diskTypes/local-ssd",
},
},
},
MachineType: "zones/" + zone + "/machineTypes/n1-standard-1",
NetworkInterfaces: []*compute.NetworkInterface{
{
Network: "global/networks/default",
},
},
}
op, err := config.clientCompute.Instances.Insert(config.Project, zone, instance).Do()
if err != nil {
t.Fatalf("Error creating instance: %s", err)
}
waitErr := computeSharedOperationWait(config.clientCompute, op, config.Project, "instance to create")
if waitErr != nil {
t.Fatal(waitErr)
}
defer cleanUpInstance(config, instanceName, zone)
attributes := map[string]string{
"boot_disk.#": "1",
"disk.#": "1",
"disk.0.auto_delete": "true",
"disk.0.type": "local-ssd",
"disk.0.scratch": "true",
"zone": zone,
}
expected := map[string]string{
"boot_disk.#": "1",
"scratch_disk.#": "1",
"scratch_disk.0.interface": "SCSI",
"zone": zone,
}
runInstanceMigrateTest(t, instanceName, "migrate disk to scratch disk", 4 /* state version */, attributes, expected, config)
}
func runInstanceMigrateTest(t *testing.T, id, testName string, version int, attributes, expected map[string]string, meta interface{}) {
is := &terraform.InstanceState{
ID: id,
Attributes: attributes,
}
is, err := resourceComputeInstanceMigrateState(version, is, meta)
if err != nil {
t.Fatal(err)
}
for k, v := range expected {
if attributes[k] != v {
t.Fatalf(
"bad: %s\n\n expected: %#v -> %#v\n got: %#v -> %#v\n in: %#v",
testName, k, expected[k], k, attributes[k], attributes)
}
}
for k, v := range attributes {
if expected[k] != v {
t.Fatalf(
"bad: %s\n\n expected: %#v -> %#v\n got: %#v -> %#v\n in: %#v",
testName, k, expected[k], k, attributes[k], attributes)
}
}
}
func cleanUpInstance(config *Config, instanceName, zone string) {
op, err := config.clientCompute.Instances.Delete(config.Project, zone, instanceName).Do()
if err != nil {
log.Printf("[WARNING] Error deleting instance %q, dangling resources may exist: %s", instanceName, err)
return
}
// Wait for the operation to complete
opErr := computeOperationWait(config.clientCompute, op, config.Project, "instance to delete")
if opErr != nil {
log.Printf("[WARNING] Error deleting instance %q, dangling resources may exist: %s", instanceName, opErr)
}
}
func cleanUpDisk(config *Config, diskName, zone string) {
op, err := config.clientCompute.Disks.Delete(config.Project, zone, diskName).Do()
if err != nil {
log.Printf("[WARNING] Error deleting disk %q, dangling resources may exist: %s", diskName, err)
return
}
// Wait for the operation to complete
opErr := computeOperationWait(config.clientCompute, op, config.Project, "disk to delete")
if opErr != nil {
log.Printf("[WARNING] Error deleting disk %q, dangling resources may exist: %s", diskName, opErr)
}
}
func getInitializedConfig(t *testing.T) *Config {
// Check that all required environment variables are set
testAccPreCheck(t)
config := &Config{
Project: getTestProjectFromEnv(),
Credentials: getTestCredsFromEnv(),
Region: getTestRegionFromEnv(),
}
err := config.loadAndValidate()
if err != nil {
t.Fatal(err)
}
return config
}