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