diff --git a/google-beta/resource_compute_snapshot.go b/google-beta/resource_compute_snapshot.go index 8749ab1fa1..cf34b8f8ec 100644 --- a/google-beta/resource_compute_snapshot.go +++ b/google-beta/resource_compute_snapshot.go @@ -21,145 +21,10 @@ import ( "strconv" "time" - "github.com/hashicorp/terraform/helper/customdiff" "github.com/hashicorp/terraform/helper/schema" compute "google.golang.org/api/compute/v1" ) -func customDiffComputeSnapshotSnapshotEncryptionKeys(diff *schema.ResourceDiff, meta interface{}) error { - oldConvenience, newConvenience := diff.GetChange("snapshot_encryption_key_raw") - oldNewField, newNewField := diff.GetChange("snapshot_encryption_key.0.raw_key") - - if newConvenience != "" && newNewField != "" { - return fmt.Errorf("can't use snapshot_encryption_key_raw and snapshot_encryption_key.0.raw_key at the same time." + - "If you're removing snapshot_encryption_key.0.raw_key, set the value to \"\" instead. This is due to limitations in Terraform.") - } - - // Either field (convenience or new) has a value - // and then has another different value, so we ForceNew. - // We need to handle _EVERY_ ForceNew case in this diff - if oldConvenience != "" && newConvenience != "" && oldConvenience != newConvenience { - return diff.ForceNew("snapshot_encryption_key_raw") - } - - if oldNewField != "" && newNewField != "" && oldNewField != newNewField { - return diff.ForceNew("snapshot_encryption_key.0.raw_key") - } - - // Our resource isn't using either field, then uses one; - // ForceNew on whichever one is now using it. - if (oldConvenience == "" && oldNewField == "" && newConvenience != "") || (oldConvenience == "" && oldNewField == "" && newNewField != "") { - if oldConvenience == "" && newConvenience != "" { - return diff.ForceNew("snapshot_encryption_key_raw") - } else { - return diff.ForceNew("snapshot_encryption_key.0.raw_key") - } - } - - // convenience no longer used - if oldConvenience != "" && newConvenience == "" { - if newNewField == "" { - // convenience is being nulled, and the new field is empty as well - // we've stopped using the field altogether - return diff.ForceNew("snapshot_encryption_key_raw") - } else if oldConvenience != newNewField { - // convenience is being nulled, and the new field has a new value - // so we ForceNew on either field - return diff.ForceNew("snapshot_encryption_key_raw") - } else { - // If we reach it here, we're using the same value in the new field as we had in the convenience field - } - } - - // new no longer used - // note that it will remain _set_ because of how Computed fields work - // unset fields will have their values kept in state as a non-zero value - if oldNewField != "" && newNewField == "" { - if newConvenience == "" { - // new field is being nulled, and the convenience field is empty as well - // we've stopped using the field altogether - return diff.ForceNew("snapshot_encryption_key.0.raw_key") - } else if oldNewField != newConvenience { - // new is being nulled, and the convenience field has a new value - // so we ForceNew on either field - - // This stops a really opaque diffs don't match during apply error. Without this, wee see - // a diff from the old state -> new state with a ForceNew at plan time (as expected!) - // But during apply time the entire nested object is nil in old state unexpectedly. - // So we just force the diff to match more by nilling it here, which is unclear why it - // works, and probably a worse UX with some real ugly diff, but also makes the tests pass. - // Computed nested fields are hard. - err := diff.SetNew("snapshot_encryption_key", nil) - if err != nil { - return err - } - - return diff.ForceNew("snapshot_encryption_key.0.raw_key") - } else { - // If we reach it here, we're using the same value in the convenience field as we had in the new field - } - } - - return nil -} - -func customDiffComputeSnapshotSourceDiskEncryptionKeys(diff *schema.ResourceDiff, meta interface{}) error { - oldConvenience, newConvenience := diff.GetChange("source_disk_encryption_key_raw") - oldNewField, newNewField := diff.GetChange("source_disk_encryption_key.0.raw_key") - - // Either field has a value and then has another value - // We need to handle _EVERY_ ForceNew case in this diff - if oldConvenience != "" && newConvenience != "" && oldConvenience != newConvenience { - return diff.ForceNew("source_disk_encryption_key_raw") - } - - if oldNewField != "" && newNewField != "" && oldNewField != newNewField { - return diff.ForceNew("source_disk_encryption_key.0.raw_key") - } - - // Our resource isn't using either field, then uses one; - // ForceNew on whichever one is now using it. - if (oldConvenience == "" && oldNewField == "" && newConvenience != "") || (oldConvenience == "" && oldNewField == "" && newNewField != "") { - if oldConvenience == "" && newConvenience != "" { - return diff.ForceNew("source_disk_encryption_key_raw") - } else { - return diff.ForceNew("source_disk_encryption_key.0.raw_key") - } - } - - // convenience no longer used - if oldConvenience != "" && newConvenience == "" { - if newNewField == "" { - // convenience is being nulled, and the new field is empty as well - // we've stopped using the field altogether - return diff.ForceNew("source_disk_encryption_key_raw") - } else if oldConvenience != newNewField { - // convenience is being nulled, and the new field has a new value - // so we ForceNew on either field - return diff.ForceNew("source_disk_encryption_key_raw") - } else { - // If we reach it here, we're using the same value in the new field as we had in the convenience field - } - } - - // new no longer used - if oldNewField != "" && newNewField == "" { - if newConvenience == "" { - // new field is being nulled, and the convenience field is empty as well - // we've stopped using the field altogether - return diff.ForceNew("source_disk_encryption_key.0.raw_key") - } else if newConvenience != oldNewField { - // new is being nulled, and the convenience field has a new value - // so we ForceNew on either field - return diff.ForceNew("source_disk_encryption_key.0.raw_key") - } else { - // If we reach it here, we're using the same value in the convenience field as we had in the new field - } - } - - return nil -} - func resourceComputeSnapshot() *schema.Resource { return &schema.Resource{ Create: resourceComputeSnapshotCreate, @@ -177,11 +42,6 @@ func resourceComputeSnapshot() *schema.Resource { Delete: schema.DefaultTimeout(300 * time.Second), }, - CustomizeDiff: customdiff.All( - customDiffComputeSnapshotSnapshotEncryptionKeys, - customDiffComputeSnapshotSourceDiskEncryptionKeys, - ), - Schema: map[string]*schema.Schema{ "name": { Type: schema.TypeString, @@ -206,14 +66,15 @@ func resourceComputeSnapshot() *schema.Resource { }, "snapshot_encryption_key": { Type: schema.TypeList, - Computed: true, Optional: true, + ForceNew: true, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "raw_key": { Type: schema.TypeString, Optional: true, + ForceNew: true, Sensitive: true, }, "sha256": { @@ -226,12 +87,14 @@ func resourceComputeSnapshot() *schema.Resource { "source_disk_encryption_key": { Type: schema.TypeList, Optional: true, + ForceNew: true, MaxItems: 1, Elem: &schema.Resource{ Schema: map[string]*schema.Schema{ "raw_key": { Type: schema.TypeString, Optional: true, + ForceNew: true, Sensitive: true, }, }, @@ -278,29 +141,29 @@ func resourceComputeSnapshot() *schema.Resource { }, "snapshot_encryption_key_raw": { - Type: schema.TypeString, - Optional: true, - Sensitive: true, - Deprecated: "Use snapshot_encryption_key.raw_key instead.", + Type: schema.TypeString, + Optional: true, + Sensitive: true, + Removed: "Use snapshot_encryption_key.raw_key instead.", }, "snapshot_encryption_key_sha256": { - Type: schema.TypeString, - Computed: true, - Deprecated: "Use snapshot_encryption_key.sha256 instead.", + Type: schema.TypeString, + Computed: true, + Removed: "Use snapshot_encryption_key.sha256 instead.", }, "source_disk_encryption_key_raw": { - Type: schema.TypeString, - Optional: true, - Sensitive: true, - Deprecated: "Use source_disk_encryption_key.raw_key instead.", + Type: schema.TypeString, + Optional: true, + Sensitive: true, + Removed: "Use source_disk_encryption_key.raw_key instead.", }, "source_disk_encryption_key_sha256": { - Type: schema.TypeString, - Computed: true, - Deprecated: "Use source_disk_encryption_key.sha256 instead.", + Type: schema.TypeString, + Computed: true, + Removed: "Use source_disk_encryption_key.sha256 instead.", }, "project": { Type: schema.TypeString, @@ -713,47 +576,62 @@ func expandComputeSnapshotZone(v interface{}, d *schema.ResourceData, config *Co func expandComputeSnapshotSnapshotEncryptionKey(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) - req := make([]interface{}, 0, 1) - if len(l) == 1 && l[0].(map[string]interface{})["raw_key"] != "" { - // There is a value - outMap := make(map[string]interface{}) - outMap["rawKey"] = l[0].(map[string]interface{})["raw_key"] - req = append(req, outMap) - } else { - // Check alternative setting? - if altV, ok := d.GetOk("snapshot_encryption_key_raw"); ok && altV != "" { - outMap := make(map[string]interface{}) - outMap["rawKey"] = altV - req = append(req, outMap) - } + if len(l) == 0 || l[0] == nil { + return nil, nil + } + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedRawKey, err := expandComputeSnapshotSnapshotEncryptionKeyRawKey(original["raw_key"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRawKey); val.IsValid() && !isEmptyValue(val) { + transformed["rawKey"] = transformedRawKey } - return req, nil + + transformedSha256, err := expandComputeSnapshotSnapshotEncryptionKeySha256(original["sha256"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedSha256); val.IsValid() && !isEmptyValue(val) { + transformed["sha256"] = transformedSha256 + } + + return transformed, nil +} + +func expandComputeSnapshotSnapshotEncryptionKeyRawKey(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil +} + +func expandComputeSnapshotSnapshotEncryptionKeySha256(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil } func expandComputeSnapshotSourceDiskEncryptionKey(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { l := v.([]interface{}) - req := make([]interface{}, 0, 1) - if len(l) == 1 { - // There is a value - outMap := make(map[string]interface{}) - outMap["rawKey"] = l[0].(map[string]interface{})["raw_key"] - req = append(req, outMap) - } else { - // Check alternative setting? - if altV, ok := d.GetOk("source_disk_encryption_key_raw"); ok && altV != "" { - outMap := make(map[string]interface{}) - outMap["rawKey"] = altV - req = append(req, outMap) - } + if len(l) == 0 || l[0] == nil { + return nil, nil } - return req, nil + raw := l[0] + original := raw.(map[string]interface{}) + transformed := make(map[string]interface{}) + + transformedRawKey, err := expandComputeSnapshotSourceDiskEncryptionKeyRawKey(original["raw_key"], d, config) + if err != nil { + return nil, err + } else if val := reflect.ValueOf(transformedRawKey); val.IsValid() && !isEmptyValue(val) { + transformed["rawKey"] = transformedRawKey + } + + return transformed, nil +} + +func expandComputeSnapshotSourceDiskEncryptionKeyRawKey(v interface{}, d *schema.ResourceData, config *Config) (interface{}, error) { + return v, nil } func resourceComputeSnapshotDecoder(d *schema.ResourceData, meta interface{}, res map[string]interface{}) (map[string]interface{}, error) { d.Set("source_disk_link", ConvertSelfLinkToV1(res["sourceDisk"].(string))) - if snapshotEncryptionKey := res["snapshotEncryptionKey"]; snapshotEncryptionKey != nil { - d.Set("snapshot_encryption_key_sha256", snapshotEncryptionKey.((map[string]interface{}))["sha256"]) - } - return res, nil } diff --git a/google-beta/resource_compute_snapshot_generated_test.go b/google-beta/resource_compute_snapshot_generated_test.go new file mode 100644 index 0000000000..12d9ed90b8 --- /dev/null +++ b/google-beta/resource_compute_snapshot_generated_test.go @@ -0,0 +1,94 @@ +// ---------------------------------------------------------------------------- +// +// *** AUTO GENERATED CODE *** AUTO GENERATED CODE *** +// +// ---------------------------------------------------------------------------- +// +// This file is automatically generated by Magic Modules and manual +// changes will be clobbered when the file is regenerated. +// +// Please read more about how to change this file in +// .github/CONTRIBUTING.md. +// +// ---------------------------------------------------------------------------- + +package google + +import ( + "fmt" + "testing" + + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccComputeSnapshot_snapshotBasicExample(t *testing.T) { + t.Parallel() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckComputeSnapshotDestroy, + Steps: []resource.TestStep{ + { + Config: testAccComputeSnapshot_snapshotBasicExample(acctest.RandString(10)), + }, + { + ResourceName: "google_compute_snapshot.snapshot", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"zone", "source_disk_encryption_key"}, + }, + }, + }) +} + +func testAccComputeSnapshot_snapshotBasicExample(val string) string { + return fmt.Sprintf(` +resource "google_compute_snapshot" "snapshot" { + name = "my-snapshot-%s" + source_disk = "${google_compute_disk.persistent.name}" + zone = "us-central1-a" + labels = { + my_label = "value" + } +} + +data "google_compute_image" "debian" { + family = "debian-9" + project = "debian-cloud" +} + +resource "google_compute_disk" "persistent" { + name = "debian-disk-%s" + image = "${data.google_compute_image.debian.self_link}" + size = 10 + type = "pd-ssd" + zone = "us-central1-a" +} +`, val, val, + ) +} + +func testAccCheckComputeSnapshotDestroy(s *terraform.State) error { + for _, rs := range s.RootModule().Resources { + if rs.Type != "google_compute_snapshot" { + continue + } + + config := testAccProvider.Meta().(*Config) + + url, err := replaceVarsForTest(rs, "https://www.googleapis.com/compute/beta/projects/{{project}}/global/snapshots/{{name}}") + if err != nil { + return err + } + + _, err = sendRequest(config, "GET", url, nil) + if err == nil { + return fmt.Errorf("ComputeSnapshot still exists at %s", url) + } + } + + return nil +} diff --git a/google-beta/resource_compute_snapshot_test.go b/google-beta/resource_compute_snapshot_test.go index c83ec28ec3..2ef8be7c1b 100644 --- a/google-beta/resource_compute_snapshot_test.go +++ b/google-beta/resource_compute_snapshot_test.go @@ -2,47 +2,16 @@ package google import ( "fmt" - "regexp" "testing" - "reflect" - "strings" - "github.com/hashicorp/terraform/helper/acctest" "github.com/hashicorp/terraform/helper/resource" - "github.com/hashicorp/terraform/terraform" - "google.golang.org/api/compute/v1" - "google.golang.org/api/googleapi" ) -func TestAccComputeSnapshot_basic(t *testing.T) { - t.Parallel() - - snapshotName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - var snapshot compute.Snapshot - diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckComputeSnapshotDestroy, - Steps: []resource.TestStep{ - resource.TestStep{ - Config: testAccComputeSnapshot_basic(snapshotName, diskName, "my-value"), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), - }, - }, - }) -} - func TestAccComputeSnapshot_update(t *testing.T) { t.Parallel() snapshotName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - var snapshot compute.Snapshot diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) resource.Test(t, resource.TestCase{ @@ -50,480 +19,52 @@ func TestAccComputeSnapshot_update(t *testing.T) { Providers: testAccProviders, CheckDestroy: testAccCheckComputeSnapshotDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccComputeSnapshot_basic(snapshotName, diskName, "my-value"), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), - }, - resource.TestStep{ - Config: testAccComputeSnapshot_basic(snapshotName, diskName, "my-updated-value"), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), - }, - }, - }) -} - -func TestAccComputeSnapshot_encryptionBasic(t *testing.T) { - t.Parallel() - - snapshotName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - var snapshot compute.Snapshot - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckComputeSnapshotDestroy, - Steps: []resource.TestStep{ - resource.TestStep{ - Config: testAccComputeSnapshot_encryption(snapshotName, diskName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), - }, - }, - }) -} - -func TestAccComputeSnapshot_encryptionModify(t *testing.T) { - t.Parallel() - - snapshotName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - var snapshot compute.Snapshot - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckComputeSnapshotDestroy, - Steps: []resource.TestStep{ - resource.TestStep{ - Config: testAccComputeSnapshot_encryption(snapshotName, diskName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), - }, - resource.TestStep{ - Config: testAccComputeSnapshot_encryptionDelta(snapshotName, diskName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), - }, - }, - }) -} - -func TestAccComputeSnapshot_encryptionModifyBad(t *testing.T) { - t.Parallel() - - snapshotName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - var snapshot compute.Snapshot - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckComputeSnapshotDestroy, - Steps: []resource.TestStep{ - resource.TestStep{ - Config: testAccComputeSnapshot_encryption(snapshotName, diskName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), - }, - resource.TestStep{ - Config: testAccComputeSnapshot_encryptionDeltaBad(snapshotName, diskName), - ExpectError: regexp.MustCompile("customerEncryptionKeyIsIncorrect"), - }, - }, - }) -} - -func TestAccComputeSnapshot_encryptionOld(t *testing.T) { - t.Parallel() - - snapshotName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - var snapshot compute.Snapshot - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckComputeSnapshotDestroy, - Steps: []resource.TestStep{ - resource.TestStep{ - Config: testAccComputeSnapshot_encryptionOld(snapshotName, diskName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), - }, - }, - }) -} - -func TestAccComputeSnapshot_encryptionUpgrade(t *testing.T) { - t.Parallel() - - snapshotName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - var snapshot compute.Snapshot - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckComputeSnapshotDestroy, - Steps: []resource.TestStep{ - resource.TestStep{ - Config: testAccComputeSnapshot_encryptionOld(snapshotName, diskName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), - }, - resource.TestStep{ - Config: testAccComputeSnapshot_encryption(snapshotName, diskName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), - }, - }, - }) -} - -func TestAccComputeSnapshot_encryptionUpgradeModify(t *testing.T) { - t.Parallel() - - snapshotName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - var snapshot compute.Snapshot - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckComputeSnapshotDestroy, - Steps: []resource.TestStep{ - resource.TestStep{ - Config: testAccComputeSnapshot_encryptionOld(snapshotName, diskName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), - }, - resource.TestStep{ - Config: testAccComputeSnapshot_encryptionDelta(snapshotName, diskName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), - }, - }, - }) -} - -func TestAccComputeSnapshot_encryptionUpgradeModifyBad(t *testing.T) { - t.Parallel() - - snapshotName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - var snapshot compute.Snapshot - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckComputeSnapshotDestroy, - Steps: []resource.TestStep{ - resource.TestStep{ - Config: testAccComputeSnapshot_encryptionOld(snapshotName, diskName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), }, - resource.TestStep{ - Config: testAccComputeSnapshot_encryptionDeltaBad(snapshotName, diskName), - ExpectError: regexp.MustCompile("customerEncryptionKeyIsIncorrect"), + { + ResourceName: "google_compute_snapshot.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"zone"}, }, - }, - }) -} - -func TestAccComputeSnapshot_encryptionDowngrade(t *testing.T) { - t.Parallel() - - snapshotName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - var snapshot compute.Snapshot - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckComputeSnapshotDestroy, - Steps: []resource.TestStep{ - resource.TestStep{ - Config: testAccComputeSnapshot_encryption(snapshotName, diskName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), - }, - resource.TestStep{ - Config: testAccComputeSnapshot_encryptionOldGuarded(snapshotName, diskName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), - }, - }, - }) -} - -func TestAccComputeSnapshot_encryptionDowngradeModify(t *testing.T) { - t.Parallel() - - snapshotName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - var snapshot compute.Snapshot - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckComputeSnapshotDestroy, - Steps: []resource.TestStep{ - resource.TestStep{ - Config: testAccComputeSnapshot_encryption(snapshotName, diskName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), - }, - resource.TestStep{ - Config: testAccComputeSnapshot_encryptionOldDelta1(snapshotName, diskName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), - }, - resource.TestStep{ - Config: testAccComputeSnapshot_encryptionOldDelta2(snapshotName, diskName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), - }, - }, - }) -} - -func TestAccComputeSnapshot_encryptionDowngradeModifyBad(t *testing.T) { - t.Parallel() - - snapshotName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - var snapshot compute.Snapshot - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckComputeSnapshotDestroy, - Steps: []resource.TestStep{ - resource.TestStep{ - Config: testAccComputeSnapshot_encryption(snapshotName, diskName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), - }, - resource.TestStep{ - Config: testAccComputeSnapshot_encryptionOldDeltaBad(snapshotName, diskName), - ExpectError: regexp.MustCompile("customerEncryptionKeyIsIncorrect"), - }, - }, - }) -} - -func TestAccComputeSnapshot_encryptionOldRemove(t *testing.T) { - t.Parallel() - - snapshotName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - var snapshot compute.Snapshot - - resource.Test(t, resource.TestCase{ - PreCheck: func() { testAccPreCheck(t) }, - Providers: testAccProviders, - CheckDestroy: testAccCheckComputeSnapshotDestroy, - Steps: []resource.TestStep{ - resource.TestStep{ - Config: testAccComputeSnapshot_encryptionOld(snapshotName, diskName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), + { + Config: testAccComputeSnapshot_basic(snapshotName, diskName, "my-updated-value"), }, - resource.TestStep{ - Config: testAccComputeSnapshot_encryptionNone(snapshotName, diskName), - ExpectError: regexp.MustCompile("resourceIsEncryptedWithCustomerEncryptionKey"), + { + ResourceName: "google_compute_snapshot.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"zone"}, }, }, }) } -func TestAccComputeSnapshot_encryptionRemove(t *testing.T) { +func TestAccComputeSnapshot_encryption(t *testing.T) { t.Parallel() snapshotName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) diskName := fmt.Sprintf("tf-test-%s", acctest.RandString(10)) - var snapshot compute.Snapshot resource.Test(t, resource.TestCase{ PreCheck: func() { testAccPreCheck(t) }, Providers: testAccProviders, CheckDestroy: testAccCheckComputeSnapshotDestroy, Steps: []resource.TestStep{ - resource.TestStep{ + { Config: testAccComputeSnapshot_encryption(snapshotName, diskName), - Check: resource.ComposeTestCheckFunc( - testAccCheckComputeSnapshotExists( - "google_compute_snapshot.foobar", &snapshot), - ), }, - resource.TestStep{ - Config: testAccComputeSnapshot_encryptionNone(snapshotName, diskName), - ExpectError: regexp.MustCompile("resourceIsEncryptedWithCustomerEncryptionKey"), + { + ResourceName: "google_compute_snapshot.foobar", + ImportState: true, + ImportStateVerify: true, + ImportStateVerifyIgnore: []string{"zone", "snapshot_encryption_key", "source_disk_encryption_key"}, }, }, }) } -func testAccCheckComputeSnapshotDestroy(s *terraform.State) error { - config := testAccProvider.Meta().(*Config) - - for _, rs := range s.RootModule().Resources { - if rs.Type != "google_compute_snapshot" { - continue - } - - _, err := config.clientCompute.Snapshots.Get( - config.Project, rs.Primary.ID).Do() - if err != nil { - if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == 404 { - return nil - } else if ok { - return fmt.Errorf("Error while requesting Google Cloud Plateform: http code error : %d, http message error: %s", gerr.Code, gerr.Message) - } - return fmt.Errorf("Error while requesting Google Cloud Plateform") - } - return fmt.Errorf("Snapshot still exists") - } - - return nil -} - -func testAccCheckComputeSnapshotExists(n string, snapshot *compute.Snapshot) resource.TestCheckFunc { - return func(s *terraform.State) error { - rs, ok := s.RootModule().Resources[n] - if !ok { - return fmt.Errorf("Not found: %s", n) - } - - if rs.Primary.ID == "" { - return fmt.Errorf("No ID is set") - } - - config := testAccProvider.Meta().(*Config) - - found, err := config.clientCompute.Snapshots.Get( - config.Project, rs.Primary.ID).Do() - if err != nil { - return err - } - - if found.Name != rs.Primary.ID { - return fmt.Errorf("Snapshot %s not found", n) - } - - attr := rs.Primary.Attributes["snapshot_encryption_key_sha256"] - if found.SnapshotEncryptionKey != nil && found.SnapshotEncryptionKey.Sha256 != attr { - return fmt.Errorf("Snapshot %s has mismatched encryption key (Sha256).\nTF State: %+v.\nGCP State: %+v", - n, attr, found.SnapshotEncryptionKey.Sha256) - } else if found.SnapshotEncryptionKey == nil && attr != "" { - return fmt.Errorf("Snapshot %s has mismatched encryption key.\nTF State: %+v.\nGCP State: %+v", - n, attr, found.SnapshotEncryptionKey) - } - - attr = rs.Primary.Attributes["source_disk_encryption_key_sha256"] - if found.SourceDiskEncryptionKey != nil && found.SourceDiskEncryptionKey.Sha256 != attr { - return fmt.Errorf("Snapshot %s has mismatched source disk encryption key (Sha256).\nTF State: %+v.\nGCP State: %+v", - n, attr, found.SourceDiskEncryptionKey.Sha256) - } else if found.SourceDiskEncryptionKey == nil && attr != "" { - return fmt.Errorf("Snapshot %s has mismatched source disk encryption key.\nTF State: %+v.\nGCP State: %+v", - n, attr, found.SourceDiskEncryptionKey) - } - - attr = rs.Primary.Attributes["source_disk_link"] - if found.SourceDisk != attr { - return fmt.Errorf("Snapshot %s has mismatched source disk link.\nTF State: %+v.\nGCP State: %+v", - n, attr, found.SourceDisk) - } - - foundDisk, errDisk := config.clientCompute.Disks.Get( - config.Project, rs.Primary.Attributes["zone"], rs.Primary.Attributes["source_disk"]).Do() - if errDisk != nil { - return errDisk - } - if foundDisk.SelfLink != attr { - return fmt.Errorf("Snapshot %s has mismatched source disk\nTF State: %+v.\nGCP State: %+v", - n, attr, foundDisk.SelfLink) - } - - attr = rs.Primary.Attributes["self_link"] - if found.SelfLink != attr { - return fmt.Errorf("Snapshot %s has mismatched self link.\nTF State: %+v.\nGCP State: %+v", - n, attr, found.SelfLink) - } - - // We should have a map - attr, ok = rs.Primary.Attributes["labels.%"] - if !ok { - return fmt.Errorf("Snapshot %s has no labels map in attributes", n) - } - // Parse out our map - attrMap := make(map[string]string) - for k, v := range rs.Primary.Attributes { - if !strings.HasPrefix(k, "labels.") || k == "labels.%" { - continue - } - key := k[len("labels."):] - attrMap[key] = v - } - if (len(attrMap) != 0 || len(found.Labels) != 0) && !reflect.DeepEqual(attrMap, found.Labels) { - return fmt.Errorf("Snapshot %s has mismatched labels.\nTF State: %+v\nGCP State: %+v", - n, attrMap, found.Labels) - } - - attr = rs.Primary.Attributes["label_fingerprint"] - if found.LabelFingerprint != attr { - return fmt.Errorf("Snapshot %s has mismatched label fingerprint\nTF State: %+v.\nGCP State: %+v", - n, attr, found.LabelFingerprint) - } - - *snapshot = *found - - return nil - } -} - func testAccComputeSnapshot_basic(snapshotName, diskName, labelValue string) string { return fmt.Sprintf(` data "google_compute_image" "my_image" { @@ -580,246 +121,3 @@ resource "google_compute_snapshot" "foobar" { } }`, diskName, snapshotName) } - -func testAccComputeSnapshot_encryptionOld(snapshotName string, diskName string) string { - return fmt.Sprintf(` -data "google_compute_image" "my_image" { - family = "debian-9" - project = "debian-cloud" -} - -resource "google_compute_disk" "foobar" { - name = "%s" - image = "${data.google_compute_image.my_image.self_link}" - size = 10 - type = "pd-ssd" - zone = "us-central1-a" - disk_encryption_key { - raw_key = "SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=" - } -} - -resource "google_compute_snapshot" "foobar" { - name = "%s" - source_disk = "${google_compute_disk.foobar.name}" - zone = "us-central1-a" - source_disk_encryption_key_raw = "SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=" - snapshot_encryption_key_raw = "SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=" -}`, diskName, snapshotName) -} - -func testAccComputeSnapshot_encryptionOldGuarded(snapshotName string, diskName string) string { - return fmt.Sprintf(` -data "google_compute_image" "my_image" { - family = "debian-9" - project = "debian-cloud" -} - -resource "google_compute_disk" "foobar" { - name = "%s" - image = "${data.google_compute_image.my_image.self_link}" - size = 10 - type = "pd-ssd" - zone = "us-central1-a" - disk_encryption_key { - raw_key = "SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=" - } -} - -resource "google_compute_snapshot" "foobar" { - name = "%s" - source_disk = "${google_compute_disk.foobar.name}" - zone = "us-central1-a" - snapshot_encryption_key { - raw_key = "" - } - - source_disk_encryption_key_raw = "SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=" - snapshot_encryption_key_raw = "SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=" -}`, diskName, snapshotName) -} - -func testAccComputeSnapshot_encryptionDelta(snapshotName string, diskName string) string { - return fmt.Sprintf(` -data "google_compute_image" "my_image" { - family = "debian-9" - project = "debian-cloud" -} - -resource "google_compute_disk" "foobar" { - name = "%s" - image = "${data.google_compute_image.my_image.self_link}" - size = 10 - type = "pd-ssd" - zone = "us-central1-a" - disk_encryption_key { - raw_key = "Sznt5GBBAJky3BgBVbDOMLY3TlStz7RikXujsFQ0GlA=" - } -} - -resource "google_compute_snapshot" "foobar" { - name = "%s" - source_disk = "${google_compute_disk.foobar.name}" - zone = "us-central1-a" - snapshot_encryption_key { - raw_key = "Sznt5GBBAJky3BgBVbDOMLY3TlStz7RikXujsFQ0GlA=" - } - - source_disk_encryption_key { - raw_key = "Sznt5GBBAJky3BgBVbDOMLY3TlStz7RikXujsFQ0GlA=" - } -}`, diskName, snapshotName) -} - -func testAccComputeSnapshot_encryptionOldDelta1(snapshotName string, diskName string) string { - return fmt.Sprintf(` -data "google_compute_image" "my_image" { - family = "debian-9" - project = "debian-cloud" -} - -resource "google_compute_disk" "foobar" { - name = "%s" - image = "${data.google_compute_image.my_image.self_link}" - size = 10 - type = "pd-ssd" - zone = "us-central1-a" - disk_encryption_key { - raw_key = "Sznt5GBBAJky3BgBVbDOMLY3TlStz7RikXujsFQ0GlA=" - } -} - -resource "google_compute_snapshot" "foobar" { - name = "%s" - source_disk = "${google_compute_disk.foobar.name}" - zone = "us-central1-a" - snapshot_encryption_key { - raw_key = "" - } - - source_disk_encryption_key { - raw_key = "Sznt5GBBAJky3BgBVbDOMLY3TlStz7RikXujsFQ0GlA=" - } - - snapshot_encryption_key_raw = "Sznt5GBBAJky3BgBVbDOMLY3TlStz7RikXujsFQ0GlA=" -}`, diskName, snapshotName) -} - -func testAccComputeSnapshot_encryptionOldDelta2(snapshotName string, diskName string) string { - return fmt.Sprintf(` -data "google_compute_image" "my_image" { - family = "debian-9" - project = "debian-cloud" -} - -resource "google_compute_disk" "foobar" { - name = "%s" - image = "${data.google_compute_image.my_image.self_link}" - size = 10 - type = "pd-ssd" - zone = "us-central1-a" - disk_encryption_key { - raw_key = "Sznt5GBBAJky3BgBVbDOMLY3TlStz7RikXujsFQ0GlA=" - } -} - -resource "google_compute_snapshot" "foobar" { - name = "%s" - source_disk = "${google_compute_disk.foobar.name}" - zone = "us-central1-a" - snapshot_encryption_key { - raw_key = "" - } - - source_disk_encryption_key_raw = "Sznt5GBBAJky3BgBVbDOMLY3TlStz7RikXujsFQ0GlA=" - snapshot_encryption_key_raw = "Sznt5GBBAJky3BgBVbDOMLY3TlStz7RikXujsFQ0GlA=" -}`, diskName, snapshotName) -} - -func testAccComputeSnapshot_encryptionDeltaBad(snapshotName string, diskName string) string { - return fmt.Sprintf(` -data "google_compute_image" "my_image" { - family = "debian-9" - project = "debian-cloud" -} - -resource "google_compute_disk" "foobar" { - name = "%s" - image = "${data.google_compute_image.my_image.self_link}" - size = 10 - type = "pd-ssd" - zone = "us-central1-a" - disk_encryption_key { - raw_key = "SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=" - } -} - -resource "google_compute_snapshot" "foobar" { - name = "%s" - source_disk = "${google_compute_disk.foobar.name}" - zone = "us-central1-a" - snapshot_encryption_key { - raw_key = "Sznt5GBBAJky3BgBVbDOMLY3TlStz7RikXujsFQ0GlA=" - } - - source_disk_encryption_key { - raw_key = "Sznt5GBBAJky3BgBVbDOMLY3TlStz7RikXujsFQ0GlA=" - } -}`, diskName, snapshotName) -} - -func testAccComputeSnapshot_encryptionOldDeltaBad(snapshotName string, diskName string) string { - return fmt.Sprintf(` -data "google_compute_image" "my_image" { - family = "debian-9" - project = "debian-cloud" -} - -resource "google_compute_disk" "foobar" { - name = "%s" - image = "${data.google_compute_image.my_image.self_link}" - size = 10 - type = "pd-ssd" - zone = "us-central1-a" - disk_encryption_key { - raw_key = "SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=" - } -} - -resource "google_compute_snapshot" "foobar" { - name = "%s" - source_disk = "${google_compute_disk.foobar.name}" - zone = "us-central1-a" - snapshot_encryption_key { - raw_key = "" - } - - source_disk_encryption_key_raw = "Sznt5GBBAJky3BgBVbDOMLY3TlStz7RikXujsFQ0GlA=" - snapshot_encryption_key_raw = "Sznt5GBBAJky3BgBVbDOMLY3TlStz7RikXujsFQ0GlA=" -}`, diskName, snapshotName) -} - -func testAccComputeSnapshot_encryptionNone(snapshotName string, diskName string) string { - return fmt.Sprintf(` -data "google_compute_image" "my_image" { - family = "debian-9" - project = "debian-cloud" -} - -resource "google_compute_disk" "foobar" { - name = "%s" - image = "${data.google_compute_image.my_image.self_link}" - size = 10 - type = "pd-ssd" - zone = "us-central1-a" - disk_encryption_key { - raw_key = "SGVsbG8gZnJvbSBHb29nbGUgQ2xvdWQgUGxhdGZvcm0=" - } -} - -resource "google_compute_snapshot" "foobar" { - name = "%s" - source_disk = "${google_compute_disk.foobar.name}" - zone = "us-central1-a" -}`, diskName, snapshotName) -} diff --git a/website/docs/r/compute_snapshot.html.markdown b/website/docs/r/compute_snapshot.html.markdown index 3898e16216..0990ad0ac7 100644 --- a/website/docs/r/compute_snapshot.html.markdown +++ b/website/docs/r/compute_snapshot.html.markdown @@ -41,6 +41,11 @@ To get more information about Snapshot, see: * How-to Guides * [Official Documentation](https://cloud.google.com/compute/docs/disks/create-snapshots) +
## Example Usage - Snapshot Basic @@ -50,7 +55,7 @@ resource "google_compute_snapshot" "snapshot" { source_disk = "${google_compute_disk.persistent.name}" zone = "us-central1-a" labels = { - my_label = "%s" + my_label = "value" } } @@ -135,13 +140,6 @@ The `source_disk_encryption_key` block supports: Specifies a 256-bit customer-supplied encryption key, encoded in RFC 4648 base64 to either encrypt or decrypt this resource. -* (Deprecated) `snapshot_encryption_key_raw`: (Optional) This is an alias for - `snapshot_encryption_key.0.raw_key`. This field has been deprecated - and will be removed in a future provider version. -* (Deprecated) `source_disk_encryption_key_raw`: (Optional) This is an alias for - `source_disk_encryption_key.0.raw_key`. This field has been deprecated - and will be removed in a future provider version. - ## Attributes Reference In addition to the arguments listed above, the following computed attributes are exported: @@ -173,12 +171,6 @@ In addition to the arguments listed above, the following computed attributes are * `self_link` - The URI of the created resource. -* (Deprecated) `snapshot_encryption_key_sha256`: This is an alias for -`source_disk_encryption_key.0.sha256`. This attribute has been deprecated -and will be removed in a future provider version. -* (Deprecated) `source_disk_encryption_key_sha256`: This attribute has never had -a value and will be removed in a future provider version. - ## Timeouts This resource provides the following