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.
228 lines
5.6 KiB
Go
228 lines
5.6 KiB
Go
package openstack
|
|
|
|
import (
|
|
"fmt"
|
|
"log"
|
|
"time"
|
|
|
|
"github.com/gophercloud/gophercloud"
|
|
"github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/policies"
|
|
"github.com/hashicorp/terraform/helper/resource"
|
|
"github.com/hashicorp/terraform/helper/schema"
|
|
)
|
|
|
|
func resourceFWPolicyV1() *schema.Resource {
|
|
return &schema.Resource{
|
|
Create: resourceFWPolicyV1Create,
|
|
Read: resourceFWPolicyV1Read,
|
|
Update: resourceFWPolicyV1Update,
|
|
Delete: resourceFWPolicyV1Delete,
|
|
Importer: &schema.ResourceImporter{
|
|
State: schema.ImportStatePassthrough,
|
|
},
|
|
|
|
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,
|
|
},
|
|
"description": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
},
|
|
"audited": &schema.Schema{
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
Default: false,
|
|
},
|
|
"shared": &schema.Schema{
|
|
Type: schema.TypeBool,
|
|
Optional: true,
|
|
},
|
|
"tenant_id": &schema.Schema{
|
|
Type: schema.TypeString,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
Computed: true,
|
|
},
|
|
"rules": &schema.Schema{
|
|
Type: schema.TypeList,
|
|
Optional: true,
|
|
Elem: &schema.Schema{Type: schema.TypeString},
|
|
},
|
|
"value_specs": &schema.Schema{
|
|
Type: schema.TypeMap,
|
|
Optional: true,
|
|
ForceNew: true,
|
|
},
|
|
},
|
|
}
|
|
}
|
|
|
|
func resourceFWPolicyV1Create(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)
|
|
}
|
|
|
|
v := d.Get("rules").([]interface{})
|
|
|
|
log.Printf("[DEBUG] Rules found : %#v", v)
|
|
log.Printf("[DEBUG] Rules count : %d", len(v))
|
|
|
|
rules := make([]string, len(v))
|
|
for i, v := range v {
|
|
rules[i] = v.(string)
|
|
}
|
|
|
|
audited := d.Get("audited").(bool)
|
|
|
|
opts := PolicyCreateOpts{
|
|
policies.CreateOpts{
|
|
Name: d.Get("name").(string),
|
|
Description: d.Get("description").(string),
|
|
Audited: &audited,
|
|
TenantID: d.Get("tenant_id").(string),
|
|
Rules: rules,
|
|
},
|
|
MapValueSpecs(d),
|
|
}
|
|
|
|
if r, ok := d.GetOk("shared"); ok {
|
|
shared := r.(bool)
|
|
opts.Shared = &shared
|
|
}
|
|
|
|
log.Printf("[DEBUG] Create firewall policy: %#v", opts)
|
|
|
|
policy, err := policies.Create(networkingClient, opts).Extract()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
log.Printf("[DEBUG] Firewall policy created: %#v", policy)
|
|
|
|
d.SetId(policy.ID)
|
|
|
|
return resourceFWPolicyV1Read(d, meta)
|
|
}
|
|
|
|
func resourceFWPolicyV1Read(d *schema.ResourceData, meta interface{}) error {
|
|
log.Printf("[DEBUG] Retrieve information about firewall policy: %s", d.Id())
|
|
|
|
config := meta.(*Config)
|
|
networkingClient, err := config.networkingV2Client(GetRegion(d))
|
|
if err != nil {
|
|
return fmt.Errorf("Error creating OpenStack networking client: %s", err)
|
|
}
|
|
|
|
policy, err := policies.Get(networkingClient, d.Id()).Extract()
|
|
if err != nil {
|
|
return CheckDeleted(d, err, "FW policy")
|
|
}
|
|
|
|
log.Printf("[DEBUG] Read OpenStack Firewall Policy %s: %#v", d.Id(), policy)
|
|
|
|
d.Set("name", policy.Name)
|
|
d.Set("description", policy.Description)
|
|
d.Set("shared", policy.Shared)
|
|
d.Set("audited", policy.Audited)
|
|
d.Set("tenant_id", policy.TenantID)
|
|
d.Set("rules", policy.Rules)
|
|
d.Set("region", GetRegion(d))
|
|
|
|
return nil
|
|
}
|
|
|
|
func resourceFWPolicyV1Update(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)
|
|
}
|
|
|
|
opts := policies.UpdateOpts{}
|
|
|
|
if d.HasChange("name") {
|
|
opts.Name = d.Get("name").(string)
|
|
}
|
|
|
|
if d.HasChange("description") {
|
|
opts.Description = d.Get("description").(string)
|
|
}
|
|
|
|
if d.HasChange("rules") {
|
|
v := d.Get("rules").([]interface{})
|
|
|
|
log.Printf("[DEBUG] Rules found : %#v", v)
|
|
log.Printf("[DEBUG] Rules count : %d", len(v))
|
|
|
|
rules := make([]string, len(v))
|
|
for i, v := range v {
|
|
rules[i] = v.(string)
|
|
}
|
|
opts.Rules = rules
|
|
}
|
|
|
|
log.Printf("[DEBUG] Updating firewall policy with id %s: %#v", d.Id(), opts)
|
|
|
|
err = policies.Update(networkingClient, d.Id(), opts).Err
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
return resourceFWPolicyV1Read(d, meta)
|
|
}
|
|
|
|
func resourceFWPolicyV1Delete(d *schema.ResourceData, meta interface{}) error {
|
|
log.Printf("[DEBUG] Destroy firewall policy: %s", d.Id())
|
|
|
|
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: waitForFirewallPolicyDeletion(networkingClient, d.Id()),
|
|
Timeout: 120 * time.Second,
|
|
Delay: 0,
|
|
MinTimeout: 2 * time.Second,
|
|
}
|
|
|
|
if _, err = stateConf.WaitForState(); err != nil {
|
|
return err
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func waitForFirewallPolicyDeletion(networkingClient *gophercloud.ServiceClient, id string) resource.StateRefreshFunc {
|
|
return func() (interface{}, string, error) {
|
|
err := policies.Delete(networkingClient, id).Err
|
|
if err == nil {
|
|
return "", "DELETED", nil
|
|
}
|
|
|
|
if errCode, ok := err.(gophercloud.ErrUnexpectedResponseCode); ok {
|
|
if errCode.Actual == 409 {
|
|
// This error usually means that the policy is attached
|
|
// to a firewall. At this point, the firewall is probably
|
|
// being delete. So, we retry a few times.
|
|
return nil, "ACTIVE", nil
|
|
}
|
|
}
|
|
|
|
return nil, "ACTIVE", err
|
|
}
|
|
}
|