terraform/vendor/github.com/terraform-providers/terraform-provider-openstack/openstack/resource_openstack_compute_...

256 lines
6.9 KiB
Go

package openstack
import (
"fmt"
"log"
"strings"
"time"
"github.com/gophercloud/gophercloud"
"github.com/gophercloud/gophercloud/openstack/compute/v2/extensions/secgroups"
"github.com/hashicorp/terraform/helper/resource"
"github.com/hashicorp/terraform/helper/schema"
)
func resourceComputeSecGroupV2() *schema.Resource {
return &schema.Resource{
Create: resourceComputeSecGroupV2Create,
Read: resourceComputeSecGroupV2Read,
Update: resourceComputeSecGroupV2Update,
Delete: resourceComputeSecGroupV2Delete,
Importer: &schema.ResourceImporter{
State: schema.ImportStatePassthrough,
},
Timeouts: &schema.ResourceTimeout{
Delete: schema.DefaultTimeout(10 * time.Minute),
},
Schema: map[string]*schema.Schema{
"region": {
Type: schema.TypeString,
Optional: true,
Computed: true,
ForceNew: true,
},
"name": {
Type: schema.TypeString,
Required: true,
ForceNew: false,
},
"description": {
Type: schema.TypeString,
Required: true,
ForceNew: false,
},
"rule": {
Type: schema.TypeSet,
Optional: true,
Computed: true,
Set: computeSecGroupV2RuleHash,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"id": {
Type: schema.TypeString,
Computed: true,
},
"from_port": {
Type: schema.TypeInt,
Required: true,
ForceNew: false,
},
"to_port": {
Type: schema.TypeInt,
Required: true,
ForceNew: false,
},
"ip_protocol": {
Type: schema.TypeString,
Required: true,
ForceNew: false,
},
"cidr": {
Type: schema.TypeString,
Optional: true,
ForceNew: false,
StateFunc: func(v interface{}) string {
return strings.ToLower(v.(string))
},
},
"from_group_id": {
Type: schema.TypeString,
Optional: true,
ForceNew: false,
},
"self": {
Type: schema.TypeBool,
Optional: true,
Default: false,
ForceNew: false,
},
},
},
},
},
}
}
func resourceComputeSecGroupV2Create(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
computeClient, err := config.computeV2Client(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating OpenStack compute client: %s", err)
}
// Before creating the security group, make sure all rules are valid.
if err := computeSecGroupV2RulesCheckForErrors(d); err != nil {
return err
}
// If all rules are valid, proceed with creating the security gruop.
name := d.Get("name").(string)
createOpts := secgroups.CreateOpts{
Name: name,
Description: d.Get("description").(string),
}
log.Printf("[DEBUG] openstack_compute_secgroup_v2 Create Options: %#v", createOpts)
sg, err := secgroups.Create(computeClient, createOpts).Extract()
if err != nil {
return fmt.Errorf("Error creating openstack_compute_secgroup_v2 %s: %s", name, err)
}
d.SetId(sg.ID)
// Now that the security group has been created, iterate through each rule and create it
createRuleOptsList := expandComputeSecGroupV2CreateRules(d)
for _, createRuleOpts := range createRuleOptsList {
_, err := secgroups.CreateRule(computeClient, createRuleOpts).Extract()
if err != nil {
return fmt.Errorf("Error creating openstack_compute_secgroup_v2 %s rule: %s", name, err)
}
}
return resourceComputeSecGroupV2Read(d, meta)
}
func resourceComputeSecGroupV2Read(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
computeClient, err := config.computeV2Client(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating OpenStack compute client: %s", err)
}
sg, err := secgroups.Get(computeClient, d.Id()).Extract()
if err != nil {
return CheckDeleted(d, err, "Error retrieving openstack_compute_secgroup_v2")
}
d.Set("name", sg.Name)
d.Set("description", sg.Description)
rules, err := flattenComputeSecGroupV2Rules(computeClient, d, sg.Rules)
if err != nil {
return err
}
log.Printf("[DEBUG] Retrieved openstack_compute_secgroup_v2 %s rules: %#v", d.Id(), rules)
if err := d.Set("rule", rules); err != nil {
return fmt.Errorf("Unable to set openstack_compute_secgroup_v2 %s rules: %s", d.Id(), err)
}
d.Set("region", GetRegion(d, config))
return nil
}
func resourceComputeSecGroupV2Update(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
computeClient, err := config.computeV2Client(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating OpenStack compute client: %s", err)
}
description := d.Get("description").(string)
updateOpts := secgroups.UpdateOpts{
Name: d.Get("name").(string),
Description: &description,
}
log.Printf("[DEBUG] openstack_compute_secgroup_v2 %s Update Options: %#v", d.Id(), updateOpts)
_, err = secgroups.Update(computeClient, d.Id(), updateOpts).Extract()
if err != nil {
return fmt.Errorf("Error updating openstack_compute_secgroup_v2 %s: %s", d.Id(), err)
}
if d.HasChange("rule") {
oldSGRaw, newSGRaw := d.GetChange("rule")
oldSGRSet, newSGRSet := oldSGRaw.(*schema.Set), newSGRaw.(*schema.Set)
secgrouprulesToAdd := newSGRSet.Difference(oldSGRSet)
secgrouprulesToRemove := oldSGRSet.Difference(newSGRSet)
log.Printf("[DEBUG] openstack_compute_secgroup_v2 %s rules to add: %v", d.Id(), secgrouprulesToAdd)
log.Printf("[DEBUG] openstack_compute_secgroup_v2 %s rules to remove: %v", d.Id(), secgrouprulesToRemove)
for _, rawRule := range secgrouprulesToAdd.List() {
createRuleOpts := expandComputeSecGroupV2CreateRule(d, rawRule)
_, err := secgroups.CreateRule(computeClient, createRuleOpts).Extract()
if err != nil {
return fmt.Errorf("Error adding rule to openstack_compute_secgroup_v2 %s: %s", d.Id(), err)
}
}
for _, r := range secgrouprulesToRemove.List() {
rule := expandComputeSecGroupV2Rule(d, r)
err := secgroups.DeleteRule(computeClient, rule.ID).ExtractErr()
if err != nil {
if _, ok := err.(gophercloud.ErrDefault404); ok {
continue
}
return fmt.Errorf("Error removing rule %s from openstack_compute_secgroup_v2 %s: %s", rule.ID, d.Id(), err)
}
}
}
return resourceComputeSecGroupV2Read(d, meta)
}
func resourceComputeSecGroupV2Delete(d *schema.ResourceData, meta interface{}) error {
config := meta.(*Config)
computeClient, err := config.computeV2Client(GetRegion(d, config))
if err != nil {
return fmt.Errorf("Error creating OpenStack compute client: %s", err)
}
stateConf := &resource.StateChangeConf{
Pending: []string{"ACTIVE"},
Target: []string{"DELETED"},
Refresh: computeSecGroupV2StateRefreshFunc(computeClient, d),
Timeout: d.Timeout(schema.TimeoutDelete),
Delay: 1 * time.Second,
MinTimeout: 3 * time.Second,
}
_, err = stateConf.WaitForState()
if err != nil {
return CheckDeleted(d, err, "Error deleting openstack_compute_secgroup_v2")
}
return nil
}