From 13ea0a01c61416795b0497cee2b9dfba30438e6a Mon Sep 17 00:00:00 2001 From: Joern Barthel Date: Thu, 4 Aug 2016 19:19:43 +0200 Subject: [PATCH 1/9] Added IP ranges from Fastly --- .../providers/fastly/data_source_ip_ranges.go | 68 +++++++++++++++++++ builtin/providers/fastly/provider.go | 3 + 2 files changed, 71 insertions(+) create mode 100644 builtin/providers/fastly/data_source_ip_ranges.go diff --git a/builtin/providers/fastly/data_source_ip_ranges.go b/builtin/providers/fastly/data_source_ip_ranges.go new file mode 100644 index 0000000000..bc01cd232a --- /dev/null +++ b/builtin/providers/fastly/data_source_ip_ranges.go @@ -0,0 +1,68 @@ +package fastly + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "sort" + "time" + + "github.com/hashicorp/go-cleanhttp" + "github.com/hashicorp/terraform/helper/schema" +) + +type dataSourceFastlyIPRangesResult struct { + Addresses []string +} + +func dataSourceFastlyIPRanges() *schema.Resource { + return &schema.Resource{ + Read: dataSourceFastlyIPRangesRead, + + Schema: map[string]*schema.Schema{ + "blocks": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + }, + } +} + +func dataSourceFastlyIPRangesRead(d *schema.ResourceData, meta interface{}) error { + + conn := cleanhttp.DefaultClient() + + log.Printf("[DEBUG] Reading IP ranges") + d.SetId(time.Now().UTC().String()) + + res, err := conn.Get("https://api.fastly.com/public-ip-list") + + if err != nil { + return fmt.Errorf("Error listing IP ranges: %s", err) + } + + defer res.Body.Close() + + data, err := ioutil.ReadAll(res.Body) + + if err != nil { + return fmt.Errorf("Error reading response body: %s", err) + } + + result := new(dataSourceFastlyIPRangesResult) + + if err := json.Unmarshal(data, result); err != nil { + return fmt.Errorf("Error parsing result: %s", err) + } + + sort.Strings(result.Addresses) + + if err := d.Set("blocks", result.Addresses); err != nil { + return fmt.Errorf("Error setting ip ranges: %s", err) + } + + return nil + +} diff --git a/builtin/providers/fastly/provider.go b/builtin/providers/fastly/provider.go index f68c6705be..eee4be8e83 100644 --- a/builtin/providers/fastly/provider.go +++ b/builtin/providers/fastly/provider.go @@ -18,6 +18,9 @@ func Provider() terraform.ResourceProvider { Description: "Fastly API Key from https://app.fastly.com/#account", }, }, + DataSourcesMap: map[string]*schema.Resource{ + "fastly_ip_ranges": dataSourceFastlyIPRanges(), + }, ResourcesMap: map[string]*schema.Resource{ "fastly_service_v1": resourceServiceV1(), }, From 8accef2c27e14d90658730b82d52cfe13875e27b Mon Sep 17 00:00:00 2001 From: Joern Barthel Date: Thu, 4 Aug 2016 19:20:14 +0200 Subject: [PATCH 2/9] Added IP ranges from AWS --- .../aws/data_source_aws_ip_ranges.go | 128 ++++++++++++++++++ builtin/providers/aws/provider.go | 1 + 2 files changed, 129 insertions(+) create mode 100644 builtin/providers/aws/data_source_aws_ip_ranges.go diff --git a/builtin/providers/aws/data_source_aws_ip_ranges.go b/builtin/providers/aws/data_source_aws_ip_ranges.go new file mode 100644 index 0000000000..c530d981df --- /dev/null +++ b/builtin/providers/aws/data_source_aws_ip_ranges.go @@ -0,0 +1,128 @@ +package aws + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "log" + "sort" + "strings" + "time" + + "github.com/hashicorp/go-cleanhttp" + "github.com/hashicorp/terraform/helper/schema" +) + +type dataSourceAwsIPRangesResult struct { + CreateDate string + Prefixes []dataSourceAwsIPRangesPrefix + SyncToken string +} + +type dataSourceAwsIPRangesPrefix struct { + IpPrefix string `json:"ip_prefix"` + Region string + Service string +} + +func dataSourceAwsIPRanges() *schema.Resource { + return &schema.Resource{ + Read: dataSourceAwsIPRangesRead, + + Schema: map[string]*schema.Schema{ + "blocks": &schema.Schema{ + Type: schema.TypeList, + Computed: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "create_date": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + "regions": &schema.Schema{ + Type: schema.TypeSet, + Elem: &schema.Schema{Type: schema.TypeString}, + Optional: true, + }, + "services": &schema.Schema{ + Type: schema.TypeSet, + Required: true, + Elem: &schema.Schema{Type: schema.TypeString}, + }, + "sync_token": &schema.Schema{ + Type: schema.TypeString, + Computed: true, + }, + }, + } +} + +func dataSourceAwsIPRangesRead(d *schema.ResourceData, meta interface{}) error { + + conn := cleanhttp.DefaultClient() + + log.Printf("[DEBUG] Reading IP ranges") + d.SetId(time.Now().UTC().String()) + + res, err := conn.Get("https://ip-ranges.amazonaws.com/ip-ranges.json") + + if err != nil { + return fmt.Errorf("Error listing IP ranges: %s", err) + } + + defer res.Body.Close() + + data, err := ioutil.ReadAll(res.Body) + + if err != nil { + return fmt.Errorf("Error reading response body: %s", err) + } + + result := new(dataSourceAwsIPRangesResult) + + if err := json.Unmarshal(data, result); err != nil { + return fmt.Errorf("Error parsing result: %s", err) + } + + if err := d.Set("create_date", result.CreateDate); err != nil { + return fmt.Errorf("Error setting create date: %s", err) + } + + if err := d.Set("sync_token", result.SyncToken); err != nil { + return fmt.Errorf("Error setting sync token: %s", err) + } + + var ( + regions = d.Get("regions").(*schema.Set) + services = d.Get("services").(*schema.Set) + noRegionFilter = regions.Len() == 0 + noServiceFilter = services.Len() == 0 + prefixes []string + ) + + for _, e := range result.Prefixes { + + var ( + matchRegion = noRegionFilter || regions.Contains(strings.ToLower(e.Region)) + matchService = noServiceFilter || services.Contains(strings.ToLower(e.Service)) + ) + + if matchRegion && matchService { + prefixes = append(prefixes, e.IpPrefix) + } + + } + + if len(prefixes) == 0 { + log.Printf("[WARN] No ip ranges result from filters") + } + + sort.Strings(prefixes) + + if err := d.Set("blocks", prefixes); err != nil { + return fmt.Errorf("Error setting ip ranges: %s", err) + } + + return nil + +} diff --git a/builtin/providers/aws/provider.go b/builtin/providers/aws/provider.go index 69e264dd92..e15931225c 100644 --- a/builtin/providers/aws/provider.go +++ b/builtin/providers/aws/provider.go @@ -114,6 +114,7 @@ func Provider() terraform.ResourceProvider { "aws_ami": dataSourceAwsAmi(), "aws_availability_zones": dataSourceAwsAvailabilityZones(), "aws_iam_policy_document": dataSourceAwsIamPolicyDocument(), + "aws_ip_ranges": dataSourceAwsIPRanges(), "aws_s3_bucket_object": dataSourceAwsS3BucketObject(), "aws_ecs_container_definition": dataSourceAwsEcsContainerDefinition(), }, From e21203a36973ef3dd7ec47b8202da6ea96a3e1f0 Mon Sep 17 00:00:00 2001 From: Joern Barthel Date: Fri, 5 Aug 2016 17:08:22 +0200 Subject: [PATCH 3/9] Changed sync token to int and use it as id. --- .../providers/aws/data_source_aws_ip_ranges.go | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/builtin/providers/aws/data_source_aws_ip_ranges.go b/builtin/providers/aws/data_source_aws_ip_ranges.go index c530d981df..c71eb0a723 100644 --- a/builtin/providers/aws/data_source_aws_ip_ranges.go +++ b/builtin/providers/aws/data_source_aws_ip_ranges.go @@ -6,8 +6,8 @@ import ( "io/ioutil" "log" "sort" + "strconv" "strings" - "time" "github.com/hashicorp/go-cleanhttp" "github.com/hashicorp/terraform/helper/schema" @@ -50,7 +50,7 @@ func dataSourceAwsIPRanges() *schema.Resource { Elem: &schema.Schema{Type: schema.TypeString}, }, "sync_token": &schema.Schema{ - Type: schema.TypeString, + Type: schema.TypeInt, Computed: true, }, }, @@ -62,7 +62,6 @@ func dataSourceAwsIPRangesRead(d *schema.ResourceData, meta interface{}) error { conn := cleanhttp.DefaultClient() log.Printf("[DEBUG] Reading IP ranges") - d.SetId(time.Now().UTC().String()) res, err := conn.Get("https://ip-ranges.amazonaws.com/ip-ranges.json") @@ -88,7 +87,15 @@ func dataSourceAwsIPRangesRead(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("Error setting create date: %s", err) } - if err := d.Set("sync_token", result.SyncToken); err != nil { + syncToken, err := strconv.Atoi(result.SyncToken) + + if err != nil { + return fmt.Errorf("Error while converting sync token: %s", err) + } + + d.SetId(result.SyncToken) + + if err := d.Set("sync_token", syncToken); err != nil { return fmt.Errorf("Error setting sync token: %s", err) } From 67b4b4cbfb453ceba45d39e9c43e187448843d98 Mon Sep 17 00:00:00 2001 From: Joern Barthel Date: Fri, 5 Aug 2016 17:08:50 +0200 Subject: [PATCH 4/9] Use content as id. --- builtin/providers/fastly/data_source_ip_ranges.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/builtin/providers/fastly/data_source_ip_ranges.go b/builtin/providers/fastly/data_source_ip_ranges.go index bc01cd232a..080ac081b2 100644 --- a/builtin/providers/fastly/data_source_ip_ranges.go +++ b/builtin/providers/fastly/data_source_ip_ranges.go @@ -6,9 +6,10 @@ import ( "io/ioutil" "log" "sort" - "time" + "strconv" "github.com/hashicorp/go-cleanhttp" + "github.com/hashicorp/terraform/helper/hashcode" "github.com/hashicorp/terraform/helper/schema" ) @@ -35,7 +36,6 @@ func dataSourceFastlyIPRangesRead(d *schema.ResourceData, meta interface{}) erro conn := cleanhttp.DefaultClient() log.Printf("[DEBUG] Reading IP ranges") - d.SetId(time.Now().UTC().String()) res, err := conn.Get("https://api.fastly.com/public-ip-list") @@ -51,6 +51,8 @@ func dataSourceFastlyIPRangesRead(d *schema.ResourceData, meta interface{}) erro return fmt.Errorf("Error reading response body: %s", err) } + d.SetId(strconv.Itoa(hashcode.String(string(data)))) + result := new(dataSourceFastlyIPRangesResult) if err := json.Unmarshal(data, result); err != nil { From 2caae49a3b773217e8efff95fcf2345031e947dc Mon Sep 17 00:00:00 2001 From: Joern Barthel Date: Fri, 5 Aug 2016 17:09:12 +0200 Subject: [PATCH 5/9] Fail if filter yields no results. --- builtin/providers/aws/data_source_aws_ip_ranges.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/builtin/providers/aws/data_source_aws_ip_ranges.go b/builtin/providers/aws/data_source_aws_ip_ranges.go index c71eb0a723..b03fc36329 100644 --- a/builtin/providers/aws/data_source_aws_ip_ranges.go +++ b/builtin/providers/aws/data_source_aws_ip_ranges.go @@ -121,7 +121,7 @@ func dataSourceAwsIPRangesRead(d *schema.ResourceData, meta interface{}) error { } if len(prefixes) == 0 { - log.Printf("[WARN] No ip ranges result from filters") + return fmt.Errorf(" No IP ranges result from filters") } sort.Strings(prefixes) From 9f565285d1eb281ca00b62ca17c8ad4e3e69db77 Mon Sep 17 00:00:00 2001 From: Joern Barthel Date: Fri, 5 Aug 2016 17:12:28 +0200 Subject: [PATCH 6/9] Renamed blocks to cidr_blocks. --- builtin/providers/aws/data_source_aws_ip_ranges.go | 4 ++-- builtin/providers/fastly/data_source_ip_ranges.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/builtin/providers/aws/data_source_aws_ip_ranges.go b/builtin/providers/aws/data_source_aws_ip_ranges.go index b03fc36329..799af0ca76 100644 --- a/builtin/providers/aws/data_source_aws_ip_ranges.go +++ b/builtin/providers/aws/data_source_aws_ip_ranges.go @@ -30,7 +30,7 @@ func dataSourceAwsIPRanges() *schema.Resource { Read: dataSourceAwsIPRangesRead, Schema: map[string]*schema.Schema{ - "blocks": &schema.Schema{ + "cidr_blocks": &schema.Schema{ Type: schema.TypeList, Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, @@ -126,7 +126,7 @@ func dataSourceAwsIPRangesRead(d *schema.ResourceData, meta interface{}) error { sort.Strings(prefixes) - if err := d.Set("blocks", prefixes); err != nil { + if err := d.Set("cidr_blocks", prefixes); err != nil { return fmt.Errorf("Error setting ip ranges: %s", err) } diff --git a/builtin/providers/fastly/data_source_ip_ranges.go b/builtin/providers/fastly/data_source_ip_ranges.go index 080ac081b2..cc418465c4 100644 --- a/builtin/providers/fastly/data_source_ip_ranges.go +++ b/builtin/providers/fastly/data_source_ip_ranges.go @@ -22,7 +22,7 @@ func dataSourceFastlyIPRanges() *schema.Resource { Read: dataSourceFastlyIPRangesRead, Schema: map[string]*schema.Schema{ - "blocks": &schema.Schema{ + "cidr_blocks": &schema.Schema{ Type: schema.TypeList, Computed: true, Elem: &schema.Schema{Type: schema.TypeString}, @@ -61,7 +61,7 @@ func dataSourceFastlyIPRangesRead(d *schema.ResourceData, meta interface{}) erro sort.Strings(result.Addresses) - if err := d.Set("blocks", result.Addresses); err != nil { + if err := d.Set("cidr_blocks", result.Addresses); err != nil { return fmt.Errorf("Error setting ip ranges: %s", err) } From 67bf13fccf21d7c4411b69761d58fd53c222631d Mon Sep 17 00:00:00 2001 From: Joern Barthel Date: Fri, 5 Aug 2016 17:12:46 +0200 Subject: [PATCH 7/9] Added documentation. --- .../providers/aws/d/ip_ranges.html.markdown | 59 +++++++++++++++++++ .../fastly/d/ip_ranges.html.markdown | 37 ++++++++++++ website/source/layouts/aws.erb | 3 + website/source/layouts/fastly.erb | 9 +++ 4 files changed, 108 insertions(+) create mode 100644 website/source/docs/providers/aws/d/ip_ranges.html.markdown create mode 100644 website/source/docs/providers/fastly/d/ip_ranges.html.markdown diff --git a/website/source/docs/providers/aws/d/ip_ranges.html.markdown b/website/source/docs/providers/aws/d/ip_ranges.html.markdown new file mode 100644 index 0000000000..f7fe90a8cd --- /dev/null +++ b/website/source/docs/providers/aws/d/ip_ranges.html.markdown @@ -0,0 +1,59 @@ +--- +layout: "aws" +page_title: "AWS: aws_ip_ranges" +sidebar_current: "docs-aws-datasource-ip_ranges" +description: |- + Get information on AWS IP ranges. +--- + +# aws\_ip_ranges + +Use this data source to get the [IP ranges][1] of various AWS products and services. + +## Example Usage + +``` +data "aws_ip_ranges" "european_ec2" { + regions = [ "eu-west-1", "eu-central-1" ] + services = [ "ec2" ] +} + +resource "aws_security_group" "from_europe" { + + name = "from_europe" + + ingress { + from_port = "443" + to_port = "443" + protocol = "tcp" + cidr_blocks = [ "${data.aws_ip_ranges.european_ec2.blocks}" ] + } + + tags { + CreateDate = "${data.aws_ip_ranges.european_ec2.create_date}" + SyncToken = "${data.aws_ip_ranges.european_ec2.sync_token}" + } + +} +``` + +## Argument Reference + +* `regions` - (Optional) Filter IP ranges by regions (or include all regions, if +omitted). Valid items are `global` (for `cloudfront`) as well as all AWS regions +(e.g. `eu-central-1`) + +* `services` - (Required) Filter IP ranges by services. Valid items are `amazon` +(for amazon.com), `cloudfront`, `ec2`, `route53` and `route53_healthchecks`. + +~> **NOTE:** If the specified combination of regions and services does not yield any +CIDR blocks, Terraform will fail. + +## Attributes Reference + +* `cidr_blocks` - The lexically ordered list of CIDR blocks. +* `create_date` - The publication time of the IP ranges (e.g. `2016-08-03-23-46-05`). +* `sync_token` - The publication time of the IP ranges, in Unix epoch time format + (e.g. `1470267965`). + +[1]: http://docs.aws.amazon.com/general/latest/gr/aws-ip-ranges.html diff --git a/website/source/docs/providers/fastly/d/ip_ranges.html.markdown b/website/source/docs/providers/fastly/d/ip_ranges.html.markdown new file mode 100644 index 0000000000..75cd59b009 --- /dev/null +++ b/website/source/docs/providers/fastly/d/ip_ranges.html.markdown @@ -0,0 +1,37 @@ +--- +layout: "fastly" +page_title: "Fastly: fastly_ip_ranges" +sidebar_current: "docs-fastly-datasource-ip_ranges" +description: |- + Get information on Fastly IP ranges. +--- + +# fastly\_ip_ranges + +Use this data source to get the [IP ranges][1] of Fastly edge nodes. + +## Example Usage + +``` +data "fastly_ip_ranges" "fastly" { +} + +resource "aws_security_group" "from_fastly" { + + name = "from_fastly" + + ingress { + from_port = "443" + to_port = "443" + protocol = "tcp" + cidr_blocks = [ "${data.fastly_ip_ranges.fastly.cidr_blocks}" ] + } + +} +``` + +## Attributes Reference + +* `cidr_blocks` - The lexically ordered list of CIDR blocks. + +[1]: https://docs.fastly.com/guides/securing-communications/accessing-fastlys-ip-ranges diff --git a/website/source/layouts/aws.erb b/website/source/layouts/aws.erb index c4765aafed..ed7e12a0d7 100644 --- a/website/source/layouts/aws.erb +++ b/website/source/layouts/aws.erb @@ -25,6 +25,9 @@ > aws_iam_policy_document + > + aws_ip_ranges + > aws_s3_bucket_object diff --git a/website/source/layouts/fastly.erb b/website/source/layouts/fastly.erb index 1958464a01..b1cd59d347 100644 --- a/website/source/layouts/fastly.erb +++ b/website/source/layouts/fastly.erb @@ -10,6 +10,15 @@ Fastly Provider + > + Data Sources + + + > Resources From d0278ecf0f69928ff55173e584dfd113e99bc970 Mon Sep 17 00:00:00 2001 From: Joern Barthel Date: Tue, 9 Aug 2016 14:42:09 +0200 Subject: [PATCH 8/9] =?UTF-8?q?Normalize=20sets,=20don=E2=80=99t=20check?= =?UTF-8?q?=20for=20missing=20services.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aws/data_source_aws_ip_ranges.go | 28 +++++++++++++++---- 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/builtin/providers/aws/data_source_aws_ip_ranges.go b/builtin/providers/aws/data_source_aws_ip_ranges.go index 799af0ca76..32e9d89883 100644 --- a/builtin/providers/aws/data_source_aws_ip_ranges.go +++ b/builtin/providers/aws/data_source_aws_ip_ranges.go @@ -99,19 +99,35 @@ func dataSourceAwsIPRangesRead(d *schema.ResourceData, meta interface{}) error { return fmt.Errorf("Error setting sync token: %s", err) } + get := func(key string) *schema.Set { + + set := d.Get(key).(*schema.Set) + + for _, e := range set.List() { + + s := e.(string) + + set.Remove(s) + set.Add(strings.ToLower(s)) + + } + + return set + + } + var ( - regions = d.Get("regions").(*schema.Set) - services = d.Get("services").(*schema.Set) - noRegionFilter = regions.Len() == 0 - noServiceFilter = services.Len() == 0 - prefixes []string + regions = get("regions") + services = get("services") + noRegionFilter = regions.Len() == 0 + prefixes []string ) for _, e := range result.Prefixes { var ( matchRegion = noRegionFilter || regions.Contains(strings.ToLower(e.Region)) - matchService = noServiceFilter || services.Contains(strings.ToLower(e.Service)) + matchService = services.Contains(strings.ToLower(e.Service)) ) if matchRegion && matchService { From 8ea400b442828bc1b461384f1babba118853ffd2 Mon Sep 17 00:00:00 2001 From: Joern Barthel Date: Tue, 9 Aug 2016 14:42:19 +0200 Subject: [PATCH 9/9] Added tests. --- .../aws/data_source_aws_ip_ranges_test.go | 128 ++++++++++++++++++ .../fastly/data_source_ip_ranges_test.go | 73 ++++++++++ 2 files changed, 201 insertions(+) create mode 100644 builtin/providers/aws/data_source_aws_ip_ranges_test.go create mode 100644 builtin/providers/fastly/data_source_ip_ranges_test.go diff --git a/builtin/providers/aws/data_source_aws_ip_ranges_test.go b/builtin/providers/aws/data_source_aws_ip_ranges_test.go new file mode 100644 index 0000000000..5e8f4b13da --- /dev/null +++ b/builtin/providers/aws/data_source_aws_ip_ranges_test.go @@ -0,0 +1,128 @@ +package aws + +import ( + "fmt" + "net" + "regexp" + "sort" + "strconv" + "testing" + "time" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccAWSIPRanges(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccAWSIPRangesConfig, + Check: resource.ComposeTestCheckFunc( + testAccAWSIPRanges("data.aws_ip_ranges.some"), + ), + }, + }, + }) +} + +func testAccAWSIPRanges(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + + r := s.RootModule().Resources[n] + a := r.Primary.Attributes + + var ( + cidrBlockSize int + createDate time.Time + err error + syncToken int + ) + + if cidrBlockSize, err = strconv.Atoi(a["cidr_blocks.#"]); err != nil { + return err + } + + if cidrBlockSize < 10 { + return fmt.Errorf("cidr_blocks for eu-west-1 seem suspiciously low: %d", cidrBlockSize) + } + + if createDate, err = time.Parse("2006-01-02-15-04-05", a["create_date"]); err != nil { + return err + } + + if syncToken, err = strconv.Atoi(a["sync_token"]); err != nil { + return err + } + + if syncToken != int(createDate.Unix()) { + return fmt.Errorf("sync_token %d does not match create_date %s", syncToken, createDate) + } + + var cidrBlocks sort.StringSlice = make([]string, cidrBlockSize) + + for i := range make([]string, cidrBlockSize) { + + block := a[fmt.Sprintf("cidr_blocks.%d", i)] + + if _, _, err := net.ParseCIDR(block); err != nil { + return fmt.Errorf("malformed CIDR block %s: %s", block, err) + } + + cidrBlocks[i] = block + + } + + if !sort.IsSorted(cidrBlocks) { + return fmt.Errorf("unexpected order of cidr_blocks: %s", cidrBlocks) + } + + var ( + regionMember = regexp.MustCompile(`regions\.\d+`) + regions, services int + serviceMember = regexp.MustCompile(`services\.\d+`) + ) + + for k, v := range a { + + if regionMember.MatchString(k) { + + if !(v == "eu-west-1" || v == "EU-central-1") { + return fmt.Errorf("unexpected region %s", v) + } + + regions = regions + 1 + + } + + if serviceMember.MatchString(k) { + + if v != "EC2" { + return fmt.Errorf("unexpected service %s", v) + } + + services = services + 1 + } + + } + + if regions != 2 { + return fmt.Errorf("unexpected number of regions: %d", regions) + } + + if services != 1 { + return fmt.Errorf("unexpected number of services: %d", services) + } + + return nil + } +} + +const testAccAWSIPRangesConfig = ` +data "aws_ip_ranges" "some" { + regions = [ "eu-west-1", "EU-central-1" ] + services = [ "EC2" ] +} +` diff --git a/builtin/providers/fastly/data_source_ip_ranges_test.go b/builtin/providers/fastly/data_source_ip_ranges_test.go new file mode 100644 index 0000000000..26e4d8f566 --- /dev/null +++ b/builtin/providers/fastly/data_source_ip_ranges_test.go @@ -0,0 +1,73 @@ +package fastly + +import ( + "fmt" + "net" + "sort" + "strconv" + "testing" + + "github.com/hashicorp/terraform/helper/resource" + "github.com/hashicorp/terraform/terraform" +) + +func TestAccFastlyIPRanges(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + Steps: []resource.TestStep{ + resource.TestStep{ + Config: testAccFastlyIPRangesConfig, + Check: resource.ComposeTestCheckFunc( + testAccFastlyIPRanges("data.fastly_ip_ranges.some"), + ), + }, + }, + }) +} + +func testAccFastlyIPRanges(n string) resource.TestCheckFunc { + return func(s *terraform.State) error { + + r := s.RootModule().Resources[n] + a := r.Primary.Attributes + + var ( + cidrBlockSize int + err error + ) + + if cidrBlockSize, err = strconv.Atoi(a["cidr_blocks.#"]); err != nil { + return err + } + + if cidrBlockSize < 10 { + return fmt.Errorf("cidr_blocks seem suspiciously low: %d", cidrBlockSize) + } + + var cidrBlocks sort.StringSlice = make([]string, cidrBlockSize) + + for i := range make([]string, cidrBlockSize) { + + block := a[fmt.Sprintf("cidr_blocks.%d", i)] + + if _, _, err := net.ParseCIDR(block); err != nil { + return fmt.Errorf("malformed CIDR block %s: %s", block, err) + } + + cidrBlocks[i] = block + + } + + if !sort.IsSorted(cidrBlocks) { + return fmt.Errorf("unexpected order of cidr_blocks: %s", cidrBlocks) + } + + return nil + } +} + +const testAccFastlyIPRangesConfig = ` +data "fastly_ip_ranges" "some" { +} +`