mirror of
https://github.com/letic/terraform-provider-google.git
synced 2024-10-08 11:41:05 +00:00
d77c0adbb2
* Support encryption in Storage bucket. * Add self links to crypto keys and key ring ids * Update ID documentation to talk about self link instead.
207 lines
5.2 KiB
Go
207 lines
5.2 KiB
Go
package google
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/hashicorp/terraform/helper/schema"
|
|
"google.golang.org/api/cloudkms/v1"
|
|
)
|
|
|
|
func resourceKmsKeyRing() *schema.Resource {
|
|
return &schema.Resource{
|
|
Create: resourceKmsKeyRingCreate,
|
|
Read: resourceKmsKeyRingRead,
|
|
Delete: resourceKmsKeyRingDelete,
|
|
Importer: &schema.ResourceImporter{
|
|
State: resourceKmsKeyRingImportState,
|
|
},
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
"name": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
ForceNew: true,
|
|
},
|
|
"location": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
ForceNew: true,
|
|
},
|
|
"project": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
Computed: true,
|
|
ForceNew: true,
|
|
},
|
|
"self_link": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Computed: true,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
type kmsKeyRingId struct {
|
|
Project string
|
|
Location string
|
|
Name string
|
|
}
|
|
|
|
func (s *kmsKeyRingId) keyRingId() string {
|
|
return fmt.Sprintf("projects/%s/locations/%s/keyRings/%s", s.Project, s.Location, s.Name)
|
|
}
|
|
|
|
func (s *kmsKeyRingId) parentId() string {
|
|
return fmt.Sprintf("projects/%s/locations/%s", s.Project, s.Location)
|
|
}
|
|
|
|
func (s *kmsKeyRingId) terraformId() string {
|
|
return fmt.Sprintf("%s/%s/%s", s.Project, s.Location, s.Name)
|
|
}
|
|
|
|
func resourceKmsKeyRingCreate(d *schema.ResourceData, meta interface{}) error {
|
|
config := meta.(*Config)
|
|
|
|
project, err := getProject(d, config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
keyRingId := &kmsKeyRingId{
|
|
Project: project,
|
|
Location: d.Get("location").(string),
|
|
Name: d.Get("name").(string),
|
|
}
|
|
|
|
// This resource is often created just after a project, and requires
|
|
// billing support, which is eventually consistent. We attempt to
|
|
// wait on billing support in the project resource, but we can't
|
|
// always get it right - this retry fixes a lot of flaky tests we were
|
|
// noticing.
|
|
err = retryTimeDuration(func() error {
|
|
keyRing, err := config.clientKms.Projects.Locations.KeyRings.Create(keyRingId.parentId(), &cloudkms.KeyRing{}).KeyRingId(keyRingId.Name).Do()
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("Error creating KeyRing: %s", err)
|
|
}
|
|
|
|
log.Printf("[DEBUG] Created KeyRing %s", keyRing.Name)
|
|
|
|
d.SetId(keyRingId.keyRingId())
|
|
return nil
|
|
}, time.Duration(30*time.Second))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return resourceKmsKeyRingRead(d, meta)
|
|
}
|
|
|
|
func resourceKmsKeyRingRead(d *schema.ResourceData, meta interface{}) error {
|
|
config := meta.(*Config)
|
|
|
|
project, err := getProject(d, config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
keyRingId, err := parseKmsKeyRingId(d.Id(), config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Printf("[DEBUG] Executing read for KMS KeyRing %s", keyRingId.keyRingId())
|
|
|
|
keyRing, err := config.clientKms.Projects.Locations.KeyRings.Get(keyRingId.keyRingId()).Do()
|
|
|
|
if err != nil {
|
|
return fmt.Errorf("Error reading KeyRing: %s", err)
|
|
}
|
|
|
|
d.Set("project", project)
|
|
d.Set("self_link", keyRing.Name)
|
|
|
|
return nil
|
|
}
|
|
|
|
/*
|
|
Because KMS KeyRing resources cannot be deleted on GCP, we are only going to remove it from state.
|
|
Re-creation of this resource through Terraform will produce an error.
|
|
*/
|
|
|
|
func resourceKmsKeyRingDelete(d *schema.ResourceData, meta interface{}) error {
|
|
config := meta.(*Config)
|
|
|
|
keyRingId, err := parseKmsKeyRingId(d.Id(), config)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Printf("[WARNING] KMS KeyRing resources cannot be deleted from GCP. This KeyRing %s will be removed from Terraform state, but will still be present on the server.", keyRingId.keyRingId())
|
|
|
|
d.SetId("")
|
|
|
|
return nil
|
|
}
|
|
|
|
func parseKmsKeyRingId(id string, config *Config) (*kmsKeyRingId, error) {
|
|
parts := strings.Split(id, "/")
|
|
|
|
keyRingIdRegex := regexp.MustCompile("^(" + ProjectRegex + ")/([a-z0-9-])+/([a-zA-Z0-9_-]{1,63})$")
|
|
keyRingIdWithoutProjectRegex := regexp.MustCompile("^([a-z0-9-])+/([a-zA-Z0-9_-]{1,63})$")
|
|
keyRingRelativeLinkRegex := regexp.MustCompile("^projects/(" + ProjectRegex + ")/locations/([a-z0-9-]+)/keyRings/([a-zA-Z0-9_-]{1,63})$")
|
|
|
|
if keyRingIdRegex.MatchString(id) {
|
|
return &kmsKeyRingId{
|
|
Project: parts[0],
|
|
Location: parts[1],
|
|
Name: parts[2],
|
|
}, nil
|
|
}
|
|
|
|
if keyRingIdWithoutProjectRegex.MatchString(id) {
|
|
if config.Project == "" {
|
|
return nil, fmt.Errorf("The default project for the provider must be set when using the `{location}/{keyRingName}` id format.")
|
|
}
|
|
|
|
return &kmsKeyRingId{
|
|
Project: config.Project,
|
|
Location: parts[0],
|
|
Name: parts[1],
|
|
}, nil
|
|
}
|
|
|
|
if parts := keyRingRelativeLinkRegex.FindStringSubmatch(id); parts != nil {
|
|
return &kmsKeyRingId{
|
|
Project: parts[1],
|
|
Location: parts[2],
|
|
Name: parts[3],
|
|
}, nil
|
|
}
|
|
return nil, fmt.Errorf("Invalid KeyRing id format, expecting `{projectId}/{locationId}/{keyRingName}` or `{locationId}/{keyRingName}.`")
|
|
}
|
|
|
|
func resourceKmsKeyRingImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {
|
|
config := meta.(*Config)
|
|
|
|
keyRingId, err := parseKmsKeyRingId(d.Id(), config)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
d.Set("name", keyRingId.Name)
|
|
d.Set("location", keyRingId.Location)
|
|
|
|
if config.Project != keyRingId.Project {
|
|
d.Set("project", keyRingId.Project)
|
|
}
|
|
|
|
d.SetId(keyRingId.keyRingId())
|
|
|
|
return []*schema.ResourceData{d}, nil
|
|
}
|