From 6821dbaad3f99cde8e251bdd9dd2e5d3be1ea612 Mon Sep 17 00:00:00 2001 From: Ian Dillon Date: Thu, 11 Jan 2018 15:03:47 -0500 Subject: [PATCH] d/security_groups: Adds aws_security_groups data source. --- aws/data_source_aws_security_groups.go | 98 +++++++++++++++++++ aws/data_source_aws_security_groups_test.go | 99 ++++++++++++++++++++ aws/provider.go | 1 + website/aws.erb | 3 + website/docs/d/security_groups.html.markdown | 52 ++++++++++ 5 files changed, 253 insertions(+) create mode 100644 aws/data_source_aws_security_groups.go create mode 100644 aws/data_source_aws_security_groups_test.go create mode 100644 website/docs/d/security_groups.html.markdown diff --git a/aws/data_source_aws_security_groups.go b/aws/data_source_aws_security_groups.go new file mode 100644 index 000000000000..603d655375e9 --- /dev/null +++ b/aws/data_source_aws_security_groups.go @@ -0,0 +1,98 @@ +package aws + +import ( + "fmt" + "github.com/aws/aws-sdk-go/aws" + "github.com/aws/aws-sdk-go/service/ec2" + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/helper/schema" + "log" +) + +func dataSourceAwsSecurityGroups() *schema.Resource { + return &schema.Resource{ + Read: dataSourceAwsSecurityGroupsRead, + + Schema: map[string]*schema.Schema{ + "filter": dataSourceFiltersSchema(), + "tags": tagsSchemaComputed(), + + "ids": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "vpc_ids": { + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + } +} + +func dataSourceAwsSecurityGroupsRead(d *schema.ResourceData, meta interface{}) error { + conn := meta.(*AWSClient).ec2conn + req := &ec2.DescribeSecurityGroupsInput{} + + filters, filtersOk := d.GetOk("filter") + tags, tagsOk := d.GetOk("tags") + + if !filtersOk && !tagsOk { + return fmt.Errorf("One of filters or tags must be assigned") + } + + if filtersOk { + req.Filters = append(req.Filters, + buildAwsDataSourceFilters(filters.(*schema.Set))...) + } + if tagsOk { + req.Filters = append(req.Filters, buildEC2TagFilterList( + tagsFromMap(tags.(map[string]interface{})), + )...) + } + + log.Printf("[DEBUG] Reading Security Groups with request: %s", req) + + var ids, vpc_ids []string + nextToken := "" + for { + if nextToken != "" { + req.NextToken = aws.String(nextToken) + } + + resp, err := conn.DescribeSecurityGroups(req) + if err != nil { + return err + } + + for _, sg := range resp.SecurityGroups { + ids = append(ids, *sg.GroupId) + vpc_ids = append(vpc_ids, *sg.VpcId) + } + + if resp.NextToken == nil { + break + } + nextToken = *resp.NextToken + } + + if len(ids) < 1 { + return fmt.Errorf("Your query returned no results. Please change your search criteria and try again.") + } + + log.Printf("[DEBUG] Found %d securuity groups via given filter: %s", len(ids), req) + + d.SetId(resource.UniqueId()) + err := d.Set("ids", ids) + if err != nil { + return err + } + + err = d.Set("vpc_ids", vpc_ids) + if err != nil { + return err + } + + return nil +} diff --git a/aws/data_source_aws_security_groups_test.go b/aws/data_source_aws_security_groups_test.go new file mode 100644 index 000000000000..1fa14d6a3b75 --- /dev/null +++ b/aws/data_source_aws_security_groups_test.go @@ -0,0 +1,99 @@ +package aws + +import ( + "fmt" + "github.com/hashicorp/terraform/helper/acctest" + "github.com/hashicorp/terraform/helper/resource" + "testing" +) + +func TestAccDataSourceAwsSecurityGroups_tag(t *testing.T) { + rInt := acctest.RandInt() + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAwsSecurityGroupsConfig_tag(rInt), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.aws_security_groups.by_tag", "ids.#", "3"), + resource.TestCheckResourceAttr("data.aws_security_groups.by_tag", "vpc_ids.#", "3"), + ), + }, + }, + }) +} + +func TestAccDataSourceAwsSecurityGroups_filter(t *testing.T) { + rInt := acctest.RandInt() + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + { + Config: testAccDataSourceAwsSecurityGroupsConfig_filter(rInt), + Check: resource.ComposeTestCheckFunc( + resource.TestCheckResourceAttr("data.aws_security_groups.by_filter", "ids.#", "3"), + resource.TestCheckResourceAttr("data.aws_security_groups.by_filter", "vpc_ids.#", "3"), + ), + }, + }, + }) +} + +func testAccDataSourceAwsSecurityGroupsConfig_tag(rInt int) string { + return fmt.Sprintf(` + resource "aws_vpc" "test_tag" { + cidr_block = "172.16.0.0/16" + tags { + Name = "terraform-testacc-security-group-data-source" + } + } + + resource "aws_security_group" "test" { + count = 3 + vpc_id = "${aws_vpc.test_tag.id}" + name = "tf-%[1]d-${count.index}" + tags { + Seed = "%[1]d" + } + } + + data "aws_security_groups" "by_tag" { + tags { + Seed = "${aws_security_group.test.0.tags["Seed"]}" + } + } +`, rInt) +} + +func testAccDataSourceAwsSecurityGroupsConfig_filter(rInt int) string { + return fmt.Sprintf(` + resource "aws_vpc" "test_filter" { + cidr_block = "172.16.0.0/16" + tags { + Name = "terraform-testacc-security-group-data-source" + } + } + + resource "aws_security_group" "test" { + count = 3 + vpc_id = "${aws_vpc.test_filter.id}" + name = "tf-%[1]d-${count.index}" + tags { + Seed = "%[1]d" + } + } + + data "aws_security_groups" "by_filter" { + filter { + name = "vpc-id" + values = ["${aws_vpc.test_filter.id}"] + } + filter { + name = "group-name" + values = ["tf-${aws_security_group.test.0.tags["Seed"]}-*"] + } + } +`, rInt) +} diff --git a/aws/provider.go b/aws/provider.go index b3b3ac340c2e..a625b64c7355 100644 --- a/aws/provider.go +++ b/aws/provider.go @@ -221,6 +221,7 @@ func Provider() terraform.ResourceProvider { "aws_subnet": dataSourceAwsSubnet(), "aws_subnet_ids": dataSourceAwsSubnetIDs(), "aws_security_group": dataSourceAwsSecurityGroup(), + "aws_security_groups": dataSourceAwsSecurityGroups(), "aws_vpc": dataSourceAwsVpc(), "aws_vpc_endpoint": dataSourceAwsVpcEndpoint(), "aws_vpc_endpoint_service": dataSourceAwsVpcEndpointService(), diff --git a/website/aws.erb b/website/aws.erb index ee605f3fb6fc..7cf651488bbf 100644 --- a/website/aws.erb +++ b/website/aws.erb @@ -203,6 +203,9 @@ > aws_security_group + > + aws_security_group + > aws_sns_topic diff --git a/website/docs/d/security_groups.html.markdown b/website/docs/d/security_groups.html.markdown new file mode 100644 index 000000000000..46adbb2ab33c --- /dev/null +++ b/website/docs/d/security_groups.html.markdown @@ -0,0 +1,52 @@ +--- +layout: "aws" +page_title: "AWS: aws_security_groups" +sidebar_current: "docs-aws-datasource-security-groups" +description: |- + Get information about a set of Security Groups. +--- + +# Data Source: aws_security_groups + +Use this data source to get IDs and VPC membership of Security Groups that are created +outside of Terraform. + +## Example Usage +```hcl +data "aws_security_groups" "test" { + tags { + Application = "k8s", + Environment = "dev" + } +} +``` + +```hcl +data "aws_security_groups" "test" { + filter { + name = "group-name" + values = ["*nodes*"] + } + filter { + name = "vpc-id" + values = ["${var.vpc_id}"] + } +} +``` + +## Argument Reference + +* `tags` - (Optional) A mapping of tags, each pair of which must exactly match for +desired security groups. + +* `filter` - (Optional) One or more name/value pairs to use as filters. There are +several valid keys, for a full reference, check out +[describe-security-groups in the AWS CLI reference][1]. + +## Attributes Reference + +* `ids` - IDs of the matches security groups. +* `vpc_ids` - The VPC IDs of the matched security groups. The data source's tag or filter *will span VPCs* +unless the `vpc-id` filter is also used. + +[1]: https://docs.aws.amazon.com/cli/latest/reference/ec2/describe-security-groups.html