github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/openstack/resource_openstack_fw_policy_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/policies" 10 "github.com/hashicorp/terraform/helper/resource" 11 "github.com/hashicorp/terraform/helper/schema" 12 ) 13 14 func resourceFWPolicyV1() *schema.Resource { 15 return &schema.Resource{ 16 Create: resourceFWPolicyV1Create, 17 Read: resourceFWPolicyV1Read, 18 Update: resourceFWPolicyV1Update, 19 Delete: resourceFWPolicyV1Delete, 20 Importer: &schema.ResourceImporter{ 21 State: schema.ImportStatePassthrough, 22 }, 23 24 Timeouts: &schema.ResourceTimeout{ 25 Create: schema.DefaultTimeout(10 * time.Minute), 26 }, 27 28 Schema: map[string]*schema.Schema{ 29 "region": &schema.Schema{ 30 Type: schema.TypeString, 31 Required: true, 32 ForceNew: true, 33 DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""), 34 }, 35 "name": &schema.Schema{ 36 Type: schema.TypeString, 37 Optional: true, 38 }, 39 "description": &schema.Schema{ 40 Type: schema.TypeString, 41 Optional: true, 42 }, 43 "audited": &schema.Schema{ 44 Type: schema.TypeBool, 45 Optional: true, 46 Default: false, 47 }, 48 "shared": &schema.Schema{ 49 Type: schema.TypeBool, 50 Optional: true, 51 }, 52 "tenant_id": &schema.Schema{ 53 Type: schema.TypeString, 54 Optional: true, 55 ForceNew: true, 56 Computed: true, 57 }, 58 "rules": &schema.Schema{ 59 Type: schema.TypeList, 60 Optional: true, 61 Elem: &schema.Schema{Type: schema.TypeString}, 62 }, 63 "value_specs": &schema.Schema{ 64 Type: schema.TypeMap, 65 Optional: true, 66 ForceNew: true, 67 }, 68 }, 69 } 70 } 71 72 func resourceFWPolicyV1Create(d *schema.ResourceData, meta interface{}) error { 73 config := meta.(*Config) 74 networkingClient, err := config.networkingV2Client(GetRegion(d)) 75 if err != nil { 76 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 77 } 78 79 v := d.Get("rules").([]interface{}) 80 81 log.Printf("[DEBUG] Rules found : %#v", v) 82 log.Printf("[DEBUG] Rules count : %d", len(v)) 83 84 rules := make([]string, len(v)) 85 for i, v := range v { 86 rules[i] = v.(string) 87 } 88 89 audited := d.Get("audited").(bool) 90 91 opts := PolicyCreateOpts{ 92 policies.CreateOpts{ 93 Name: d.Get("name").(string), 94 Description: d.Get("description").(string), 95 Audited: &audited, 96 TenantID: d.Get("tenant_id").(string), 97 Rules: rules, 98 }, 99 MapValueSpecs(d), 100 } 101 102 if r, ok := d.GetOk("shared"); ok { 103 shared := r.(bool) 104 opts.Shared = &shared 105 } 106 107 log.Printf("[DEBUG] Create firewall policy: %#v", opts) 108 109 policy, err := policies.Create(networkingClient, opts).Extract() 110 if err != nil { 111 return err 112 } 113 114 log.Printf("[DEBUG] Firewall policy created: %#v", policy) 115 116 d.SetId(policy.ID) 117 118 return resourceFWPolicyV1Read(d, meta) 119 } 120 121 func resourceFWPolicyV1Read(d *schema.ResourceData, meta interface{}) error { 122 log.Printf("[DEBUG] Retrieve information about firewall policy: %s", d.Id()) 123 124 config := meta.(*Config) 125 networkingClient, err := config.networkingV2Client(GetRegion(d)) 126 if err != nil { 127 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 128 } 129 130 policy, err := policies.Get(networkingClient, d.Id()).Extract() 131 if err != nil { 132 return CheckDeleted(d, err, "FW policy") 133 } 134 135 log.Printf("[DEBUG] Read OpenStack Firewall Policy %s: %#v", d.Id(), policy) 136 137 d.Set("name", policy.Name) 138 d.Set("description", policy.Description) 139 d.Set("shared", policy.Shared) 140 d.Set("audited", policy.Audited) 141 d.Set("tenant_id", policy.TenantID) 142 d.Set("rules", policy.Rules) 143 d.Set("region", GetRegion(d)) 144 145 return nil 146 } 147 148 func resourceFWPolicyV1Update(d *schema.ResourceData, meta interface{}) error { 149 config := meta.(*Config) 150 networkingClient, err := config.networkingV2Client(GetRegion(d)) 151 if err != nil { 152 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 153 } 154 155 opts := policies.UpdateOpts{} 156 157 if d.HasChange("name") { 158 opts.Name = d.Get("name").(string) 159 } 160 161 if d.HasChange("description") { 162 opts.Description = d.Get("description").(string) 163 } 164 165 if d.HasChange("rules") { 166 v := d.Get("rules").([]interface{}) 167 168 log.Printf("[DEBUG] Rules found : %#v", v) 169 log.Printf("[DEBUG] Rules count : %d", len(v)) 170 171 rules := make([]string, len(v)) 172 for i, v := range v { 173 rules[i] = v.(string) 174 } 175 opts.Rules = rules 176 } 177 178 log.Printf("[DEBUG] Updating firewall policy with id %s: %#v", d.Id(), opts) 179 180 err = policies.Update(networkingClient, d.Id(), opts).Err 181 if err != nil { 182 return err 183 } 184 185 return resourceFWPolicyV1Read(d, meta) 186 } 187 188 func resourceFWPolicyV1Delete(d *schema.ResourceData, meta interface{}) error { 189 log.Printf("[DEBUG] Destroy firewall policy: %s", d.Id()) 190 191 config := meta.(*Config) 192 networkingClient, err := config.networkingV2Client(GetRegion(d)) 193 if err != nil { 194 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 195 } 196 197 stateConf := &resource.StateChangeConf{ 198 Pending: []string{"ACTIVE"}, 199 Target: []string{"DELETED"}, 200 Refresh: waitForFirewallPolicyDeletion(networkingClient, d.Id()), 201 Timeout: d.Timeout(schema.TimeoutCreate), 202 Delay: 0, 203 MinTimeout: 2 * time.Second, 204 } 205 206 if _, err = stateConf.WaitForState(); err != nil { 207 return err 208 } 209 210 return nil 211 } 212 213 func waitForFirewallPolicyDeletion(networkingClient *gophercloud.ServiceClient, id string) resource.StateRefreshFunc { 214 return func() (interface{}, string, error) { 215 err := policies.Delete(networkingClient, id).Err 216 if err == nil { 217 return "", "DELETED", nil 218 } 219 220 if errCode, ok := err.(gophercloud.ErrUnexpectedResponseCode); ok { 221 if errCode.Actual == 409 { 222 // This error usually means that the policy is attached 223 // to a firewall. At this point, the firewall is probably 224 // being delete. So, we retry a few times. 225 return nil, "ACTIVE", nil 226 } 227 } 228 229 return nil, "ACTIVE", err 230 } 231 }