Skip to content

Commit

Permalink
Merge pull request #197 from modular-magician/codegen-pr-995
Browse files Browse the repository at this point in the history
Fix spanner database iam binding import
  • Loading branch information
emilymye authored and nat-henderson committed Dec 12, 2018
1 parent f98e189 commit 525f3c8
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 83 deletions.
15 changes: 3 additions & 12 deletions google-beta/iam_spanner_database.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/helper/schema"
"google.golang.org/api/cloudresourcemanager/v1"
spanner "google.golang.org/api/spanner/v1"
"google.golang.org/api/spanner/v1"
)

var IamSpannerDatabaseSchema = map[string]*schema.Schema{
Expand Down Expand Up @@ -51,17 +51,8 @@ func NewSpannerDatabaseIamUpdater(d *schema.ResourceData, config *Config) (Resou
}

func SpannerDatabaseIdParseFunc(d *schema.ResourceData, config *Config) error {
id, err := extractSpannerDatabaseId(d.Id())
if err != nil {
return err
}
d.Set("instance", id.Instance)
d.Set("project", id.Project)
d.Set("database", id.Database)

// Explicitly set the id so imported resources have the same ID format as non-imported ones.
d.SetId(id.terraformId())
return nil
_, err := resourceSpannerDatabaseImport("database")(d, config)
return err
}

func (u *SpannerDatabaseIamUpdater) GetResourceIamPolicy() (*cloudresourcemanager.Policy, error) {
Expand Down
112 changes: 41 additions & 71 deletions google-beta/resource_spanner_database.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,40 @@ package google

import (
"fmt"
"github.com/hashicorp/terraform/helper/schema"
"log"
"net/http"
"regexp"
"strings"

"github.com/hashicorp/terraform/helper/schema"

"google.golang.org/api/googleapi"
"google.golang.org/api/spanner/v1"
)

const (
spannerDatabaseNameFormat = "^[a-z][a-z0-9_-]*[a-z0-9]$"
)

func resourceSpannerDatabase() *schema.Resource {
return &schema.Resource{
Create: resourceSpannerDatabaseCreate,
Read: resourceSpannerDatabaseRead,
Delete: resourceSpannerDatabaseDelete,
Importer: &schema.ResourceImporter{
State: resourceSpannerDatabaseImportState,
State: resourceSpannerDatabaseImport("name"),
},

Schema: map[string]*schema.Schema{

"instance": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
},

"name": &schema.Schema{
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: func(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)

if len(value) < 2 && len(value) > 30 {
errors = append(errors, fmt.Errorf(
"%q must be between 2 and 30 characters in length", k))
}
if !regexp.MustCompile("^[a-z0-9-]+$").MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q can only contain lowercase letters, numbers and hyphens", k))
}
if !regexp.MustCompile("^[a-z]").MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q must start with a letter", k))
}
if !regexp.MustCompile("[a-z0-9]$").MatchString(value) {
errors = append(errors, fmt.Errorf(
"%q must end with a number or a letter", k))
}
return
},
Type: schema.TypeString,
Required: true,
ForceNew: true,
ValidateFunc: validateResourceSpannerDatabaseName,
},

"project": {
Expand Down Expand Up @@ -154,36 +135,41 @@ func resourceSpannerDatabaseDelete(d *schema.ResourceData, meta interface{}) err
return nil
}

func resourceSpannerDatabaseImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(*Config)
id, err := importSpannerDatabaseId(d.Id())
if err != nil {
return nil, err
}
func resourceSpannerDatabaseImport(databaseField string) schema.StateFunc {
return func(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
config := meta.(*Config)
err := parseImportId([]string{
fmt.Sprintf("projects/(?P<project>[^/]+)/instances/(?P<instance>[^/]+)/databases/(?P<%s>[^/]+)", databaseField),
fmt.Sprintf("instances/(?P<instance>[^/]+)/databases/(?P<%s>[^/]+)", databaseField),
fmt.Sprintf("(?P<project>[^/]+)/(?P<instance>[^/]+)/(?P<%s>[^/]+)", databaseField),
fmt.Sprintf("(?P<instance>[^/]+)/(?P<%s>[^/]+)", databaseField),
}, d, config)
if err != nil {
return nil, fmt.Errorf("Error constructing id: %s", err)
}

if id.Project != "" {
d.Set("project", id.Project)
} else {
project, err := getProject(d, config)
id, err := buildSpannerDatabaseId(d, config)
if err != nil {
return nil, err
return nil, fmt.Errorf("Error constructing id: %s", err)
}
id.Project = project
}

d.Set("instance", id.Instance)
d.Set("name", id.Database)
d.SetId(id.terraformId())
d.SetId(id.terraformId())

return []*schema.ResourceData{d}, nil
return []*schema.ResourceData{d}, nil
}
}

func buildSpannerDatabaseId(d *schema.ResourceData, config *Config) (*spannerDatabaseId, error) {
project, err := getProject(d, config)
if err != nil {
return nil, err
}
dbName := d.Get("name").(string)
database, ok := d.GetOk("name")
if !ok {
database = d.Get("database")
}

dbName := database.(string)
instanceName := d.Get("instance").(string)

return &spannerDatabaseId{
Expand Down Expand Up @@ -215,32 +201,16 @@ func (s spannerDatabaseId) databaseUri() string {
return fmt.Sprintf("%s/databases/%s", s.parentInstanceUri(), s.Database)
}

func importSpannerDatabaseId(id string) (*spannerDatabaseId, error) {
if !regexp.MustCompile("^[a-z0-9-]+/[a-z0-9-]+$").Match([]byte(id)) &&
!regexp.MustCompile("^"+ProjectRegex+"/[a-z0-9-]+/[a-z0-9-]+$").Match([]byte(id)) {
return nil, fmt.Errorf("Invalid spanner database specifier. " +
"Expecting either {projectId}/{instanceId}/{dbId} OR " +
"{instanceId}/{dbId} (where project will be derived from the provider)")
}
func validateResourceSpannerDatabaseName(v interface{}, k string) (ws []string, errors []error) {
value := v.(string)

parts := strings.Split(id, "/")
if len(parts) == 2 {
log.Printf("[INFO] Spanner database import format of {instanceId}/{dbId} specified: %s", id)
return &spannerDatabaseId{Instance: parts[0], Database: parts[1]}, nil
if len(value) < 2 && len(value) > 30 {
errors = append(errors, fmt.Errorf(
"%q must be between 2 and 30 characters in length", k))
}

log.Printf("[INFO] Spanner database import format of {projectId}/{instanceId}/{dbId} specified: %s", id)
return extractSpannerDatabaseId(id)
}

func extractSpannerDatabaseId(id string) (*spannerDatabaseId, error) {
if !regexp.MustCompile("^" + ProjectRegex + "/[a-z0-9-]+/[a-z0-9-]+$").Match([]byte(id)) {
return nil, fmt.Errorf("Invalid spanner id format, expecting {projectId}/{instanceId}/{databaseId}")
if !regexp.MustCompile(spannerDatabaseNameFormat).MatchString(value) {
errors = append(errors, fmt.Errorf("database name %q must match regexp %q", value, spannerDatabaseNameFormat))
}
parts := strings.Split(id, "/")
return &spannerDatabaseId{
Project: parts[0],
Instance: parts[1],
Database: parts[2],
}, nil
return
}

0 comments on commit 525f3c8

Please sign in to comment.