mirror of
https://github.com/opentffoundation/opentf.git
synced 2026-03-27 11:00:18 -04:00
* provider/openstack: Detect Region for Importing Resources This commit changes the way the OpenStack region is detected and set. Any time a region is required, the region attribute will first be checked. Next, the OS_REGION_NAME environment variable will be checked. While schema.EnvDefaultFunc handles this same situation, it is not applicable when importing resources. * provider/openstack: No longer ignore region in importing tests * provider/openstack: Network and Subnet Import Fixes This commit fixes the OpenStack Network and Subnet resources so that importing of those resources is successful.
253 lines
6.8 KiB
Go
253 lines
6.8 KiB
Go
package openstack
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"time"
|
|
|
|
"github.com/hashicorp/terraform/helper/resource"
|
|
"github.com/hashicorp/terraform/helper/schema"
|
|
|
|
"github.com/gophercloud/gophercloud"
|
|
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/layer3/routers"
|
|
)
|
|
|
|
func resourceNetworkingRouterV2() *schema.Resource {
|
|
return &schema.Resource{
|
|
Create: resourceNetworkingRouterV2Create,
|
|
Read: resourceNetworkingRouterV2Read,
|
|
Update: resourceNetworkingRouterV2Update,
|
|
Delete: resourceNetworkingRouterV2Delete,
|
|
|
|
Schema: map[string]*schema.Schema{
|
|
"region": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Required: true,
|
|
ForceNew: true,
|
|
DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""),
|
|
},
|
|
"name": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: false,
|
|
},
|
|
"admin_state_up": &schema.Schema{
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
ForceNew: false,
|
|
Computed: true,
|
|
},
|
|
"distributed": &schema.Schema{
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
Computed: true,
|
|
},
|
|
"external_gateway": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: false,
|
|
},
|
|
"tenant_id": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
Computed: true,
|
|
},
|
|
"value_specs": &schema.Schema{
|
|
Type: schema.TypeMap,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func resourceNetworkingRouterV2Create(d *schema.ResourceData, meta interface{}) error {
|
|
config := meta.(*Config)
|
|
networkingClient, err := config.networkingV2Client(GetRegion(d))
|
|
if err != nil {
|
|
return fmt.Errorf("Error creating OpenStack networking client: %s", err)
|
|
}
|
|
|
|
createOpts := RouterCreateOpts{
|
|
routers.CreateOpts{
|
|
Name: d.Get("name").(string),
|
|
TenantID: d.Get("tenant_id").(string),
|
|
},
|
|
MapValueSpecs(d),
|
|
}
|
|
|
|
if asuRaw, ok := d.GetOk("admin_state_up"); ok {
|
|
asu := asuRaw.(bool)
|
|
createOpts.AdminStateUp = &asu
|
|
}
|
|
|
|
if dRaw, ok := d.GetOk("distributed"); ok {
|
|
d := dRaw.(bool)
|
|
createOpts.Distributed = &d
|
|
}
|
|
|
|
externalGateway := d.Get("external_gateway").(string)
|
|
if externalGateway != "" {
|
|
gatewayInfo := routers.GatewayInfo{
|
|
NetworkID: externalGateway,
|
|
}
|
|
createOpts.GatewayInfo = &gatewayInfo
|
|
}
|
|
|
|
log.Printf("[DEBUG] Create Options: %#v", createOpts)
|
|
n, err := routers.Create(networkingClient, createOpts).Extract()
|
|
if err != nil {
|
|
return fmt.Errorf("Error creating OpenStack Neutron router: %s", err)
|
|
}
|
|
log.Printf("[INFO] Router ID: %s", n.ID)
|
|
|
|
log.Printf("[DEBUG] Waiting for OpenStack Neutron Router (%s) to become available", n.ID)
|
|
stateConf := &resource.StateChangeConf{
|
|
Pending: []string{"BUILD", "PENDING_CREATE", "PENDING_UPDATE"},
|
|
Target: []string{"ACTIVE"},
|
|
Refresh: waitForRouterActive(networkingClient, n.ID),
|
|
Timeout: 10 * time.Minute,
|
|
Delay: 5 * time.Second,
|
|
MinTimeout: 3 * time.Second,
|
|
}
|
|
|
|
_, err = stateConf.WaitForState()
|
|
|
|
d.SetId(n.ID)
|
|
|
|
return resourceNetworkingRouterV2Read(d, meta)
|
|
}
|
|
|
|
func resourceNetworkingRouterV2Read(d *schema.ResourceData, meta interface{}) error {
|
|
config := meta.(*Config)
|
|
networkingClient, err := config.networkingV2Client(GetRegion(d))
|
|
if err != nil {
|
|
return fmt.Errorf("Error creating OpenStack networking client: %s", err)
|
|
}
|
|
|
|
n, err := routers.Get(networkingClient, d.Id()).Extract()
|
|
if err != nil {
|
|
if _, ok := err.(gophercloud.ErrDefault404); ok {
|
|
d.SetId("")
|
|
return nil
|
|
}
|
|
|
|
return fmt.Errorf("Error retrieving OpenStack Neutron Router: %s", err)
|
|
}
|
|
|
|
log.Printf("[DEBUG] Retrieved Router %s: %+v", d.Id(), n)
|
|
|
|
d.Set("name", n.Name)
|
|
d.Set("admin_state_up", n.AdminStateUp)
|
|
d.Set("distributed", n.Distributed)
|
|
d.Set("tenant_id", n.TenantID)
|
|
d.Set("external_gateway", n.GatewayInfo.NetworkID)
|
|
|
|
return nil
|
|
}
|
|
|
|
func resourceNetworkingRouterV2Update(d *schema.ResourceData, meta interface{}) error {
|
|
routerId := d.Id()
|
|
osMutexKV.Lock(routerId)
|
|
defer osMutexKV.Unlock(routerId)
|
|
|
|
config := meta.(*Config)
|
|
networkingClient, err := config.networkingV2Client(GetRegion(d))
|
|
if err != nil {
|
|
return fmt.Errorf("Error creating OpenStack networking client: %s", err)
|
|
}
|
|
|
|
var updateOpts routers.UpdateOpts
|
|
if d.HasChange("name") {
|
|
updateOpts.Name = d.Get("name").(string)
|
|
}
|
|
if d.HasChange("admin_state_up") {
|
|
asu := d.Get("admin_state_up").(bool)
|
|
updateOpts.AdminStateUp = &asu
|
|
}
|
|
if d.HasChange("external_gateway") {
|
|
externalGateway := d.Get("external_gateway").(string)
|
|
if externalGateway != "" {
|
|
gatewayInfo := routers.GatewayInfo{
|
|
NetworkID: externalGateway,
|
|
}
|
|
updateOpts.GatewayInfo = &gatewayInfo
|
|
}
|
|
}
|
|
|
|
log.Printf("[DEBUG] Updating Router %s with options: %+v", d.Id(), updateOpts)
|
|
|
|
_, err = routers.Update(networkingClient, d.Id(), updateOpts).Extract()
|
|
if err != nil {
|
|
return fmt.Errorf("Error updating OpenStack Neutron Router: %s", err)
|
|
}
|
|
|
|
return resourceNetworkingRouterV2Read(d, meta)
|
|
}
|
|
|
|
func resourceNetworkingRouterV2Delete(d *schema.ResourceData, meta interface{}) error {
|
|
config := meta.(*Config)
|
|
networkingClient, err := config.networkingV2Client(GetRegion(d))
|
|
if err != nil {
|
|
return fmt.Errorf("Error creating OpenStack networking client: %s", err)
|
|
}
|
|
|
|
stateConf := &resource.StateChangeConf{
|
|
Pending: []string{"ACTIVE"},
|
|
Target: []string{"DELETED"},
|
|
Refresh: waitForRouterDelete(networkingClient, d.Id()),
|
|
Timeout: 10 * time.Minute,
|
|
Delay: 5 * time.Second,
|
|
MinTimeout: 3 * time.Second,
|
|
}
|
|
|
|
_, err = stateConf.WaitForState()
|
|
if err != nil {
|
|
return fmt.Errorf("Error deleting OpenStack Neutron Router: %s", err)
|
|
}
|
|
|
|
d.SetId("")
|
|
return nil
|
|
}
|
|
|
|
func waitForRouterActive(networkingClient *gophercloud.ServiceClient, routerId string) resource.StateRefreshFunc {
|
|
return func() (interface{}, string, error) {
|
|
r, err := routers.Get(networkingClient, routerId).Extract()
|
|
if err != nil {
|
|
return nil, r.Status, err
|
|
}
|
|
|
|
log.Printf("[DEBUG] OpenStack Neutron Router: %+v", r)
|
|
return r, r.Status, nil
|
|
}
|
|
}
|
|
|
|
func waitForRouterDelete(networkingClient *gophercloud.ServiceClient, routerId string) resource.StateRefreshFunc {
|
|
return func() (interface{}, string, error) {
|
|
log.Printf("[DEBUG] Attempting to delete OpenStack Router %s.\n", routerId)
|
|
|
|
r, err := routers.Get(networkingClient, routerId).Extract()
|
|
if err != nil {
|
|
if _, ok := err.(gophercloud.ErrDefault404); ok {
|
|
log.Printf("[DEBUG] Successfully deleted OpenStack Router %s", routerId)
|
|
return r, "DELETED", nil
|
|
}
|
|
return r, "ACTIVE", err
|
|
}
|
|
|
|
err = routers.Delete(networkingClient, routerId).ExtractErr()
|
|
if err != nil {
|
|
if _, ok := err.(gophercloud.ErrDefault404); ok {
|
|
log.Printf("[DEBUG] Successfully deleted OpenStack Router %s", routerId)
|
|
return r, "DELETED", nil
|
|
}
|
|
return r, "ACTIVE", err
|
|
}
|
|
|
|
log.Printf("[DEBUG] OpenStack Router %s still active.\n", routerId)
|
|
return r, "ACTIVE", nil
|
|
}
|
|
}
|