github.com/minamijoyo/terraform@v0.7.8-0.20161029001309-18b3736ba44b/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(d.Get("region").(string)) 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(d.Get("region").(string)) 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 return nil 171 } 172 173 func resourceNetworkingSecGroupRuleV2Delete(d *schema.ResourceData, meta interface{}) error { 174 log.Printf("[DEBUG] Destroy security group rule: %s", d.Id()) 175 176 config := meta.(*Config) 177 networkingClient, err := config.networkingV2Client(d.Get("region").(string)) 178 if err != nil { 179 return fmt.Errorf("Error creating OpenStack networking client: %s", err) 180 } 181 182 stateConf := &resource.StateChangeConf{ 183 Pending: []string{"ACTIVE"}, 184 Target: []string{"DELETED"}, 185 Refresh: waitForSecGroupRuleDelete(networkingClient, d.Id()), 186 Timeout: 2 * time.Minute, 187 Delay: 5 * time.Second, 188 MinTimeout: 3 * time.Second, 189 } 190 191 _, err = stateConf.WaitForState() 192 if err != nil { 193 return fmt.Errorf("Error deleting OpenStack Neutron Security Group Rule: %s", err) 194 } 195 196 d.SetId("") 197 return err 198 } 199 200 func resourceNetworkingSecGroupRuleV2DetermineDirection(v string) rules.RuleDirection { 201 var direction rules.RuleDirection 202 switch v { 203 case "ingress": 204 direction = rules.DirIngress 205 case "egress": 206 direction = rules.DirEgress 207 } 208 209 return direction 210 } 211 212 func resourceNetworkingSecGroupRuleV2DetermineEtherType(v string) rules.RuleEtherType { 213 var etherType rules.RuleEtherType 214 switch v { 215 case "IPv4": 216 etherType = rules.EtherType4 217 case "IPv6": 218 etherType = rules.EtherType6 219 } 220 221 return etherType 222 } 223 224 func resourceNetworkingSecGroupRuleV2DetermineProtocol(v string) rules.RuleProtocol { 225 var protocol rules.RuleProtocol 226 switch v { 227 case "tcp": 228 protocol = rules.ProtocolTCP 229 case "udp": 230 protocol = rules.ProtocolUDP 231 case "icmp": 232 protocol = rules.ProtocolICMP 233 } 234 235 return protocol 236 } 237 238 func waitForSecGroupRuleDelete(networkingClient *gophercloud.ServiceClient, secGroupRuleId string) resource.StateRefreshFunc { 239 return func() (interface{}, string, error) { 240 log.Printf("[DEBUG] Attempting to delete OpenStack Security Group Rule %s.\n", secGroupRuleId) 241 242 r, err := rules.Get(networkingClient, secGroupRuleId).Extract() 243 if err != nil { 244 if _, ok := err.(gophercloud.ErrDefault404); ok { 245 log.Printf("[DEBUG] Successfully deleted OpenStack Neutron Security Group Rule %s", secGroupRuleId) 246 return r, "DELETED", nil 247 } 248 return r, "ACTIVE", err 249 } 250 251 err = rules.Delete(networkingClient, secGroupRuleId).ExtractErr() 252 if err != nil { 253 if _, ok := err.(gophercloud.ErrDefault404); ok { 254 log.Printf("[DEBUG] Successfully deleted OpenStack Neutron Security Group Rule %s", secGroupRuleId) 255 return r, "DELETED", nil 256 } 257 return r, "ACTIVE", err 258 } 259 260 log.Printf("[DEBUG] OpenStack Neutron Security Group Rule %s still active.\n", secGroupRuleId) 261 return r, "ACTIVE", nil 262 } 263 }