mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-09-07 01:26:43 +00:00
![Nic Cope](/assets/img/avatar_default.png)
* 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
878 lines
29 KiB
Go
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
|
|
}
|