providers/aws: add `self` to ingress [GH-219]

This commit is contained in:
Mitchell Hashimoto 2014-09-30 14:19:16 -07:00
parent 6e02465be7
commit dbc890e401
6 changed files with 120 additions and 36 deletions

View File

@ -25,6 +25,9 @@ IMPROVEMENTS:
* providers/aws: New resource `db_subnet_group`. [GH-295]
* providers/aws: Add `map_public_ip_on_launch` for subnets. [GH-285]
* providers/aws: Add `iam_instance_profile` for instances. [GH-319]
* providers/aws: add `internal` option for ELBs. [GH-303]
* providers/aws: add `self` option for security groups for ingress
rules with self as source. [GH-303]
* providers/google: Support `target_tags` for firewalls. [GH-324]
BUG FIXES:
@ -34,7 +37,6 @@ BUG FIXES:
* core: Plugin loading from CWD works properly.
* providers/aws: autoscaling_group can be launched into a vpc [GH-259]
* providers/aws: not an error when RDS instance is deleted manually. [GH-307]
* providers/aws: add `internal` option for ELBs. [GH-303]
## 0.2.2 (September 9, 2014)

View File

@ -69,6 +69,11 @@ func resourceAwsSecurityGroup() *schema.Resource {
Optional: true,
Elem: &schema.Schema{Type: schema.TypeString},
},
"self": &schema.Schema{
Type: schema.TypeBool,
Optional: true,
},
},
},
Set: resourceAwsSecurityGroupIngressHash,
@ -143,7 +148,6 @@ func resourceAwsSecurityGroupCreate(d *schema.ResourceData, meta interface{}) er
}
d.SetId(createResp.Id)
group := createResp.SecurityGroup
log.Printf("[INFO] Security Group ID: %s", d.Id())
@ -163,21 +167,7 @@ func resourceAwsSecurityGroupCreate(d *schema.ResourceData, meta interface{}) er
d.Id(), err)
}
// Expand the "ingress" array to goamz compat []ec2.IPPerm
ingressRaw := d.Get("ingress")
if ingressRaw == nil {
ingressRaw = new(schema.Set)
}
ingressList := ingressRaw.(*schema.Set).List()
if len(ingressList) > 0 {
ingressRules := expandIPPerms(ingressList)
_, err = ec2conn.AuthorizeSecurityGroup(group, ingressRules)
if err != nil {
return fmt.Errorf("Error authorizing security group ingress rules: %s", err)
}
}
return resourceAwsSecurityGroupRead(d, meta)
return resourceAwsSecurityGroupUpdate(d, meta)
}
func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) error {
@ -206,8 +196,8 @@ func resourceAwsSecurityGroupUpdate(d *schema.ResourceData, meta interface{}) er
os := o.(*schema.Set)
ns := n.(*schema.Set)
remove := expandIPPerms(os.Difference(ns).List())
add := expandIPPerms(ns.Difference(os).List())
remove := expandIPPerms(d.Id(), os.Difference(ns).List())
add := expandIPPerms(d.Id(), ns.Difference(os).List())
// TODO: We need to handle partial state better in the in-between
// in this update.

View File

@ -43,6 +43,51 @@ func TestAccAWSSecurityGroup_normal(t *testing.T) {
})
}
func TestAccAWSSecurityGroup_self(t *testing.T) {
var group ec2.SecurityGroupInfo
checkSelf := func(s *terraform.State) (err error) {
defer func() {
if e := recover(); e != nil {
err = fmt.Errorf("bad: %#v", group)
}
}()
if group.IPPerms[0].SourceGroups[0].Id != group.Id {
return fmt.Errorf("bad: %#v", group)
}
return nil
}
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: testAccCheckAWSSecurityGroupDestroy,
Steps: []resource.TestStep{
resource.TestStep{
Config: testAccAWSSecurityGroupConfigSelf,
Check: resource.ComposeTestCheckFunc(
testAccCheckAWSSecurityGroupExists("aws_security_group.web", &group),
resource.TestCheckResourceAttr(
"aws_security_group.web", "name", "terraform_acceptance_test_example"),
resource.TestCheckResourceAttr(
"aws_security_group.web", "description", "Used in the terraform acceptance tests"),
resource.TestCheckResourceAttr(
"aws_security_group.web", "ingress.0.protocol", "tcp"),
resource.TestCheckResourceAttr(
"aws_security_group.web", "ingress.0.from_port", "80"),
resource.TestCheckResourceAttr(
"aws_security_group.web", "ingress.0.to_port", "8000"),
resource.TestCheckResourceAttr(
"aws_security_group.web", "ingress.0.self", "true"),
checkSelf,
),
},
},
})
}
func TestAccAWSSecurityGroup_vpc(t *testing.T) {
var group ec2.SecurityGroupInfo
@ -215,6 +260,10 @@ func testAccCheckAWSSecurityGroupAttributes(group *ec2.SecurityGroupInfo) resour
return fmt.Errorf("Bad description: %s", group.Description)
}
if len(group.IPPerms) == 0 {
return fmt.Errorf("No IPPerms")
}
// Compare our ingress
if !reflect.DeepEqual(group.IPPerms[0], p) {
return fmt.Errorf(
@ -311,6 +360,20 @@ resource "aws_security_group" "web" {
}
`
const testAccAWSSecurityGroupConfigSelf = `
resource "aws_security_group" "web" {
name = "terraform_acceptance_test_example"
description = "Used in the terraform acceptance tests"
ingress {
protocol = "tcp"
from_port = 80
to_port = 8000
self = true
}
}
`
const testAccAWSSecurityGroupConfigVpc = `
resource "aws_vpc" "foo" {
cidr_block = "10.1.0.0/16"

View File

@ -41,7 +41,7 @@ func expandListeners(configured []interface{}) ([]elb.Listener, error) {
// Takes the result of flatmap.Expand for an array of ingress/egress
// security group rules and returns EC2 API compatible objects
func expandIPPerms(configured []interface{}) []ec2.IPPerm {
func expandIPPerms(id string, configured []interface{}) []ec2.IPPerm {
perms := make([]ec2.IPPerm, len(configured))
for i, mRaw := range configured {
var perm ec2.IPPerm
@ -51,11 +51,20 @@ func expandIPPerms(configured []interface{}) []ec2.IPPerm {
perm.ToPort = m["to_port"].(int)
perm.Protocol = m["protocol"].(string)
var groups []string
if raw, ok := m["security_groups"]; ok {
list := raw.([]interface{})
perm.SourceGroups = make([]ec2.UserSecurityGroup, len(list))
for i, v := range list {
name := v.(string)
for _, v := range list {
groups = append(groups, v.(string))
}
}
if v, ok := m["self"]; ok && v.(bool) {
groups = append(groups, id)
}
if len(groups) > 0 {
perm.SourceGroups = make([]ec2.UserSecurityGroup, len(groups))
for i, name := range groups {
ownerId, id := "", name
if items := strings.Split(id, "/"); len(items) > 1 {
ownerId, id = items[0], items[1]

View File

@ -44,26 +44,44 @@ func Test_expandIPPerms(t *testing.T) {
"foo/sg-22222",
},
},
map[string]interface{}{
"protocol": "icmp",
"from_port": 1,
"to_port": -1,
"self": true,
},
}
perms := expandIPPerms(expanded)
perms := expandIPPerms("foo", expanded)
expected := ec2.IPPerm{
Protocol: "icmp",
FromPort: 1,
ToPort: -1,
SourceIPs: []string{"0.0.0.0/0"},
SourceGroups: []ec2.UserSecurityGroup{
ec2.UserSecurityGroup{
Id: "sg-11111",
expected := []ec2.IPPerm{
ec2.IPPerm{
Protocol: "icmp",
FromPort: 1,
ToPort: -1,
SourceIPs: []string{"0.0.0.0/0"},
SourceGroups: []ec2.UserSecurityGroup{
ec2.UserSecurityGroup{
Id: "sg-11111",
},
ec2.UserSecurityGroup{
OwnerId: "foo",
Id: "sg-22222",
},
},
ec2.UserSecurityGroup{
OwnerId: "foo",
Id: "sg-22222",
},
ec2.IPPerm{
Protocol: "icmp",
FromPort: 1,
ToPort: -1,
SourceGroups: []ec2.UserSecurityGroup{
ec2.UserSecurityGroup{
Id: "foo",
},
},
},
}
if !reflect.DeepEqual(perms[0], expected) {
if !reflect.DeepEqual(perms, expected) {
t.Fatalf(
"Got:\n\n%#v\n\nExpected:\n\n%#v\n",
perms[0],

View File

@ -41,6 +41,8 @@ The `ingress` block supports:
* `from_port` - (Required) The start port.
* `protocol` - (Required) The protocol.
* `security_groups` - (Optional) List of security group IDs. Cannot be used with `cidr_blocks`.
* `self` - (Optional) If true, the security group itself will be added as
a source to this ingress rule.
* `to_port` - (Required) The end range port.
## Attributes Reference