mirror of
https://github.com/opentofu/opentofu.git
synced 2025-02-25 18:45:20 -06:00
Merge #7984: Data sources for AWS and Fastly IP address ranges
This commit is contained in:
commit
c6e8662838
@ -6,6 +6,8 @@ FEATURES:
|
||||
* **New Resource:** `aws_load_balancer_policy` [GH-7458]
|
||||
* **New Resource:** `aws_load_balancer_backend_server_policy` [GH-7458]
|
||||
* **New Resource:** `aws_load_balancer_listener_policy` [GH-7458]
|
||||
* **New Data Source:** `aws_ip_ranges` [GH-7984]
|
||||
* **New Data Source:** `fastly_ip_ranges` [GH-7984]
|
||||
|
||||
IMPROVEMENTS
|
||||
* provider/aws: Introduce `aws_elasticsearch_domain` `elasticsearch_version` field (to specify ES version) [GH-7860]
|
||||
|
151
builtin/providers/aws/data_source_aws_ip_ranges.go
Normal file
151
builtin/providers/aws/data_source_aws_ip_ranges.go
Normal file
@ -0,0 +1,151 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"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{
|
||||
"cidr_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.TypeInt,
|
||||
Computed: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func dataSourceAwsIPRangesRead(d *schema.ResourceData, meta interface{}) error {
|
||||
|
||||
conn := cleanhttp.DefaultClient()
|
||||
|
||||
log.Printf("[DEBUG] Reading IP ranges")
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
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 = 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 = services.Contains(strings.ToLower(e.Service))
|
||||
)
|
||||
|
||||
if matchRegion && matchService {
|
||||
prefixes = append(prefixes, e.IpPrefix)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if len(prefixes) == 0 {
|
||||
return fmt.Errorf(" No IP ranges result from filters")
|
||||
}
|
||||
|
||||
sort.Strings(prefixes)
|
||||
|
||||
if err := d.Set("cidr_blocks", prefixes); err != nil {
|
||||
return fmt.Errorf("Error setting ip ranges: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
128
builtin/providers/aws/data_source_aws_ip_ranges_test.go
Normal file
128
builtin/providers/aws/data_source_aws_ip_ranges_test.go
Normal file
@ -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" ]
|
||||
}
|
||||
`
|
@ -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(),
|
||||
},
|
||||
|
70
builtin/providers/fastly/data_source_ip_ranges.go
Normal file
70
builtin/providers/fastly/data_source_ip_ranges.go
Normal file
@ -0,0 +1,70 @@
|
||||
package fastly
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"sort"
|
||||
"strconv"
|
||||
|
||||
"github.com/hashicorp/go-cleanhttp"
|
||||
"github.com/hashicorp/terraform/helper/hashcode"
|
||||
"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{
|
||||
"cidr_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")
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
d.SetId(strconv.Itoa(hashcode.String(string(data))))
|
||||
|
||||
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("cidr_blocks", result.Addresses); err != nil {
|
||||
return fmt.Errorf("Error setting ip ranges: %s", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
}
|
73
builtin/providers/fastly/data_source_ip_ranges_test.go
Normal file
73
builtin/providers/fastly/data_source_ip_ranges_test.go
Normal file
@ -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" {
|
||||
}
|
||||
`
|
@ -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(),
|
||||
},
|
||||
|
59
website/source/docs/providers/aws/d/ip_ranges.html.markdown
Normal file
59
website/source/docs/providers/aws/d/ip_ranges.html.markdown
Normal file
@ -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
|
@ -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
|
@ -25,6 +25,9 @@
|
||||
<li<%= sidebar_current("docs-aws-datasource-iam-policy-document") %>>
|
||||
<a href="/docs/providers/aws/d/iam_policy_document.html">aws_iam_policy_document</a>
|
||||
</li>
|
||||
<li<%= sidebar_current("docs-aws-datasource-ip_ranges") %>>
|
||||
<a href="/docs/providers/aws/d/ip_ranges.html">aws_ip_ranges</a>
|
||||
</li>
|
||||
<li<%= sidebar_current("docs-aws-datasource-s3-bucket-object") %>>
|
||||
<a href="/docs/providers/aws/d/s3_bucket_object.html">aws_s3_bucket_object</a>
|
||||
</li>
|
||||
|
@ -10,6 +10,15 @@
|
||||
<a href="/docs/providers/fastly/index.html">Fastly Provider</a>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current(/^docs-fastly-datasource/) %>>
|
||||
<a href="#">Data Sources</a>
|
||||
<ul class="nav nav-visible">
|
||||
<li<%= sidebar_current("docs-fastly-datasource-ip_ranges") %>>
|
||||
<a href="/docs/providers/fastly/d/ip_ranges.html">fastly_ip_ranges</a>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li<%= sidebar_current(/^docs-fastly-resource/) %>>
|
||||
<a href="#">Resources</a>
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user