github.com/armen/terraform@v0.5.2-0.20150529052519-caa8117a08f1/builtin/providers/aws/structure.go (about)

     1  package aws
     2  
     3  import (
     4  	"fmt"
     5  	"sort"
     6  	"strings"
     7  
     8  	"github.com/awslabs/aws-sdk-go/aws"
     9  	"github.com/awslabs/aws-sdk-go/service/ec2"
    10  	"github.com/awslabs/aws-sdk-go/service/elb"
    11  	"github.com/awslabs/aws-sdk-go/service/rds"
    12  	"github.com/awslabs/aws-sdk-go/service/route53"
    13  	"github.com/hashicorp/terraform/helper/schema"
    14  )
    15  
    16  // Takes the result of flatmap.Expand for an array of listeners and
    17  // returns ELB API compatible objects
    18  func expandListeners(configured []interface{}) ([]*elb.Listener, error) {
    19  	listeners := make([]*elb.Listener, 0, len(configured))
    20  
    21  	// Loop over our configured listeners and create
    22  	// an array of aws-sdk-go compatabile objects
    23  	for _, lRaw := range configured {
    24  		data := lRaw.(map[string]interface{})
    25  
    26  		ip := int64(data["instance_port"].(int))
    27  		lp := int64(data["lb_port"].(int))
    28  		l := &elb.Listener{
    29  			InstancePort:     &ip,
    30  			InstanceProtocol: aws.String(data["instance_protocol"].(string)),
    31  			LoadBalancerPort: &lp,
    32  			Protocol:         aws.String(data["lb_protocol"].(string)),
    33  		}
    34  
    35  		if v, ok := data["ssl_certificate_id"]; ok {
    36  			l.SSLCertificateID = aws.String(v.(string))
    37  		}
    38  
    39  		listeners = append(listeners, l)
    40  	}
    41  
    42  	return listeners, nil
    43  }
    44  
    45  // Takes the result of flatmap.Expand for an array of ingress/egress security
    46  // group rules and returns EC2 API compatible objects. This function will error
    47  // if it finds invalid permissions input, namely a protocol of "-1" with either
    48  // to_port or from_port set to a non-zero value.
    49  func expandIPPerms(
    50  	group *ec2.SecurityGroup, configured []interface{}) ([]*ec2.IPPermission, error) {
    51  	vpc := group.VPCID != nil
    52  
    53  	perms := make([]*ec2.IPPermission, len(configured))
    54  	for i, mRaw := range configured {
    55  		var perm ec2.IPPermission
    56  		m := mRaw.(map[string]interface{})
    57  
    58  		perm.FromPort = aws.Long(int64(m["from_port"].(int)))
    59  		perm.ToPort = aws.Long(int64(m["to_port"].(int)))
    60  		perm.IPProtocol = aws.String(m["protocol"].(string))
    61  
    62  		// When protocol is "-1", AWS won't store any ports for the
    63  		// rule, but also won't error if the user specifies ports other
    64  		// than '0'. Force the user to make a deliberate '0' port
    65  		// choice when specifying a "-1" protocol, and tell them about
    66  		// AWS's behavior in the error message.
    67  		if *perm.IPProtocol == "-1" && (*perm.FromPort != 0 || *perm.ToPort != 0) {
    68  			return nil, fmt.Errorf(
    69  				"from_port (%d) and to_port (%d) must both be 0 to use the the 'ALL' \"-1\" protocol!",
    70  				*perm.FromPort, *perm.ToPort)
    71  		}
    72  
    73  		var groups []string
    74  		if raw, ok := m["security_groups"]; ok {
    75  			list := raw.(*schema.Set).List()
    76  			for _, v := range list {
    77  				groups = append(groups, v.(string))
    78  			}
    79  		}
    80  		if v, ok := m["self"]; ok && v.(bool) {
    81  			if vpc {
    82  				groups = append(groups, *group.GroupID)
    83  			} else {
    84  				groups = append(groups, *group.GroupName)
    85  			}
    86  		}
    87  
    88  		if len(groups) > 0 {
    89  			perm.UserIDGroupPairs = make([]*ec2.UserIDGroupPair, len(groups))
    90  			for i, name := range groups {
    91  				ownerId, id := "", name
    92  				if items := strings.Split(id, "/"); len(items) > 1 {
    93  					ownerId, id = items[0], items[1]
    94  				}
    95  
    96  				perm.UserIDGroupPairs[i] = &ec2.UserIDGroupPair{
    97  					GroupID: aws.String(id),
    98  					UserID:  aws.String(ownerId),
    99  				}
   100  				if !vpc {
   101  					perm.UserIDGroupPairs[i].GroupID = nil
   102  					perm.UserIDGroupPairs[i].GroupName = aws.String(id)
   103  					perm.UserIDGroupPairs[i].UserID = nil
   104  				}
   105  			}
   106  		}
   107  
   108  		if raw, ok := m["cidr_blocks"]; ok {
   109  			list := raw.([]interface{})
   110  			for _, v := range list {
   111  				perm.IPRanges = append(perm.IPRanges, &ec2.IPRange{CIDRIP: aws.String(v.(string))})
   112  			}
   113  		}
   114  
   115  		perms[i] = &perm
   116  	}
   117  
   118  	return perms, nil
   119  }
   120  
   121  // Takes the result of flatmap.Expand for an array of parameters and
   122  // returns Parameter API compatible objects
   123  func expandParameters(configured []interface{}) ([]*rds.Parameter, error) {
   124  	parameters := make([]*rds.Parameter, 0, len(configured))
   125  
   126  	// Loop over our configured parameters and create
   127  	// an array of aws-sdk-go compatabile objects
   128  	for _, pRaw := range configured {
   129  		data := pRaw.(map[string]interface{})
   130  
   131  		p := &rds.Parameter{
   132  			ApplyMethod:    aws.String(data["apply_method"].(string)),
   133  			ParameterName:  aws.String(data["name"].(string)),
   134  			ParameterValue: aws.String(data["value"].(string)),
   135  		}
   136  
   137  		parameters = append(parameters, p)
   138  	}
   139  
   140  	return parameters, nil
   141  }
   142  
   143  // Flattens a health check into something that flatmap.Flatten()
   144  // can handle
   145  func flattenHealthCheck(check *elb.HealthCheck) []map[string]interface{} {
   146  	result := make([]map[string]interface{}, 0, 1)
   147  
   148  	chk := make(map[string]interface{})
   149  	chk["unhealthy_threshold"] = *check.UnhealthyThreshold
   150  	chk["healthy_threshold"] = *check.HealthyThreshold
   151  	chk["target"] = *check.Target
   152  	chk["timeout"] = *check.Timeout
   153  	chk["interval"] = *check.Interval
   154  
   155  	result = append(result, chk)
   156  
   157  	return result
   158  }
   159  
   160  // Flattens an array of UserSecurityGroups into a []string
   161  func flattenSecurityGroups(list []*ec2.UserIDGroupPair) []string {
   162  	result := make([]string, 0, len(list))
   163  	for _, g := range list {
   164  		result = append(result, *g.GroupID)
   165  	}
   166  	return result
   167  }
   168  
   169  // Flattens an array of Instances into a []string
   170  func flattenInstances(list []*elb.Instance) []string {
   171  	result := make([]string, 0, len(list))
   172  	for _, i := range list {
   173  		result = append(result, *i.InstanceID)
   174  	}
   175  	return result
   176  }
   177  
   178  // Expands an array of String Instance IDs into a []Instances
   179  func expandInstanceString(list []interface{}) []*elb.Instance {
   180  	result := make([]*elb.Instance, 0, len(list))
   181  	for _, i := range list {
   182  		result = append(result, &elb.Instance{InstanceID: aws.String(i.(string))})
   183  	}
   184  	return result
   185  }
   186  
   187  // Flattens an array of Backend Descriptions into a a map of instance_port to policy names.
   188  func flattenBackendPolicies(backends []*elb.BackendServerDescription) map[int64][]string {
   189  	policies := make(map[int64][]string)
   190  	for _, i := range backends {
   191  		for _, p := range i.PolicyNames {
   192  			policies[*i.InstancePort] = append(policies[*i.InstancePort], *p)
   193  		}
   194  		sort.Strings(policies[*i.InstancePort])
   195  	}
   196  	return policies
   197  }
   198  
   199  // Flattens an array of Listeners into a []map[string]interface{}
   200  func flattenListeners(list []*elb.ListenerDescription) []map[string]interface{} {
   201  	result := make([]map[string]interface{}, 0, len(list))
   202  	for _, i := range list {
   203  		l := map[string]interface{}{
   204  			"instance_port":     *i.Listener.InstancePort,
   205  			"instance_protocol": strings.ToLower(*i.Listener.InstanceProtocol),
   206  			"lb_port":           *i.Listener.LoadBalancerPort,
   207  			"lb_protocol":       strings.ToLower(*i.Listener.Protocol),
   208  		}
   209  		// SSLCertificateID is optional, and may be nil
   210  		if i.Listener.SSLCertificateID != nil {
   211  			l["ssl_certificate_id"] = *i.Listener.SSLCertificateID
   212  		}
   213  		result = append(result, l)
   214  	}
   215  	return result
   216  }
   217  
   218  // Flattens an array of Parameters into a []map[string]interface{}
   219  func flattenParameters(list []*rds.Parameter) []map[string]interface{} {
   220  	result := make([]map[string]interface{}, 0, len(list))
   221  	for _, i := range list {
   222  		result = append(result, map[string]interface{}{
   223  			"name":  strings.ToLower(*i.ParameterName),
   224  			"value": strings.ToLower(*i.ParameterValue),
   225  		})
   226  	}
   227  	return result
   228  }
   229  
   230  // Takes the result of flatmap.Expand for an array of strings
   231  // and returns a []string
   232  func expandStringList(configured []interface{}) []*string {
   233  	vs := make([]*string, 0, len(configured))
   234  	for _, v := range configured {
   235  		vs = append(vs, aws.String(v.(string)))
   236  	}
   237  	return vs
   238  }
   239  
   240  //Flattens an array of private ip addresses into a []string, where the elements returned are the IP strings e.g. "192.168.0.0"
   241  func flattenNetworkInterfacesPrivateIPAddesses(dtos []*ec2.NetworkInterfacePrivateIPAddress) []string {
   242  	ips := make([]string, 0, len(dtos))
   243  	for _, v := range dtos {
   244  		ip := *v.PrivateIPAddress
   245  		ips = append(ips, ip)
   246  	}
   247  	return ips
   248  }
   249  
   250  //Flattens security group identifiers into a []string, where the elements returned are the GroupIDs
   251  func flattenGroupIdentifiers(dtos []*ec2.GroupIdentifier) []string {
   252  	ids := make([]string, 0, len(dtos))
   253  	for _, v := range dtos {
   254  		group_id := *v.GroupID
   255  		ids = append(ids, group_id)
   256  	}
   257  	return ids
   258  }
   259  
   260  //Expands an array of IPs into a ec2 Private IP Address Spec
   261  func expandPrivateIPAddesses(ips []interface{}) []*ec2.PrivateIPAddressSpecification {
   262  	dtos := make([]*ec2.PrivateIPAddressSpecification, 0, len(ips))
   263  	for i, v := range ips {
   264  		new_private_ip := &ec2.PrivateIPAddressSpecification{
   265  			PrivateIPAddress: aws.String(v.(string)),
   266  		}
   267  
   268  		new_private_ip.Primary = aws.Boolean(i == 0)
   269  
   270  		dtos = append(dtos, new_private_ip)
   271  	}
   272  	return dtos
   273  }
   274  
   275  //Flattens network interface attachment into a map[string]interface
   276  func flattenAttachment(a *ec2.NetworkInterfaceAttachment) map[string]interface{} {
   277  	att := make(map[string]interface{})
   278  	att["instance"] = *a.InstanceID
   279  	att["device_index"] = *a.DeviceIndex
   280  	att["attachment_id"] = *a.AttachmentID
   281  	return att
   282  }
   283  
   284  func flattenResourceRecords(recs []*route53.ResourceRecord) []string {
   285  	strs := make([]string, 0, len(recs))
   286  	for _, r := range recs {
   287  		if r.Value != nil {
   288  			s := strings.Replace(*r.Value, "\"", "", 2)
   289  			strs = append(strs, s)
   290  		}
   291  	}
   292  	return strs
   293  }
   294  
   295  func expandResourceRecords(recs []interface{}, typeStr string) []*route53.ResourceRecord {
   296  	records := make([]*route53.ResourceRecord, 0, len(recs))
   297  	for _, r := range recs {
   298  		s := r.(string)
   299  		switch typeStr {
   300  		case "TXT":
   301  			str := fmt.Sprintf("\"%s\"", s)
   302  			records = append(records, &route53.ResourceRecord{Value: aws.String(str)})
   303  		default:
   304  			records = append(records, &route53.ResourceRecord{Value: aws.String(s)})
   305  		}
   306  	}
   307  	return records
   308  }