github.com/bengesoff/terraform@v0.3.1-0.20141018223233-b25a53629922/builtin/providers/aws/resource_aws_db_security_group.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"log"
     6  	"time"
     7  
     8  	"github.com/hashicorp/terraform/flatmap"
     9  	"github.com/hashicorp/terraform/helper/config"
    10  	"github.com/hashicorp/terraform/helper/diff"
    11  	"github.com/hashicorp/terraform/helper/multierror"
    12  	"github.com/hashicorp/terraform/helper/resource"
    13  	"github.com/hashicorp/terraform/terraform"
    14  	"github.com/mitchellh/goamz/rds"
    15  )
    16  
    17  func resource_aws_db_security_group_create(
    18  	s *terraform.InstanceState,
    19  	d *terraform.InstanceDiff,
    20  	meta interface{}) (*terraform.InstanceState, error) {
    21  	p := meta.(*ResourceProvider)
    22  	conn := p.rdsconn
    23  
    24  	// Merge the diff into the state so that we have all the attributes
    25  	// properly.
    26  	rs := s.MergeDiff(d)
    27  
    28  	var err error
    29  	var errs []error
    30  
    31  	opts := rds.CreateDBSecurityGroup{
    32  		DBSecurityGroupName:        rs.Attributes["name"],
    33  		DBSecurityGroupDescription: rs.Attributes["description"],
    34  	}
    35  
    36  	log.Printf("[DEBUG] DB Security Group create configuration: %#v", opts)
    37  	_, err = conn.CreateDBSecurityGroup(&opts)
    38  	if err != nil {
    39  		return nil, fmt.Errorf("Error creating DB Security Group: %s", err)
    40  	}
    41  
    42  	rs.ID = rs.Attributes["name"]
    43  
    44  	log.Printf("[INFO] DB Security Group ID: %s", rs.ID)
    45  
    46  	v, err := resource_aws_db_security_group_retrieve(rs.ID, conn)
    47  	if err != nil {
    48  		return rs, err
    49  	}
    50  
    51  	if _, ok := rs.Attributes["ingress.#"]; ok {
    52  		ingresses := flatmap.Expand(
    53  			rs.Attributes, "ingress").([]interface{})
    54  
    55  		for _, ing := range ingresses {
    56  			err = authorize_ingress_rule(ing, v.Name, conn)
    57  
    58  			if err != nil {
    59  				errs = append(errs, err)
    60  			}
    61  		}
    62  
    63  		if len(errs) > 0 {
    64  			return rs, &multierror.Error{Errors: errs}
    65  		}
    66  	}
    67  
    68  	log.Println(
    69  		"[INFO] Waiting for Ingress Authorizations to be authorized")
    70  
    71  	stateConf := &resource.StateChangeConf{
    72  		Pending: []string{"authorizing"},
    73  		Target:  "authorized",
    74  		Refresh: DBSecurityGroupStateRefreshFunc(rs.ID, conn),
    75  		Timeout: 10 * time.Minute,
    76  	}
    77  
    78  	// Wait, catching any errors
    79  	_, err = stateConf.WaitForState()
    80  	if err != nil {
    81  		return rs, err
    82  	}
    83  
    84  	return resource_aws_db_security_group_update_state(rs, v)
    85  }
    86  
    87  func resource_aws_db_security_group_update(
    88  	s *terraform.InstanceState,
    89  	d *terraform.InstanceDiff,
    90  	meta interface{}) (*terraform.InstanceState, error) {
    91  	panic("Cannot update DB security group")
    92  }
    93  
    94  func resource_aws_db_security_group_destroy(
    95  	s *terraform.InstanceState,
    96  	meta interface{}) error {
    97  	p := meta.(*ResourceProvider)
    98  	conn := p.rdsconn
    99  
   100  	log.Printf("[DEBUG] DB Security Group destroy: %v", s.ID)
   101  
   102  	opts := rds.DeleteDBSecurityGroup{DBSecurityGroupName: s.ID}
   103  
   104  	log.Printf("[DEBUG] DB Security Group destroy configuration: %v", opts)
   105  	_, err := conn.DeleteDBSecurityGroup(&opts)
   106  
   107  	if err != nil {
   108  		newerr, ok := err.(*rds.Error)
   109  		if ok && newerr.Code == "InvalidDBSecurityGroup.NotFound" {
   110  			return nil
   111  		}
   112  		return err
   113  	}
   114  
   115  	return nil
   116  }
   117  
   118  func resource_aws_db_security_group_refresh(
   119  	s *terraform.InstanceState,
   120  	meta interface{}) (*terraform.InstanceState, error) {
   121  	p := meta.(*ResourceProvider)
   122  	conn := p.rdsconn
   123  
   124  	v, err := resource_aws_db_security_group_retrieve(s.ID, conn)
   125  
   126  	if err != nil {
   127  		return s, err
   128  	}
   129  
   130  	return resource_aws_db_security_group_update_state(s, v)
   131  }
   132  
   133  func resource_aws_db_security_group_diff(
   134  	s *terraform.InstanceState,
   135  	c *terraform.ResourceConfig,
   136  	meta interface{}) (*terraform.InstanceDiff, error) {
   137  
   138  	b := &diff.ResourceBuilder{
   139  		Attrs: map[string]diff.AttrType{
   140  			"name":        diff.AttrTypeCreate,
   141  			"description": diff.AttrTypeCreate,
   142  			"ingress":     diff.AttrTypeCreate,
   143  		},
   144  
   145  		ComputedAttrs: []string{
   146  			"ingress_cidr",
   147  			"ingress_security_groups",
   148  		},
   149  	}
   150  
   151  	return b.Diff(s, c)
   152  }
   153  
   154  func resource_aws_db_security_group_update_state(
   155  	s *terraform.InstanceState,
   156  	v *rds.DBSecurityGroup) (*terraform.InstanceState, error) {
   157  
   158  	s.Attributes["name"] = v.Name
   159  	s.Attributes["description"] = v.Description
   160  
   161  	// Flatten our group values
   162  	toFlatten := make(map[string]interface{})
   163  
   164  	if len(v.EC2SecurityGroupOwnerIds) > 0 && v.EC2SecurityGroupOwnerIds[0] != "" {
   165  		toFlatten["ingress_security_groups"] = v.EC2SecurityGroupOwnerIds
   166  	}
   167  
   168  	if len(v.CidrIps) > 0 && v.CidrIps[0] != "" {
   169  		toFlatten["ingress_cidr"] = v.CidrIps
   170  	}
   171  
   172  	for k, v := range flatmap.Flatten(toFlatten) {
   173  		s.Attributes[k] = v
   174  	}
   175  
   176  	return s, nil
   177  }
   178  
   179  func resource_aws_db_security_group_retrieve(id string, conn *rds.Rds) (*rds.DBSecurityGroup, error) {
   180  	opts := rds.DescribeDBSecurityGroups{
   181  		DBSecurityGroupName: id,
   182  	}
   183  
   184  	log.Printf("[DEBUG] DB Security Group describe configuration: %#v", opts)
   185  
   186  	resp, err := conn.DescribeDBSecurityGroups(&opts)
   187  
   188  	if err != nil {
   189  		return nil, fmt.Errorf("Error retrieving DB Security Groups: %s", err)
   190  	}
   191  
   192  	if len(resp.DBSecurityGroups) != 1 ||
   193  		resp.DBSecurityGroups[0].Name != id {
   194  		if err != nil {
   195  			return nil, fmt.Errorf("Unable to find DB Security Group: %#v", resp.DBSecurityGroups)
   196  		}
   197  	}
   198  
   199  	v := resp.DBSecurityGroups[0]
   200  
   201  	return &v, nil
   202  }
   203  
   204  // Authorizes the ingress rule on the db security group
   205  func authorize_ingress_rule(ingress interface{}, dbSecurityGroupName string, conn *rds.Rds) error {
   206  	ing := ingress.(map[string]interface{})
   207  
   208  	opts := rds.AuthorizeDBSecurityGroupIngress{
   209  		DBSecurityGroupName: dbSecurityGroupName,
   210  	}
   211  
   212  	if attr, ok := ing["cidr"].(string); ok && attr != "" {
   213  		opts.Cidr = attr
   214  	}
   215  
   216  	if attr, ok := ing["security_group_name"].(string); ok && attr != "" {
   217  		opts.EC2SecurityGroupName = attr
   218  	}
   219  
   220  	if attr, ok := ing["security_group_id"].(string); ok && attr != "" {
   221  		opts.EC2SecurityGroupId = attr
   222  	}
   223  
   224  	if attr, ok := ing["security_group_owner_id"].(string); ok && attr != "" {
   225  		opts.EC2SecurityGroupOwnerId = attr
   226  	}
   227  
   228  	log.Printf("[DEBUG] Authorize ingress rule configuration: %#v", opts)
   229  
   230  	_, err := conn.AuthorizeDBSecurityGroupIngress(&opts)
   231  
   232  	if err != nil {
   233  		return fmt.Errorf("Error authorizing security group ingress: %s", err)
   234  	}
   235  
   236  	return nil
   237  }
   238  
   239  func resource_aws_db_security_group_validation() *config.Validator {
   240  	return &config.Validator{
   241  		Required: []string{
   242  			"name",
   243  			"description",
   244  		},
   245  		Optional: []string{
   246  			"ingress.*",
   247  			"ingress.*.cidr",
   248  			"ingress.*.security_group_name",
   249  			"ingress.*.security_group_id",
   250  			"ingress.*.security_group_owner_id",
   251  		},
   252  	}
   253  }
   254  
   255  func DBSecurityGroupStateRefreshFunc(id string, conn *rds.Rds) resource.StateRefreshFunc {
   256  	return func() (interface{}, string, error) {
   257  		v, err := resource_aws_db_security_group_retrieve(id, conn)
   258  
   259  		if err != nil {
   260  			log.Printf("Error on retrieving DB Security Group when waiting: %s", err)
   261  			return nil, "", err
   262  		}
   263  
   264  		statuses := append(v.EC2SecurityGroupStatuses, v.CidrStatuses...)
   265  
   266  		for _, stat := range statuses {
   267  			// Not done
   268  			if stat != "authorized" {
   269  				return nil, "authorizing", nil
   270  			}
   271  		}
   272  
   273  		return v, "authorized", nil
   274  	}
   275  }