github.com/bradfeehan/terraform@v0.7.0-rc3.0.20170529055808-34b45c5ad841/builtin/providers/aws/import_aws_security_group.go (about) 1 package aws 2 3 import ( 4 "fmt" 5 6 "github.com/aws/aws-sdk-go/service/ec2" 7 "github.com/hashicorp/errwrap" 8 "github.com/hashicorp/terraform/helper/schema" 9 ) 10 11 // Security group import fans out to multiple resources due to the 12 // security group rules. Instead of creating one resource with nested 13 // rules, we use the best practices approach of one resource per rule. 14 func resourceAwsSecurityGroupImportState( 15 d *schema.ResourceData, 16 meta interface{}) ([]*schema.ResourceData, error) { 17 conn := meta.(*AWSClient).ec2conn 18 19 // First query the security group 20 sgRaw, _, err := SGStateRefreshFunc(conn, d.Id())() 21 if err != nil { 22 return nil, err 23 } 24 if sgRaw == nil { 25 return nil, fmt.Errorf("security group not found") 26 } 27 sg := sgRaw.(*ec2.SecurityGroup) 28 29 // Start building our results 30 results := make([]*schema.ResourceData, 1, 31 1+len(sg.IpPermissions)+len(sg.IpPermissionsEgress)) 32 results[0] = d 33 34 // Construct the rules 35 permMap := map[string][]*ec2.IpPermission{ 36 "ingress": sg.IpPermissions, 37 "egress": sg.IpPermissionsEgress, 38 } 39 for ruleType, perms := range permMap { 40 for _, perm := range perms { 41 ds, err := resourceAwsSecurityGroupImportStatePerm(sg, ruleType, perm) 42 if err != nil { 43 return nil, err 44 } 45 results = append(results, ds...) 46 } 47 } 48 49 return results, nil 50 } 51 52 func resourceAwsSecurityGroupImportStatePerm(sg *ec2.SecurityGroup, ruleType string, perm *ec2.IpPermission) ([]*schema.ResourceData, error) { 53 /* 54 Create a seperate Security Group Rule for: 55 * The collection of IpRanges (cidr_blocks) 56 * The collection of Ipv6Ranges (ipv6_cidr_blocks) 57 * Each individual UserIdGroupPair (source_security_group_id) 58 59 If, for example, a security group has rules for: 60 * 2 IpRanges 61 * 2 Ipv6Ranges 62 * 2 UserIdGroupPairs 63 64 This would generate 4 security group rules: 65 * 1 for the collection of IpRanges 66 * 1 for the collection of Ipv6Ranges 67 * 1 for the first UserIdGroupPair 68 * 1 for the second UserIdGroupPair 69 */ 70 var result []*schema.ResourceData 71 72 if perm.IpRanges != nil { 73 p := &ec2.IpPermission{ 74 FromPort: perm.FromPort, 75 IpProtocol: perm.IpProtocol, 76 PrefixListIds: perm.PrefixListIds, 77 ToPort: perm.ToPort, 78 IpRanges: perm.IpRanges, 79 } 80 81 r, err := resourceAwsSecurityGroupImportStatePermPair(sg, ruleType, p) 82 if err != nil { 83 return nil, err 84 } 85 result = append(result, r) 86 } 87 88 if perm.Ipv6Ranges != nil { 89 p := &ec2.IpPermission{ 90 FromPort: perm.FromPort, 91 IpProtocol: perm.IpProtocol, 92 PrefixListIds: perm.PrefixListIds, 93 ToPort: perm.ToPort, 94 Ipv6Ranges: perm.Ipv6Ranges, 95 } 96 97 r, err := resourceAwsSecurityGroupImportStatePermPair(sg, ruleType, p) 98 if err != nil { 99 return nil, err 100 } 101 result = append(result, r) 102 } 103 104 if len(perm.UserIdGroupPairs) > 0 { 105 for _, pair := range perm.UserIdGroupPairs { 106 p := &ec2.IpPermission{ 107 FromPort: perm.FromPort, 108 IpProtocol: perm.IpProtocol, 109 PrefixListIds: perm.PrefixListIds, 110 ToPort: perm.ToPort, 111 UserIdGroupPairs: []*ec2.UserIdGroupPair{pair}, 112 } 113 114 r, err := resourceAwsSecurityGroupImportStatePermPair(sg, ruleType, p) 115 if err != nil { 116 return nil, err 117 } 118 result = append(result, r) 119 } 120 } 121 122 if len(result) == 0 && len(perm.PrefixListIds) > 0 { 123 p := &ec2.IpPermission{ 124 FromPort: perm.FromPort, 125 IpProtocol: perm.IpProtocol, 126 PrefixListIds: perm.PrefixListIds, 127 ToPort: perm.ToPort, 128 } 129 130 r, err := resourceAwsSecurityGroupImportStatePermPair(sg, ruleType, p) 131 if err != nil { 132 return nil, err 133 } 134 result = append(result, r) 135 } 136 137 return result, nil 138 } 139 140 func resourceAwsSecurityGroupImportStatePermPair(sg *ec2.SecurityGroup, ruleType string, perm *ec2.IpPermission) (*schema.ResourceData, error) { 141 // Construct the rule. We do this by populating the absolute 142 // minimum necessary for Refresh on the rule to work. This 143 // happens to be a lot of fields since they're almost all needed 144 // for de-dupping. 145 sgId := sg.GroupId 146 id := ipPermissionIDHash(*sgId, ruleType, perm) 147 ruleResource := resourceAwsSecurityGroupRule() 148 d := ruleResource.Data(nil) 149 d.SetId(id) 150 d.SetType("aws_security_group_rule") 151 d.Set("security_group_id", sgId) 152 d.Set("type", ruleType) 153 154 // 'self' is false by default. Below, we range over the group ids and set true 155 // if the parent sg id is found 156 d.Set("self", false) 157 158 if len(perm.UserIdGroupPairs) > 0 { 159 s := perm.UserIdGroupPairs[0] 160 161 // Check for Pair that is the same as the Security Group, to denote self. 162 // Otherwise, mark the group id in source_security_group_id 163 isVPC := sg.VpcId != nil && *sg.VpcId != "" 164 if isVPC { 165 if *s.GroupId == *sg.GroupId { 166 d.Set("self", true) 167 // prune the self reference from the UserIdGroupPairs, so we don't 168 // have duplicate sg ids (both self and in source_security_group_id) 169 perm.UserIdGroupPairs = append(perm.UserIdGroupPairs[:0], perm.UserIdGroupPairs[0+1:]...) 170 } 171 } else { 172 if *s.GroupName == *sg.GroupName { 173 d.Set("self", true) 174 // prune the self reference from the UserIdGroupPairs, so we don't 175 // have duplicate sg ids (both self and in source_security_group_id) 176 perm.UserIdGroupPairs = append(perm.UserIdGroupPairs[:0], perm.UserIdGroupPairs[0+1:]...) 177 } 178 } 179 } 180 181 if err := setFromIPPerm(d, sg, perm); err != nil { 182 return nil, errwrap.Wrapf("Error importing AWS Security Group: {{err}}", err) 183 } 184 185 return d, nil 186 }