2017-08-14 16:30:41 +00:00
|
|
|
package google
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"testing"
|
|
|
|
|
2018-09-17 18:15:11 +00:00
|
|
|
"github.com/hashicorp/errwrap"
|
2017-08-14 16:30:41 +00:00
|
|
|
"github.com/hashicorp/terraform/helper/acctest"
|
|
|
|
"github.com/hashicorp/terraform/helper/resource"
|
|
|
|
"github.com/hashicorp/terraform/terraform"
|
|
|
|
|
|
|
|
"strings"
|
2018-09-17 18:15:11 +00:00
|
|
|
|
|
|
|
"google.golang.org/api/googleapi"
|
2017-08-14 16:30:41 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
// Unit Tests
|
|
|
|
|
|
|
|
func TestSpannerInstanceId_instanceUri(t *testing.T) {
|
|
|
|
id := spannerInstanceId{
|
|
|
|
Project: "project123",
|
|
|
|
Instance: "instance456",
|
|
|
|
}
|
|
|
|
actual := id.instanceUri()
|
|
|
|
expected := "projects/project123/instances/instance456"
|
|
|
|
expectEquals(t, expected, actual)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSpannerInstanceId_instanceConfigUri(t *testing.T) {
|
|
|
|
id := spannerInstanceId{
|
|
|
|
Project: "project123",
|
|
|
|
Instance: "instance456",
|
|
|
|
}
|
|
|
|
actual := id.instanceConfigUri("conf987")
|
|
|
|
expected := "projects/project123/instanceConfigs/conf987"
|
|
|
|
expectEquals(t, expected, actual)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestSpannerInstanceId_parentProjectUri(t *testing.T) {
|
|
|
|
id := spannerInstanceId{
|
|
|
|
Project: "project123",
|
|
|
|
Instance: "instance456",
|
|
|
|
}
|
|
|
|
actual := id.parentProjectUri()
|
|
|
|
expected := "projects/project123"
|
|
|
|
expectEquals(t, expected, actual)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGenSpannerInstanceName(t *testing.T) {
|
|
|
|
s := genSpannerInstanceName()
|
|
|
|
if len(s) != 30 {
|
|
|
|
t.Fatalf("Expected a 30 char ID to be generated, instead found %d chars", len(s))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestImportSpannerInstanceId(t *testing.T) {
|
|
|
|
sid, e := importSpannerInstanceId("instance456")
|
|
|
|
if e != nil {
|
|
|
|
t.Errorf("Error should have been nil")
|
|
|
|
}
|
|
|
|
expectEquals(t, "", sid.Project)
|
|
|
|
expectEquals(t, "instance456", sid.Instance)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestImportSpannerInstanceId_projectAndInstance(t *testing.T) {
|
|
|
|
sid, e := importSpannerInstanceId("project123/instance456")
|
|
|
|
if e != nil {
|
|
|
|
t.Errorf("Error should have been nil")
|
|
|
|
}
|
|
|
|
expectEquals(t, "project123", sid.Project)
|
|
|
|
expectEquals(t, "instance456", sid.Instance)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestImportSpannerInstanceId_invalidLeadingSlash(t *testing.T) {
|
|
|
|
sid, e := importSpannerInstanceId("/instance456")
|
|
|
|
expectInvalidSpannerInstanceImport(t, sid, e)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestImportSpannerInstanceId_invalidTrailingSlash(t *testing.T) {
|
|
|
|
sid, e := importSpannerInstanceId("project123/")
|
|
|
|
expectInvalidSpannerInstanceImport(t, sid, e)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestImportSpannerInstanceId_invalidSingleSlash(t *testing.T) {
|
|
|
|
sid, e := importSpannerInstanceId("/")
|
|
|
|
expectInvalidSpannerInstanceImport(t, sid, e)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestImportSpannerInstanceId_invalidMultiSlash(t *testing.T) {
|
|
|
|
sid, e := importSpannerInstanceId("project123/instance456/db789")
|
|
|
|
expectInvalidSpannerInstanceImport(t, sid, e)
|
|
|
|
}
|
|
|
|
|
2018-03-05 21:24:55 +00:00
|
|
|
func TestImportSpannerInstanceId_projectId(t *testing.T) {
|
|
|
|
shouldPass := []string{
|
|
|
|
"project-id/instance",
|
|
|
|
"123123/instance",
|
|
|
|
"hashicorptest.net:project-123/instance",
|
|
|
|
"123/456",
|
|
|
|
}
|
|
|
|
|
|
|
|
shouldFail := []string{
|
|
|
|
"project-id#/instance",
|
|
|
|
"project-id/instance#",
|
|
|
|
"hashicorptest.net:project-123:invalid:project/instance",
|
|
|
|
"hashicorptest.net:/instance",
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, element := range shouldPass {
|
|
|
|
_, e := importSpannerInstanceId(element)
|
|
|
|
if e != nil {
|
|
|
|
t.Error("importSpannerInstanceId should pass on '" + element + "' but doesn't")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, element := range shouldFail {
|
|
|
|
_, e := importSpannerInstanceId(element)
|
|
|
|
if e == nil {
|
|
|
|
t.Error("importSpannerInstanceId should fail on '" + element + "' but doesn't")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-08-14 16:30:41 +00:00
|
|
|
func expectInvalidSpannerInstanceImport(t *testing.T, sid *spannerInstanceId, e error) {
|
|
|
|
if sid != nil {
|
|
|
|
t.Errorf("Expected spannerInstanceId to be nil")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if e == nil {
|
|
|
|
t.Errorf("Expected an Error but did not get one")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if !strings.HasPrefix(e.Error(), "Invalid spanner instance specifier") {
|
|
|
|
t.Errorf("Expecting Error starting with 'Invalid spanner instance specifier'")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func expectEquals(t *testing.T, expected, actual string) {
|
|
|
|
if actual != expected {
|
|
|
|
t.Fatalf("Expected %s, but got %s", expected, actual)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Acceptance Tests
|
|
|
|
|
|
|
|
func TestAccSpannerInstance_basic(t *testing.T) {
|
2017-10-12 22:07:29 +00:00
|
|
|
t.Parallel()
|
|
|
|
|
2018-09-17 18:15:11 +00:00
|
|
|
idName := fmt.Sprintf("spanner-test-%s", acctest.RandString(10))
|
2017-08-14 16:30:41 +00:00
|
|
|
resource.Test(t, resource.TestCase{
|
|
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
|
|
Providers: testAccProviders,
|
|
|
|
CheckDestroy: testAccCheckSpannerInstanceDestroy,
|
|
|
|
Steps: []resource.TestStep{
|
|
|
|
{
|
|
|
|
Config: testAccSpannerInstance_basic(idName),
|
|
|
|
Check: resource.ComposeTestCheckFunc(
|
|
|
|
resource.TestCheckResourceAttrSet("google_spanner_instance.basic", "state"),
|
|
|
|
),
|
|
|
|
},
|
2018-09-17 18:15:11 +00:00
|
|
|
{
|
|
|
|
ResourceName: "google_spanner_instance.basic",
|
|
|
|
ImportState: true,
|
|
|
|
ImportStateVerify: true,
|
|
|
|
},
|
2017-08-14 16:30:41 +00:00
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAccSpannerInstance_basicWithAutogenName(t *testing.T) {
|
2017-10-12 22:07:29 +00:00
|
|
|
t.Parallel()
|
|
|
|
|
2018-09-17 18:15:11 +00:00
|
|
|
displayName := fmt.Sprintf("spanner-test-%s-dname", acctest.RandString(10))
|
2017-08-14 16:30:41 +00:00
|
|
|
resource.Test(t, resource.TestCase{
|
|
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
|
|
Providers: testAccProviders,
|
|
|
|
CheckDestroy: testAccCheckSpannerInstanceDestroy,
|
|
|
|
Steps: []resource.TestStep{
|
|
|
|
{
|
|
|
|
Config: testAccSpannerInstance_basicWithAutogenName(displayName),
|
|
|
|
Check: resource.ComposeTestCheckFunc(
|
|
|
|
resource.TestCheckResourceAttrSet("google_spanner_instance.basic", "name"),
|
|
|
|
),
|
|
|
|
},
|
|
|
|
{
|
2018-09-17 18:15:11 +00:00
|
|
|
ResourceName: "google_spanner_instance.basic",
|
|
|
|
ImportState: true,
|
|
|
|
ImportStateVerify: true,
|
2017-08-14 16:30:41 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestAccSpannerInstance_update(t *testing.T) {
|
2017-10-12 22:07:29 +00:00
|
|
|
t.Parallel()
|
|
|
|
|
2018-09-17 18:15:11 +00:00
|
|
|
dName1 := fmt.Sprintf("spanner-dname1-%s", acctest.RandString(10))
|
|
|
|
dName2 := fmt.Sprintf("spanner-dname2-%s", acctest.RandString(10))
|
2017-08-14 16:30:41 +00:00
|
|
|
resource.Test(t, resource.TestCase{
|
|
|
|
PreCheck: func() { testAccPreCheck(t) },
|
|
|
|
Providers: testAccProviders,
|
|
|
|
CheckDestroy: testAccCheckSpannerInstanceDestroy,
|
|
|
|
Steps: []resource.TestStep{
|
|
|
|
{
|
|
|
|
Config: testAccSpannerInstance_update(dName1, 1, false),
|
2018-09-17 18:15:11 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
ResourceName: "google_spanner_instance.updater",
|
|
|
|
ImportState: true,
|
|
|
|
ImportStateVerify: true,
|
2017-08-14 16:30:41 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
Config: testAccSpannerInstance_update(dName2, 2, true),
|
2018-09-17 18:15:11 +00:00
|
|
|
},
|
|
|
|
{
|
|
|
|
ResourceName: "google_spanner_instance.updater",
|
|
|
|
ImportState: true,
|
|
|
|
ImportStateVerify: true,
|
2017-08-14 16:30:41 +00:00
|
|
|
},
|
|
|
|
},
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
func testAccCheckSpannerInstanceDestroy(s *terraform.State) error {
|
|
|
|
config := testAccProvider.Meta().(*Config)
|
|
|
|
|
|
|
|
for _, rs := range s.RootModule().Resources {
|
|
|
|
if rs.Type != "google_spanner_instance" {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
if rs.Primary.ID == "" {
|
|
|
|
return fmt.Errorf("Unable to verify delete of spanner instance, ID is empty")
|
|
|
|
}
|
|
|
|
|
|
|
|
instanceName := rs.Primary.Attributes["name"]
|
|
|
|
project, err := getTestProject(rs.Primary, config)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
id := spannerInstanceId{
|
|
|
|
Project: project,
|
|
|
|
Instance: instanceName,
|
|
|
|
}
|
|
|
|
_, err = config.clientSpanner.Projects.Instances.Get(
|
|
|
|
id.instanceUri()).Do()
|
|
|
|
|
2018-09-17 18:15:11 +00:00
|
|
|
if err == nil {
|
|
|
|
return fmt.Errorf("Spanner instance still exists")
|
2017-08-14 16:30:41 +00:00
|
|
|
}
|
|
|
|
|
2018-09-17 18:15:11 +00:00
|
|
|
if gerr, ok := err.(*googleapi.Error); ok && gerr.Code == http.StatusNotFound {
|
|
|
|
return nil
|
2017-08-14 16:30:41 +00:00
|
|
|
}
|
2018-09-17 18:15:11 +00:00
|
|
|
return errwrap.Wrapf("Error verifying spanner instance deleted: {{err}}", err)
|
2017-08-14 16:30:41 +00:00
|
|
|
}
|
2018-09-17 18:15:11 +00:00
|
|
|
|
|
|
|
return nil
|
2017-08-14 16:30:41 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func testAccSpannerInstance_basic(name string) string {
|
|
|
|
return fmt.Sprintf(`
|
|
|
|
resource "google_spanner_instance" "basic" {
|
|
|
|
name = "%s"
|
|
|
|
config = "regional-us-central1"
|
|
|
|
display_name = "%s-dname"
|
|
|
|
num_nodes = 1
|
|
|
|
}
|
|
|
|
`, name, name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func testAccSpannerInstance_basicWithAutogenName(name string) string {
|
|
|
|
return fmt.Sprintf(`
|
|
|
|
resource "google_spanner_instance" "basic" {
|
|
|
|
config = "regional-us-central1"
|
|
|
|
display_name = "%s"
|
|
|
|
num_nodes = 1
|
|
|
|
}
|
|
|
|
`, name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func testAccSpannerInstance_update(name string, nodes int, addLabel bool) string {
|
|
|
|
extraLabel := ""
|
|
|
|
if addLabel {
|
|
|
|
extraLabel = "\"key2\" = \"value2\""
|
|
|
|
}
|
|
|
|
return fmt.Sprintf(`
|
|
|
|
resource "google_spanner_instance" "updater" {
|
|
|
|
config = "regional-us-central1"
|
|
|
|
display_name = "%s"
|
|
|
|
num_nodes = %d
|
|
|
|
|
|
|
|
labels {
|
|
|
|
"key1" = "value1"
|
|
|
|
%s
|
|
|
|
}
|
|
|
|
}
|
|
|
|
`, name, nodes, extraLabel)
|
|
|
|
}
|