github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/openstack/resource_openstack_networking_secgroup_rule_v2.go (about) 1 package openstack 2 3 import ( 4 "fmt" 5 "log" 6 "strings" 7 "time" 8 9 "github.com/hashicorp/terraform/helper/resource" 10 "github.com/hashicorp/terraform/helper/schema" 11 12 "github.com/gophercloud/gophercloud" 13 "github.com/gophercloud/gophercloud/openstack/networking/v2/extensions/security/rules" 14 ) 15 16 func resourceNetworkingSecGroupRuleV2() *schema.Resource { 17 return &schema.Resource{ 18 Create: resourceNetworkingSecGroupRuleV2Create, 19 Read: resourceNetworkingSecGroupRuleV2Read, 20 Delete: resourceNetworkingSecGroupRuleV2Delete, 21 Importer: &schema.ResourceImporter{ 22 State: schema.ImportStatePassthrough, 23 }, 24 25 Timeouts: &schema.ResourceTimeout{ 26 Delete: schema.DefaultTimeout(10 * time.Minute), 27 }, 28 29 Schema: map[string]*schema.Schema{ 30 "region": &schema.Schema{ 31 Type: schema.TypeString, 32 Required: true, 33 ForceNew: true, 34 DefaultFunc: schema.EnvDefaultFunc("OS_REGION_NAME", ""), 35 }, 36 "direction": &schema.Schema{ 37 Type: schema.TypeString, 38 Required: true, 39 ForceNew: true, 40 }, 41 "ethertype": &schema.Schema{ 42 Type: schema.TypeString, 43 Required: true, 44 ForceNew: true, 45 }, 46 "port_range_min": &schema.Schema{ 47 Type: schema.TypeInt, 48 Optional: true, 49 ForceNew: true, 50 Computed: true, 51 }, 52 "port_range_max": &schema.Schema{ 53 Type: schema.TypeInt, 54 Optional: true, 55 ForceNew: true, 56 Computed: true, 57 }, 58 "protocol": &schema.Schema{ 59 Type: schema.TypeString, 60 Optional: true, 61 ForceNew: true, 62 Computed: true, 63 }, 64 "remote_group_id": &schema.Schema{ 65 Type: schema.TypeString, 66 Optional: true, 67 ForceNew: true, 68 Computed: true, 69 }, 70 "remote_ip_prefix": &schema.Schema{ 71 Type: schema.TypeString, 72 Optional: true, 73 ForceNew: true, 74 Computed: true, 75 StateFunc: func(v interface{}) string { 76 return strings.ToLower(v.(string)) 77 }, 78 }, 79 "security_group_id": &schema.Schema{ 80 Type: schema.TypeString, 81 Required: true, 82 ForceNew: true, 83 }, 84 "tenant_id": &schema.Schema{ 85 Type: schema.TypeString, 86 Optional: true, 87 ForceNew: true, 88 Computed: true, 89 }, 90 }, 91 } 92 } 93 94 func resourceNetworkingSecGroupRuleV2Create(d *schema.ResourceData, meta interface{}) error { 95 96 config := meta.(*Config) 97 networkingClient, err := config.networkingV2Client(GetRegion(d)) 98 if err != nil { 99 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 100 } 101 102 portRangeMin := d.Get("port_range_min").(int) 103 portRangeMax := d.Get("port_range_max").(int) 104 protocol := d.Get("protocol").(string) 105 106 if protocol == "" { 107 if portRangeMin != 0 || portRangeMax != 0 { 108 return fmt.Errorf("A protocol must be specified when using port_range_min and port_range_max") 109 } 110 } 111 112 opts := rules.CreateOpts{ 113 SecGroupID: d.Get("security_group_id").(string), 114 PortRangeMin: d.Get("port_range_min").(int), 115 PortRangeMax: d.Get("port_range_max").(int), 116 RemoteGroupID: d.Get("remote_group_id").(string), 117 RemoteIPPrefix: d.Get("remote_ip_prefix").(string), 118 TenantID: d.Get("tenant_id").(string), 119 } 120 121 if v, ok := d.GetOk("direction"); ok { 122 direction := resourceNetworkingSecGroupRuleV2DetermineDirection(v.(string)) 123 opts.Direction = direction 124 } 125 126 if v, ok := d.GetOk("ethertype"); ok { 127 ethertype := resourceNetworkingSecGroupRuleV2DetermineEtherType(v.(string)) 128 opts.EtherType = ethertype 129 } 130 131 if v, ok := d.GetOk("protocol"); ok { 132 protocol := resourceNetworkingSecGroupRuleV2DetermineProtocol(v.(string)) 133 opts.Protocol = protocol 134 } 135 136 log.Printf("[DEBUG] Create OpenStack Neutron security group: %#v", opts) 137 138 security_group_rule, err := rules.Create(networkingClient, opts).Extract() 139 if err != nil { 140 return err 141 } 142 143 log.Printf("[DEBUG] OpenStack Neutron Security Group Rule created: %#v", security_group_rule) 144 145 d.SetId(security_group_rule.ID) 146 147 return resourceNetworkingSecGroupRuleV2Read(d, meta) 148 } 149 150 func resourceNetworkingSecGroupRuleV2Read(d *schema.ResourceData, meta interface{}) error { 151 log.Printf("[DEBUG] Retrieve information about security group rule: %s", d.Id()) 152 153 config := meta.(*Config) 154 networkingClient, err := config.networkingV2Client(GetRegion(d)) 155 if err != nil { 156 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 157 } 158 159 security_group_rule, err := rules.Get(networkingClient, d.Id()).Extract() 160 161 if err != nil { 162 return CheckDeleted(d, err, "OpenStack Security Group Rule") 163 } 164 165 d.Set("direction", security_group_rule.Direction) 166 d.Set("ethertype", security_group_rule.EtherType) 167 d.Set("protocol", security_group_rule.Protocol) 168 d.Set("port_range_min", security_group_rule.PortRangeMin) 169 d.Set("port_range_max", security_group_rule.PortRangeMax) 170 d.Set("remote_group_id", security_group_rule.RemoteGroupID) 171 d.Set("remote_ip_prefix", security_group_rule.RemoteIPPrefix) 172 d.Set("security_group_id", security_group_rule.SecGroupID) 173 d.Set("tenant_id", security_group_rule.TenantID) 174 d.Set("region", GetRegion(d)) 175 176 return nil 177 } 178 179 func resourceNetworkingSecGroupRuleV2Delete(d *schema.ResourceData, meta interface{}) error { 180 log.Printf("[DEBUG] Destroy security group rule: %s", d.Id()) 181 182 config := meta.(*Config) 183 networkingClient, err := config.networkingV2Client(GetRegion(d)) 184 if err != nil { 185 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 186 } 187 188 stateConf := &resource.StateChangeConf{ 189 Pending: []string{"ACTIVE"}, 190 Target: []string{"DELETED"}, 191 Refresh: waitForSecGroupRuleDelete(networkingClient, d.Id()), 192 Timeout: d.Timeout(schema.TimeoutDelete), 193 Delay: 5 * time.Second, 194 MinTimeout: 3 * time.Second, 195 } 196 197 _, err = stateConf.WaitForState() 198 if err != nil { 199 return fmt.Errorf("Error deleting OpenStack Neutron Security Group Rule: %s", err) 200 } 201 202 d.SetId("") 203 return err 204 } 205 206 func resourceNetworkingSecGroupRuleV2DetermineDirection(v string) rules.RuleDirection { 207 var direction rules.RuleDirection 208 switch v { 209 case "ingress": 210 direction = rules.DirIngress 211 case "egress": 212 direction = rules.DirEgress 213 } 214 215 return direction 216 } 217 218 func resourceNetworkingSecGroupRuleV2DetermineEtherType(v string) rules.RuleEtherType { 219 var etherType rules.RuleEtherType 220 switch v { 221 case "IPv4": 222 etherType = rules.EtherType4 223 case "IPv6": 224 etherType = rules.EtherType6 225 } 226 227 return etherType 228 } 229 230 func resourceNetworkingSecGroupRuleV2DetermineProtocol(v string) rules.RuleProtocol { 231 var protocol rules.RuleProtocol 232 switch v { 233 case "tcp": 234 protocol = rules.ProtocolTCP 235 case "udp": 236 protocol = rules.ProtocolUDP 237 case "icmp": 238 protocol = rules.ProtocolICMP 239 } 240 241 return protocol 242 } 243 244 func waitForSecGroupRuleDelete(networkingClient *gophercloud.ServiceClient, secGroupRuleId string) resource.StateRefreshFunc { 245 return func() (interface{}, string, error) { 246 log.Printf("[DEBUG] Attempting to delete OpenStack Security Group Rule %s.\n", secGroupRuleId) 247 248 r, err := rules.Get(networkingClient, secGroupRuleId).Extract() 249 if err != nil { 250 if _, ok := err.(gophercloud.ErrDefault404); ok { 251 log.Printf("[DEBUG] Successfully deleted OpenStack Neutron Security Group Rule %s", secGroupRuleId) 252 return r, "DELETED", nil 253 } 254 return r, "ACTIVE", err 255 } 256 257 err = rules.Delete(networkingClient, secGroupRuleId).ExtractErr() 258 if err != nil { 259 if _, ok := err.(gophercloud.ErrDefault404); ok { 260 log.Printf("[DEBUG] Successfully deleted OpenStack Neutron Security Group Rule %s", secGroupRuleId) 261 return r, "DELETED", nil 262 } 263 return r, "ACTIVE", err 264 } 265 266 log.Printf("[DEBUG] OpenStack Neutron Security Group Rule %s still active.\n", secGroupRuleId) 267 return r, "ACTIVE", nil 268 } 269 }