github.com/ezbercih/terraform@v0.1.1-0.20140729011846-3c33865e0839/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.ResourceState,
    19  	d *terraform.ResourceDiff,
    20  	meta interface{}) (*terraform.ResourceState, 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.ResourceState,
    89  	d *terraform.ResourceDiff,
    90  	meta interface{}) (*terraform.ResourceState, error) {
    91  
    92  	panic("Cannot update DB")
    93  
    94  	return nil, nil
    95  }
    96  
    97  func resource_aws_db_security_group_destroy(
    98  	s *terraform.ResourceState,
    99  	meta interface{}) error {
   100  	p := meta.(*ResourceProvider)
   101  	conn := p.rdsconn
   102  
   103  	log.Printf("[DEBUG] DB Security Group destroy: %v", s.ID)
   104  
   105  	opts := rds.DeleteDBSecurityGroup{DBSecurityGroupName: s.ID}
   106  
   107  	log.Printf("[DEBUG] DB Security Group destroy configuration: %v", opts)
   108  	_, err := conn.DeleteDBSecurityGroup(&opts)
   109  
   110  	if err != nil {
   111  		newerr, ok := err.(*rds.Error)
   112  		if ok && newerr.Code == "InvalidDBSecurityGroup.NotFound" {
   113  			return nil
   114  		}
   115  		return err
   116  	}
   117  
   118  	return nil
   119  }
   120  
   121  func resource_aws_db_security_group_refresh(
   122  	s *terraform.ResourceState,
   123  	meta interface{}) (*terraform.ResourceState, error) {
   124  	p := meta.(*ResourceProvider)
   125  	conn := p.rdsconn
   126  
   127  	v, err := resource_aws_db_security_group_retrieve(s.ID, conn)
   128  
   129  	if err != nil {
   130  		return s, err
   131  	}
   132  
   133  	return resource_aws_db_security_group_update_state(s, v)
   134  }
   135  
   136  func resource_aws_db_security_group_diff(
   137  	s *terraform.ResourceState,
   138  	c *terraform.ResourceConfig,
   139  	meta interface{}) (*terraform.ResourceDiff, error) {
   140  
   141  	b := &diff.ResourceBuilder{
   142  		Attrs: map[string]diff.AttrType{
   143  			"name":        diff.AttrTypeCreate,
   144  			"description": diff.AttrTypeCreate,
   145  			"ingress":     diff.AttrTypeCreate,
   146  		},
   147  
   148  		ComputedAttrs: []string{
   149  			"ingress_cidr",
   150  			"ingress_security_groups",
   151  		},
   152  	}
   153  
   154  	return b.Diff(s, c)
   155  }
   156  
   157  func resource_aws_db_security_group_update_state(
   158  	s *terraform.ResourceState,
   159  	v *rds.DBSecurityGroup) (*terraform.ResourceState, error) {
   160  
   161  	s.Attributes["name"] = v.Name
   162  	s.Attributes["description"] = v.Description
   163  
   164  	// Flatten our group values
   165  	toFlatten := make(map[string]interface{})
   166  
   167  	if len(v.EC2SecurityGroupOwnerIds) > 0 && v.EC2SecurityGroupOwnerIds[0] != "" {
   168  		toFlatten["ingress_security_groups"] = v.EC2SecurityGroupOwnerIds
   169  	}
   170  
   171  	if len(v.CidrIps) > 0 && v.CidrIps[0] != "" {
   172  		toFlatten["ingress_cidr"] = v.CidrIps
   173  	}
   174  
   175  	for k, v := range flatmap.Flatten(toFlatten) {
   176  		s.Attributes[k] = v
   177  	}
   178  
   179  	return s, nil
   180  }
   181  
   182  func resource_aws_db_security_group_retrieve(id string, conn *rds.Rds) (*rds.DBSecurityGroup, error) {
   183  	opts := rds.DescribeDBSecurityGroups{
   184  		DBSecurityGroupName: id,
   185  	}
   186  
   187  	log.Printf("[DEBUG] DB Security Group describe configuration: %#v", opts)
   188  
   189  	resp, err := conn.DescribeDBSecurityGroups(&opts)
   190  
   191  	if err != nil {
   192  		return nil, fmt.Errorf("Error retrieving DB Security Groups: %s", err)
   193  	}
   194  
   195  	if len(resp.DBSecurityGroups) != 1 ||
   196  		resp.DBSecurityGroups[0].Name != id {
   197  		if err != nil {
   198  			return nil, fmt.Errorf("Unable to find DB Security Group: %#v", resp.DBSecurityGroups)
   199  		}
   200  	}
   201  
   202  	v := resp.DBSecurityGroups[0]
   203  
   204  	return &v, nil
   205  }
   206  
   207  // Authorizes the ingress rule on the db security group
   208  func authorize_ingress_rule(ingress interface{}, dbSecurityGroupName string, conn *rds.Rds) error {
   209  	ing := ingress.(map[string]interface{})
   210  
   211  	opts := rds.AuthorizeDBSecurityGroupIngress{
   212  		DBSecurityGroupName: dbSecurityGroupName,
   213  	}
   214  
   215  	if attr, ok := ing["cidr"].(string); ok && attr != "" {
   216  		opts.Cidr = attr
   217  	}
   218  
   219  	if attr, ok := ing["security_group_name"].(string); ok && attr != "" {
   220  		opts.EC2SecurityGroupName = attr
   221  	}
   222  
   223  	if attr, ok := ing["security_group_id"].(string); ok && attr != "" {
   224  		opts.EC2SecurityGroupId = attr
   225  	}
   226  
   227  	if attr, ok := ing["security_group_owner_id"].(string); ok && attr != "" {
   228  		opts.EC2SecurityGroupOwnerId = attr
   229  	}
   230  
   231  	log.Printf("[DEBUG] Authorize ingress rule configuration: %#v", opts)
   232  
   233  	_, err := conn.AuthorizeDBSecurityGroupIngress(&opts)
   234  
   235  	if err != nil {
   236  		return fmt.Errorf("Error authorizing security group ingress: %s", err)
   237  	}
   238  
   239  	return nil
   240  }
   241  
   242  func resource_aws_db_security_group_validation() *config.Validator {
   243  	return &config.Validator{
   244  		Required: []string{
   245  			"name",
   246  			"description",
   247  		},
   248  		Optional: []string{
   249  			"ingress.*",
   250  			"ingress.*.cidr",
   251  			"ingress.*.security_group_name",
   252  			"ingress.*.security_group_id",
   253  			"ingress.*.security_group_owner_id",
   254  		},
   255  	}
   256  }
   257  
   258  func DBSecurityGroupStateRefreshFunc(id string, conn *rds.Rds) resource.StateRefreshFunc {
   259  	return func() (interface{}, string, error) {
   260  		v, err := resource_aws_db_security_group_retrieve(id, conn)
   261  
   262  		if err != nil {
   263  			log.Printf("Error on retrieving DB Security Group when waiting: %s", err)
   264  			return nil, "", err
   265  		}
   266  
   267  		statuses := append(v.EC2SecurityGroupStatuses, v.CidrStatuses...)
   268  
   269  		for _, stat := range statuses {
   270  			// Not done
   271  			if stat != "authorized" {
   272  				return nil, "authorizing", nil
   273  			}
   274  		}
   275  
   276  		return v, "authorized", nil
   277  	}
   278  }