package google import ( "fmt" "log" "github.com/hashicorp/terraform/helper/schema" "google.golang.org/api/compute/v1" "regexp" "strings" ) var ( computeAddressIdTemplate = "projects/%s/regions/%s/addresses/%s" computeAddressLinkRegex = regexp.MustCompile("projects/(.+)/regions/(.+)/addresses/(.+)$") ) func resourceComputeAddress() *schema.Resource { return &schema.Resource{ Create: resourceComputeAddressCreate, Read: resourceComputeAddressRead, Delete: resourceComputeAddressDelete, Importer: &schema.ResourceImporter{ State: resourceComputeAddressImportState, }, SchemaVersion: 1, MigrateState: resourceComputeAddressMigrateState, Schema: map[string]*schema.Schema{ "name": &schema.Schema{ Type: schema.TypeString, Required: true, ForceNew: true, }, "address": &schema.Schema{ Type: schema.TypeString, Computed: true, }, "project": &schema.Schema{ Type: schema.TypeString, Optional: true, ForceNew: true, }, "region": &schema.Schema{ Type: schema.TypeString, Optional: true, Computed: true, ForceNew: true, }, "self_link": &schema.Schema{ Type: schema.TypeString, Computed: true, }, }, } } func resourceComputeAddressCreate(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) region, err := getRegion(d, config) if err != nil { return err } project, err := getProject(d, config) if err != nil { return err } // Build the address parameter addr := &compute.Address{Name: d.Get("name").(string)} op, err := config.clientCompute.Addresses.Insert( project, region, addr).Do() if err != nil { return fmt.Errorf("Error creating address: %s", err) } // It probably maybe worked, so store the ID now d.SetId(computeAddressId{ Project: project, Region: region, Name: addr.Name, }.canonicalId()) err = computeOperationWait(config, op, project, "Creating Address") if err != nil { return err } return resourceComputeAddressRead(d, meta) } func resourceComputeAddressRead(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) addressId, err := parseComputeAddressId(d.Id(), config) if err != nil { return err } addr, err := config.clientCompute.Addresses.Get( addressId.Project, addressId.Region, addressId.Name).Do() if err != nil { return handleNotFoundError(err, d, fmt.Sprintf("Address %q", d.Get("name").(string))) } d.Set("address", addr.Address) d.Set("self_link", addr.SelfLink) d.Set("name", addr.Name) d.Set("region", GetResourceNameFromSelfLink(addr.Region)) return nil } func resourceComputeAddressDelete(d *schema.ResourceData, meta interface{}) error { config := meta.(*Config) addressId, err := parseComputeAddressId(d.Id(), config) if err != nil { return err } // Delete the address log.Printf("[DEBUG] address delete request") op, err := config.clientCompute.Addresses.Delete( addressId.Project, addressId.Region, addressId.Name).Do() if err != nil { return fmt.Errorf("Error deleting address: %s", err) } err = computeOperationWait(config, op, addressId.Project, "Deleting Address") if err != nil { return err } d.SetId("") return nil } func resourceComputeAddressImportState(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { config := meta.(*Config) addressId, err := parseComputeAddressId(d.Id(), config) if err != nil { return nil, err } d.SetId(addressId.canonicalId()) return []*schema.ResourceData{d}, nil } type computeAddressId struct { Project string Region string Name string } func (s computeAddressId) canonicalId() string { return fmt.Sprintf(computeAddressIdTemplate, s.Project, s.Region, s.Name) } func parseComputeAddressId(id string, config *Config) (*computeAddressId, error) { var parts []string if computeAddressLinkRegex.MatchString(id) { parts = computeAddressLinkRegex.FindStringSubmatch(id) return &computeAddressId{ Project: parts[1], Region: parts[2], Name: parts[3], }, nil } else { parts = strings.Split(id, "/") } if len(parts) == 3 { return &computeAddressId{ Project: parts[0], Region: parts[1], Name: parts[2], }, nil } else if len(parts) == 2 { // Project is optional. if config.Project == "" { return nil, fmt.Errorf("The default project for the provider must be set when using the `{region}/{name}` id format.") } return &computeAddressId{ Project: config.Project, Region: parts[0], Name: parts[1], }, nil } else if len(parts) == 1 { // Project and region is optional if config.Project == "" { return nil, fmt.Errorf("The default project for the provider must be set when using the `{name}` id format.") } if config.Region == "" { return nil, fmt.Errorf("The default region for the provider must be set when using the `{name}` id format.") } return &computeAddressId{ Project: config.Project, Region: config.Region, Name: parts[0], }, nil } return nil, fmt.Errorf("Invalid compute address id. Expecting resource link, `{project}/{region}/{name}`, `{region}/{name}` or `{name}` format.") }