github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/openstack/resource_openstack_fw_firewall_v1.go (about) 1 package openstack 2 3 import ( 4 "fmt" 5 "log" 6 "time" 7 8 "github.com/gophercloud/gophercloud" 9 "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/fwaas/firewalls" 10 "github.com/hashicorp/terraform/helper/resource" 11 "github.com/hashicorp/terraform/helper/schema" 12 ) 13 14 func resourceFWFirewallV1() *schema.Resource { 15 return &schema.Resource{ 16 Create: resourceFWFirewallV1Create, 17 Read: resourceFWFirewallV1Read, 18 Update: resourceFWFirewallV1Update, 19 Delete: resourceFWFirewallV1Delete, 20 Importer: &schema.ResourceImporter{ 21 State: schema.ImportStatePassthrough, 22 }, 23 24 Timeouts: &schema.ResourceTimeout{ 25 Create: schema.DefaultTimeout(10 * time.Minute), 26 Update: schema.DefaultTimeout(10 * time.Minute), 27 Delete: schema.DefaultTimeout(10 * time.Minute), 28 }, 29 30 Schema: map[string]*schema.Schema{ 31 "region": &schema.Schema{ 32 Type: schema.TypeString, 33 Required: true, 34 ForceNew: true, 35 DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""), 36 }, 37 "name": &schema.Schema{ 38 Type: schema.TypeString, 39 Optional: true, 40 }, 41 "description": &schema.Schema{ 42 Type: schema.TypeString, 43 Optional: true, 44 }, 45 "policy_id": &schema.Schema{ 46 Type: schema.TypeString, 47 Required: true, 48 }, 49 "admin_state_up": &schema.Schema{ 50 Type: schema.TypeBool, 51 Optional: true, 52 Default: true, 53 }, 54 "tenant_id": &schema.Schema{ 55 Type: schema.TypeString, 56 Optional: true, 57 ForceNew: true, 58 Computed: true, 59 }, 60 "value_specs": &schema.Schema{ 61 Type: schema.TypeMap, 62 Optional: true, 63 ForceNew: true, 64 }, 65 }, 66 } 67 } 68 69 func resourceFWFirewallV1Create(d *schema.ResourceData, meta interface{}) error { 70 71 config := meta.(*Config) 72 networkingClient, err := config.networkingV2Client(GetRegion(d)) 73 if err != nil { 74 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 75 } 76 77 adminStateUp := d.Get("admin_state_up").(bool) 78 79 firewallConfiguration := FirewallCreateOpts{ 80 firewalls.CreateOpts{ 81 Name: d.Get("name").(string), 82 Description: d.Get("description").(string), 83 PolicyID: d.Get("policy_id").(string), 84 AdminStateUp: &adminStateUp, 85 TenantID: d.Get("tenant_id").(string), 86 }, 87 MapValueSpecs(d), 88 } 89 90 log.Printf("[DEBUG] Create firewall: %#v", firewallConfiguration) 91 92 firewall, err := firewalls.Create(networkingClient, firewallConfiguration).Extract() 93 if err != nil { 94 return err 95 } 96 97 log.Printf("[DEBUG] Firewall created: %#v", firewall) 98 99 stateConf := &resource.StateChangeConf{ 100 Pending: []string{"PENDING_CREATE"}, 101 Target: []string{"ACTIVE"}, 102 Refresh: waitForFirewallActive(networkingClient, firewall.ID), 103 Timeout: d.Timeout(schema.TimeoutCreate), 104 Delay: 0, 105 MinTimeout: 2 * time.Second, 106 } 107 108 _, err = stateConf.WaitForState() 109 110 d.SetId(firewall.ID) 111 112 return resourceFWFirewallV1Read(d, meta) 113 } 114 115 func resourceFWFirewallV1Read(d *schema.ResourceData, meta interface{}) error { 116 log.Printf("[DEBUG] Retrieve information about firewall: %s", d.Id()) 117 118 config := meta.(*Config) 119 networkingClient, err := config.networkingV2Client(GetRegion(d)) 120 if err != nil { 121 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 122 } 123 124 firewall, err := firewalls.Get(networkingClient, d.Id()).Extract() 125 if err != nil { 126 return CheckDeleted(d, err, "firewall") 127 } 128 129 log.Printf("[DEBUG] Read OpenStack Firewall %s: %#v", d.Id(), firewall) 130 131 d.Set("name", firewall.Name) 132 d.Set("description", firewall.Description) 133 d.Set("policy_id", firewall.PolicyID) 134 d.Set("admin_state_up", firewall.AdminStateUp) 135 d.Set("tenant_id", firewall.TenantID) 136 d.Set("region", GetRegion(d)) 137 138 return nil 139 } 140 141 func resourceFWFirewallV1Update(d *schema.ResourceData, meta interface{}) error { 142 143 config := meta.(*Config) 144 networkingClient, err := config.networkingV2Client(GetRegion(d)) 145 if err != nil { 146 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 147 } 148 149 opts := firewalls.UpdateOpts{} 150 151 if d.HasChange("name") { 152 opts.Name = d.Get("name").(string) 153 } 154 155 if d.HasChange("description") { 156 opts.Description = d.Get("description").(string) 157 } 158 159 if d.HasChange("policy_id") { 160 opts.PolicyID = d.Get("policy_id").(string) 161 } 162 163 if d.HasChange("admin_state_up") { 164 adminStateUp := d.Get("admin_state_up").(bool) 165 opts.AdminStateUp = &adminStateUp 166 } 167 168 log.Printf("[DEBUG] Updating firewall with id %s: %#v", d.Id(), opts) 169 170 stateConf := &resource.StateChangeConf{ 171 Pending: []string{"PENDING_CREATE", "PENDING_UPDATE"}, 172 Target: []string{"ACTIVE"}, 173 Refresh: waitForFirewallActive(networkingClient, d.Id()), 174 Timeout: d.Timeout(schema.TimeoutUpdate), 175 Delay: 0, 176 MinTimeout: 2 * time.Second, 177 } 178 179 _, err = stateConf.WaitForState() 180 181 err = firewalls.Update(networkingClient, d.Id(), opts).Err 182 if err != nil { 183 return err 184 } 185 186 return resourceFWFirewallV1Read(d, meta) 187 } 188 189 func resourceFWFirewallV1Delete(d *schema.ResourceData, meta interface{}) error { 190 log.Printf("[DEBUG] Destroy firewall: %s", d.Id()) 191 192 config := meta.(*Config) 193 networkingClient, err := config.networkingV2Client(GetRegion(d)) 194 if err != nil { 195 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 196 } 197 198 // Ensure the firewall was fully created/updated before being deleted. 199 stateConf := &resource.StateChangeConf{ 200 Pending: []string{"PENDING_CREATE", "PENDING_UPDATE"}, 201 Target: []string{"ACTIVE"}, 202 Refresh: waitForFirewallActive(networkingClient, d.Id()), 203 Timeout: d.Timeout(schema.TimeoutUpdate), 204 Delay: 0, 205 MinTimeout: 2 * time.Second, 206 } 207 208 _, err = stateConf.WaitForState() 209 210 err = firewalls.Delete(networkingClient, d.Id()).Err 211 212 if err != nil { 213 return err 214 } 215 216 stateConf = &resource.StateChangeConf{ 217 Pending: []string{"DELETING"}, 218 Target: []string{"DELETED"}, 219 Refresh: waitForFirewallDeletion(networkingClient, d.Id()), 220 Timeout: d.Timeout(schema.TimeoutDelete), 221 Delay: 0, 222 MinTimeout: 2 * time.Second, 223 } 224 225 _, err = stateConf.WaitForState() 226 227 return err 228 } 229 230 func waitForFirewallActive(networkingClient *gophercloud.ServiceClient, id string) resource.StateRefreshFunc { 231 232 return func() (interface{}, string, error) { 233 fw, err := firewalls.Get(networkingClient, id).Extract() 234 log.Printf("[DEBUG] Get firewall %s => %#v", id, fw) 235 236 if err != nil { 237 return nil, "", err 238 } 239 return fw, fw.Status, nil 240 } 241 } 242 243 func waitForFirewallDeletion(networkingClient *gophercloud.ServiceClient, id string) resource.StateRefreshFunc { 244 245 return func() (interface{}, string, error) { 246 fw, err := firewalls.Get(networkingClient, id).Extract() 247 log.Printf("[DEBUG] Get firewall %s => %#v", id, fw) 248 249 if err != nil { 250 if _, ok := err.(gophercloud.ErrDefault404); ok { 251 log.Printf("[DEBUG] Firewall %s is actually deleted", id) 252 return "", "DELETED", nil 253 } 254 return nil, "", fmt.Errorf("Unexpected error: %s", err) 255 } 256 257 log.Printf("[DEBUG] Firewall %s deletion is pending", id) 258 return fw, "DELETING", nil 259 } 260 }