Skip to content

Commit

Permalink
Add aws_apigatewayv2_api and aws_apigatewayv2_apis data source.
Browse files Browse the repository at this point in the history
  • Loading branch information
ewbankkit committed Feb 17, 2021
1 parent 091eb54 commit 187222b
Show file tree
Hide file tree
Showing 9 changed files with 652 additions and 0 deletions.
7 changes: 7 additions & 0 deletions .changelog/13883.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
```release-note:new-data-source
aws_apigatewayv2_api
```

```release-note:new-data-source
aws_apigatewayv2_api
```
149 changes: 149 additions & 0 deletions aws/data_source_aws_apigatewayv2_api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
package aws

import (
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/arn"
"github.com/aws/aws-sdk-go/service/apigatewayv2"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
)

func dataSourceAwsApiGatewayV2Api() *schema.Resource {
return &schema.Resource{
Read: dataSourceAwsAwsApiGatewayV2ApiRead,

Schema: map[string]*schema.Schema{
"api_endpoint": {
Type: schema.TypeString,
Computed: true,
},
"api_id": {
Type: schema.TypeString,
Required: true,
},
"api_key_selection_expression": {
Type: schema.TypeString,
Computed: true,
},
"arn": {
Type: schema.TypeString,
Computed: true,
},
"cors_configuration": {
Type: schema.TypeList,
Computed: true,
Elem: &schema.Resource{
Schema: map[string]*schema.Schema{
"allow_credentials": {
Type: schema.TypeBool,
Computed: true,
},
"allow_headers": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: hashStringCaseInsensitive,
},
"allow_methods": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: hashStringCaseInsensitive,
},
"allow_origins": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: hashStringCaseInsensitive,
},
"expose_headers": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: hashStringCaseInsensitive,
},
"max_age": {
Type: schema.TypeInt,
Computed: true,
},
},
},
},
"description": {
Type: schema.TypeString,
Computed: true,
},
"execution_arn": {
Type: schema.TypeString,
Computed: true,
},
"name": {
Type: schema.TypeString,
Computed: true,
},
"protocol_type": {
Type: schema.TypeString,
Computed: true,
},
"route_selection_expression": {
Type: schema.TypeString,
Computed: true,
},
"tags": tagsSchemaComputed(),
"version": {
Type: schema.TypeString,
Computed: true,
},
},
}
}

func dataSourceAwsAwsApiGatewayV2ApiRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).apigatewayv2conn
ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig

d.SetId(d.Get("api_id").(string))

input := &apigatewayv2.GetApiInput{
ApiId: aws.String(d.Id()),
}

output, err := conn.GetApi(input)

if err != nil {
return fmt.Errorf("error reading API Gateway v2 API (%s): %s", d.Id(), err)
}

d.Set("api_endpoint", output.ApiEndpoint)
d.Set("api_key_selection_expression", output.ApiKeySelectionExpression)
apiArn := arn.ARN{
Partition: meta.(*AWSClient).partition,
Service: "apigateway",
Region: meta.(*AWSClient).region,
Resource: fmt.Sprintf("/apis/%s", d.Id()),
}.String()
d.Set("arn", apiArn)
if err := d.Set("cors_configuration", flattenApiGateway2CorsConfiguration(output.CorsConfiguration)); err != nil {
return fmt.Errorf("error setting cors_configuration: %s", err)
}
d.Set("description", output.Description)
executionArn := arn.ARN{
Partition: meta.(*AWSClient).partition,
Service: "execute-api",
Region: meta.(*AWSClient).region,
AccountID: meta.(*AWSClient).accountid,
Resource: d.Id(),
}.String()
d.Set("execution_arn", executionArn)
d.Set("name", output.Name)
d.Set("protocol_type", output.ProtocolType)
d.Set("route_selection_expression", output.RouteSelectionExpression)
if err := d.Set("tags", keyvaluetags.Apigatewayv2KeyValueTags(output.Tags).IgnoreAws().IgnoreConfig(ignoreTagsConfig).Map()); err != nil {
return fmt.Errorf("error setting tags: %s", err)
}
d.Set("version", output.Version)

return nil
}
127 changes: 127 additions & 0 deletions aws/data_source_aws_apigatewayv2_api_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
package aws

import (
"fmt"
"testing"

"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
)

func TestAccAWSAPIGatewayV2ApiDataSource_Http(t *testing.T) {
dataSourceName := "data.aws_apigatewayv2_api.test"
resourceName := "aws_apigatewayv2_api.test"
rName := acctest.RandomWithPrefix("tf-acc-test")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: testAccAWSAPIGatewayV2ApiDataSourceConfigHttp(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(dataSourceName, "api_endpoint", resourceName, "api_endpoint"),
resource.TestCheckResourceAttrPair(dataSourceName, "api_key_selection_expression", resourceName, "api_key_selection_expression"),
resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "cors_configuration.#", resourceName, "cors_configuration.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "cors_configuration.0.allow_credentials", resourceName, "cors_configuration.0.allow_credentials"),
resource.TestCheckResourceAttrPair(dataSourceName, "cors_configuration.0.allow_headers.#", resourceName, "cors_configuration.0.allow_headers.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "cors_configuration.0.allow_methods.#", resourceName, "cors_configuration.0.allow_methods.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "cors_configuration.0.allow_origins.#", resourceName, "cors_configuration.0.allow_origins.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "cors_configuration.0.expose_headers.#", resourceName, "cors_configuration.0.expose_headers.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "cors_configuration.0.max_age", resourceName, "cors_configuration.0.max_age"),
resource.TestCheckResourceAttrPair(dataSourceName, "description", resourceName, "description"),
resource.TestCheckResourceAttrPair(dataSourceName, "execution_arn", resourceName, "execution_arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "name", resourceName, "name"),
resource.TestCheckResourceAttrPair(dataSourceName, "protocol_type", resourceName, "protocol_type"),
resource.TestCheckResourceAttrPair(dataSourceName, "route_selection_expression", resourceName, "route_selection_expression"),
resource.TestCheckResourceAttrPair(dataSourceName, "tags.%", resourceName, "tags.%"),
resource.TestCheckResourceAttrPair(dataSourceName, "tags.Key1", resourceName, "tags.Key1"),
resource.TestCheckResourceAttrPair(dataSourceName, "tags.Key2", resourceName, "tags.Key2"),
resource.TestCheckResourceAttrPair(dataSourceName, "version", resourceName, "version"),
),
},
},
})
}

func TestAccAWSAPIGatewayV2ApiDataSource_WebSocket(t *testing.T) {
dataSourceName := "data.aws_apigatewayv2_api.test"
resourceName := "aws_apigatewayv2_api.test"
rName := acctest.RandomWithPrefix("tf-acc-test")

resource.ParallelTest(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
CheckDestroy: nil,
Steps: []resource.TestStep{
{
Config: testAccAWSAPIGatewayV2ApiDataSourceConfigWebSocket(rName),
Check: resource.ComposeTestCheckFunc(
resource.TestCheckResourceAttrPair(dataSourceName, "api_endpoint", resourceName, "api_endpoint"),
resource.TestCheckResourceAttrPair(dataSourceName, "api_key_selection_expression", resourceName, "api_key_selection_expression"),
resource.TestCheckResourceAttrPair(dataSourceName, "arn", resourceName, "arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "cors_configuration.#", resourceName, "cors_configuration.#"),
resource.TestCheckResourceAttrPair(dataSourceName, "description", resourceName, "description"),
resource.TestCheckResourceAttrPair(dataSourceName, "execution_arn", resourceName, "execution_arn"),
resource.TestCheckResourceAttrPair(dataSourceName, "name", resourceName, "name"),
resource.TestCheckResourceAttrPair(dataSourceName, "protocol_type", resourceName, "protocol_type"),
resource.TestCheckResourceAttrPair(dataSourceName, "route_selection_expression", resourceName, "route_selection_expression"),
resource.TestCheckResourceAttrPair(dataSourceName, "tags.%", resourceName, "tags.%"),
resource.TestCheckResourceAttrPair(dataSourceName, "tags.Key1", resourceName, "tags.Key1"),
resource.TestCheckResourceAttrPair(dataSourceName, "tags.Key2", resourceName, "tags.Key2"),
resource.TestCheckResourceAttrPair(dataSourceName, "version", resourceName, "version"),
),
},
},
})
}

func testAccAWSAPIGatewayV2ApiDataSourceConfigHttp(rName string) string {
return fmt.Sprintf(`
resource "aws_apigatewayv2_api" "test" {
description = "test description"
name = %[1]q
protocol_type = "HTTP"
version = "v1"
cors_configuration {
allow_headers = ["Authorization"]
allow_methods = ["GET", "put"]
allow_origins = ["https://www.example.com"]
}
tags = {
Key1 = "Value1h"
Key2 = "Value2h"
}
}
data "aws_apigatewayv2_api" "test" {
api_id = aws_apigatewayv2_api.test.id
}
`, rName)
}

func testAccAWSAPIGatewayV2ApiDataSourceConfigWebSocket(rName string) string {
return fmt.Sprintf(`
resource "aws_apigatewayv2_api" "test" {
api_key_selection_expression = "$context.authorizer.usageIdentifierKey"
description = "test description"
name = %[1]q
protocol_type = "WEBSOCKET"
route_selection_expression = "$request.body.service"
version = "v1"
tags = {
Key1 = "Value1ws"
Key2 = "Value2ws"
}
}
data "aws_apigatewayv2_api" "test" {
api_id = aws_apigatewayv2_api.test.id
}
`, rName)
}
105 changes: 105 additions & 0 deletions aws/data_source_aws_apigatewayv2_apis.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
package aws

import (
"fmt"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/apigatewayv2"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/terraform-providers/terraform-provider-aws/aws/internal/keyvaluetags"
)

func dataSourceAwsApiGatewayV2Apis() *schema.Resource {
return &schema.Resource{
Read: dataSourceAwsAwsApiGatewayV2ApisRead,

Schema: map[string]*schema.Schema{
"ids": {
Type: schema.TypeSet,
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Set: schema.HashString,
},
"name": {
Type: schema.TypeString,
Optional: true,
},
"protocol_type": {
Type: schema.TypeString,
Optional: true,
},
"tags": tagsSchema(),
},
}
}

func dataSourceAwsAwsApiGatewayV2ApisRead(d *schema.ResourceData, meta interface{}) error {
conn := meta.(*AWSClient).apigatewayv2conn
ignoreTagsConfig := meta.(*AWSClient).IgnoreTagsConfig

tagsToMatch := keyvaluetags.New(d.Get("tags").(map[string]interface{})).IgnoreAws().IgnoreConfig(ignoreTagsConfig)

var ids []*string

err := ListAllApiGatewayV2Apis(conn, func(page *apigatewayv2.GetApisOutput, isLast bool) bool {
if page == nil {
return !isLast
}

for _, api := range page.Items {
if v, ok := d.GetOk("name"); ok && v.(string) != aws.StringValue(api.Name) {
continue
}

if v, ok := d.GetOk("protocol_type"); ok && v.(string) != aws.StringValue(api.ProtocolType) {
continue
}

if len(tagsToMatch) > 0 && !keyvaluetags.Apigatewayv2KeyValueTags(api.Tags).IgnoreAws().IgnoreConfig(ignoreTagsConfig).ContainsAll(tagsToMatch) {
continue
}

ids = append(ids, api.ApiId)
}

return !isLast
})

if err != nil {
return fmt.Errorf("error listing API Gateway v2 APIs: %w", err)
}

d.SetId(resource.UniqueId())

if err := d.Set("ids", flattenStringSet(ids)); err != nil {
return fmt.Errorf("error setting ids: %w", err)
}

return nil
}

//
// These can be moved to a per-service package like "aws/internal/service/apigatewayv2/lister" in the future.
//

func ListAllApiGatewayV2Apis(conn *apigatewayv2.ApiGatewayV2, fn func(*apigatewayv2.GetApisOutput, bool) bool) error {
return ListApiGatewayV2ApisPages(conn, &apigatewayv2.GetApisInput{}, fn)
}

func ListApiGatewayV2ApisPages(conn *apigatewayv2.ApiGatewayV2, input *apigatewayv2.GetApisInput, fn func(*apigatewayv2.GetApisOutput, bool) bool) error {
for {
output, err := conn.GetApis(input)
if err != nil {
return err
}

lastPage := aws.StringValue(output.NextToken) == ""
if !fn(output, lastPage) || lastPage {
break
}

input.NextToken = output.NextToken
}
return nil
}
Loading

0 comments on commit 187222b

Please sign in to comment.