-
Notifications
You must be signed in to change notification settings - Fork 9.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added API Gateway Gateway response resource #1168
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"time" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/aws/awserr" | ||
"github.com/aws/aws-sdk-go/service/apigateway" | ||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/helper/schema" | ||
) | ||
|
||
func resourceAwsApiGatewayGatewayResponse() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceAwsApiGatewayGatewayResponsePut, | ||
Read: resourceAwsApiGatewayGatewayResponseRead, | ||
Update: resourceAwsApiGatewayGatewayResponsePut, | ||
Delete: resourceAwsApiGatewayGatewayResponseDelete, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"rest_api_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
|
||
"response_type": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
|
||
"status_code": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
}, | ||
|
||
"response_templates": { | ||
Type: schema.TypeMap, | ||
Elem: schema.TypeString, | ||
Optional: true, | ||
}, | ||
|
||
"response_parameters": { | ||
Type: schema.TypeMap, | ||
Elem: schema.TypeString, | ||
Optional: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceAwsApiGatewayGatewayResponsePut(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).apigateway | ||
|
||
templates := make(map[string]string) | ||
if kv, ok := d.GetOk("response_templates"); ok { | ||
for k, v := range kv.(map[string]interface{}) { | ||
templates[k] = v.(string) | ||
} | ||
} | ||
|
||
parameters := make(map[string]string) | ||
if kv, ok := d.GetOk("response_parameters"); ok { | ||
for k, v := range kv.(map[string]interface{}) { | ||
parameters[k] = v.(string) | ||
} | ||
} | ||
|
||
input := apigateway.PutGatewayResponseInput{ | ||
RestApiId: aws.String(d.Get("rest_api_id").(string)), | ||
ResponseType: aws.String(d.Get("response_type").(string)), | ||
ResponseTemplates: aws.StringMap(templates), | ||
ResponseParameters: aws.StringMap(parameters), | ||
} | ||
|
||
if v, ok := d.GetOk("status_code"); ok { | ||
input.StatusCode = aws.String(v.(string)) | ||
} | ||
|
||
log.Printf("[DEBUG] Putting API Gateway Gateway Response: %s", input) | ||
|
||
_, err := conn.PutGatewayResponse(&input) | ||
if err != nil { | ||
return fmt.Errorf("Error putting API Gateway Gateway Response: %s", err) | ||
} | ||
|
||
d.SetId(fmt.Sprintf("aggr-%s-%s", d.Get("rest_api_id").(string), d.Get("response_type").(string))) | ||
log.Printf("[DEBUG] API Gateway Gateway Response put (%q)", d.Id()) | ||
|
||
return resourceAwsApiGatewayGatewayResponseRead(d, meta) | ||
} | ||
|
||
func resourceAwsApiGatewayGatewayResponseRead(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).apigateway | ||
|
||
log.Printf("[DEBUG] Reading API Gateway Gateway Response %s", d.Id()) | ||
gatewayResponse, err := conn.GetGatewayResponse(&apigateway.GetGatewayResponseInput{ | ||
RestApiId: aws.String(d.Get("rest_api_id").(string)), | ||
ResponseType: aws.String(d.Get("response_type").(string)), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the combination of both There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup, don't see any counter argument :) |
||
}) | ||
if err != nil { | ||
if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "NotFoundException" { | ||
log.Printf("[WARN] API Gateway Gateway Response (%s) not found, removing from state", d.Id()) | ||
d.SetId("") | ||
return nil | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👌 👍 |
||
} | ||
return err | ||
} | ||
|
||
log.Printf("[DEBUG] Received API Gateway Gateway Response: %s", gatewayResponse) | ||
|
||
d.Set("response_type", gatewayResponse.ResponseType) | ||
d.Set("status_code", gatewayResponse.StatusCode) | ||
d.Set("response_templates", aws.StringValueMap(gatewayResponse.ResponseTemplates)) | ||
d.Set("response_parameters", aws.StringValueMap(gatewayResponse.ResponseParameters)) | ||
|
||
return nil | ||
} | ||
|
||
func resourceAwsApiGatewayGatewayResponseDelete(d *schema.ResourceData, meta interface{}) error { | ||
conn := meta.(*AWSClient).apigateway | ||
log.Printf("[DEBUG] Deleting API Gateway Gateway Response: %s", d.Id()) | ||
|
||
return resource.Retry(1*time.Minute, func() *resource.RetryError { | ||
_, err := conn.DeleteGatewayResponse(&apigateway.DeleteGatewayResponseInput{ | ||
RestApiId: aws.String(d.Get("rest_api_id").(string)), | ||
ResponseType: aws.String(d.Get("response_type").(string)), | ||
}) | ||
|
||
if err == nil { | ||
return nil | ||
} | ||
|
||
apigatewayErr, ok := err.(awserr.Error) | ||
|
||
if ok && apigatewayErr.Code() == "NotFoundException" { | ||
return nil | ||
} | ||
|
||
return resource.NonRetryableError(err) | ||
}) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
package aws | ||
|
||
import ( | ||
"fmt" | ||
"testing" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/aws/awserr" | ||
"github.com/aws/aws-sdk-go/service/apigateway" | ||
"github.com/hashicorp/terraform/helper/acctest" | ||
"github.com/hashicorp/terraform/helper/resource" | ||
"github.com/hashicorp/terraform/terraform" | ||
) | ||
|
||
func TestAccAWSAPIGatewayGatewayResponse_basic(t *testing.T) { | ||
var conf apigateway.UpdateGatewayResponseOutput | ||
|
||
rName := acctest.RandString(10) | ||
|
||
resource.Test(t, resource.TestCase{ | ||
PreCheck: func() { testAccPreCheck(t) }, | ||
Providers: testAccProviders, | ||
CheckDestroy: testAccCheckAWSAPIGatewayGatewayResponseDestroy, | ||
Steps: []resource.TestStep{ | ||
{ | ||
Config: testAccAWSAPIGatewayGatewayResponseConfig(rName), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckAWSAPIGatewayGatewayResponseExists("aws_api_gateway_gateway_response.test", &conf), | ||
resource.TestCheckResourceAttr("aws_api_gateway_gateway_response.test", "status_code", "401"), | ||
resource.TestCheckResourceAttr("aws_api_gateway_gateway_response.test", "response_parameters.gatewayresponse.header.Authorization", "'Basic'"), | ||
resource.TestCheckResourceAttr("aws_api_gateway_gateway_response.test", "response_templates.application/xml", "#set($inputRoot = $input.path('$'))\n{ }"), | ||
resource.TestCheckNoResourceAttr("aws_api_gateway_gateway_response.test", "response_templates.application/json"), | ||
), | ||
}, | ||
|
||
{ | ||
Config: testAccAWSAPIGatewayGatewayResponseConfigUpdate(rName), | ||
Check: resource.ComposeTestCheckFunc( | ||
testAccCheckAWSAPIGatewayGatewayResponseExists("aws_api_gateway_gateway_response.test", &conf), | ||
resource.TestCheckResourceAttr("aws_api_gateway_gateway_response.test", "status_code", "477"), | ||
resource.TestCheckResourceAttr("aws_api_gateway_gateway_response.test", "response_templates.application/json", "{'message':$context.error.messageString}"), | ||
resource.TestCheckNoResourceAttr("aws_api_gateway_gateway_response.test", "response_templates.application/xml"), | ||
resource.TestCheckNoResourceAttr("aws_api_gateway_gateway_response.test", "response_parameters.gatewayresponse.header.Authorization"), | ||
), | ||
}, | ||
}, | ||
}) | ||
} | ||
|
||
func testAccCheckAWSAPIGatewayGatewayResponseExists(n string, res *apigateway.UpdateGatewayResponseOutput) resource.TestCheckFunc { | ||
return func(s *terraform.State) error { | ||
rs, ok := s.RootModule().Resources[n] | ||
if !ok { | ||
return fmt.Errorf("Not found: %s", n) | ||
} | ||
|
||
if rs.Primary.ID == "" { | ||
return fmt.Errorf("No API Gateway Gateway Response ID is set") | ||
} | ||
|
||
conn := testAccProvider.Meta().(*AWSClient).apigateway | ||
|
||
req := &apigateway.GetGatewayResponseInput{ | ||
RestApiId: aws.String(s.RootModule().Resources["aws_api_gateway_rest_api.main"].Primary.ID), | ||
ResponseType: aws.String(rs.Primary.Attributes["response_type"]), | ||
} | ||
describe, err := conn.GetGatewayResponse(req) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
*res = *describe | ||
|
||
return nil | ||
} | ||
} | ||
|
||
func testAccCheckAWSAPIGatewayGatewayResponseDestroy(s *terraform.State) error { | ||
conn := testAccProvider.Meta().(*AWSClient).apigateway | ||
|
||
for _, rs := range s.RootModule().Resources { | ||
if rs.Type != "aws_api_gateway_gateway_response" { | ||
continue | ||
} | ||
|
||
req := &apigateway.GetGatewayResponseInput{ | ||
RestApiId: aws.String(s.RootModule().Resources["aws_api_gateway_rest_api.main"].Primary.ID), | ||
ResponseType: aws.String(rs.Primary.Attributes["response_type"]), | ||
} | ||
_, err := conn.GetGatewayResponse(req) | ||
|
||
if err == nil { | ||
return fmt.Errorf("API Gateway Gateway Response still exists") | ||
} | ||
|
||
aws2err, ok := err.(awserr.Error) | ||
if !ok { | ||
return err | ||
} | ||
if aws2err.Code() != "NotFoundException" { | ||
return err | ||
} | ||
|
||
return nil | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func testAccAWSAPIGatewayGatewayResponseConfig(rName string) string { | ||
return fmt.Sprintf(` | ||
resource "aws_api_gateway_rest_api" "main" { | ||
name = "%s" | ||
} | ||
|
||
resource "aws_api_gateway_gateway_response" "test" { | ||
rest_api_id = "${aws_api_gateway_rest_api.main.id}" | ||
status_code = "401" | ||
response_type = "UNAUTHORIZED" | ||
|
||
response_templates = { | ||
"application/xml" = "#set($inputRoot = $input.path('$'))\n{ }" | ||
} | ||
|
||
response_parameters = { | ||
"gatewayresponse.header.Authorization" = "'Basic'" | ||
} | ||
} | ||
`, rName) | ||
} | ||
|
||
func testAccAWSAPIGatewayGatewayResponseConfigUpdate(rName string) string { | ||
return fmt.Sprintf(` | ||
resource "aws_api_gateway_rest_api" "main" { | ||
name = "%s" | ||
} | ||
|
||
resource "aws_api_gateway_gateway_response" "test" { | ||
rest_api_id = "${aws_api_gateway_rest_api.main.id}" | ||
status_code = "477" | ||
response_type = "UNAUTHORIZED" | ||
|
||
response_templates = { | ||
"application/json" = "{'message':$context.error.messageString}" | ||
} | ||
} | ||
`, rName) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
--- | ||
layout: "aws" | ||
page_title: "AWS: aws_api_gateway_gateway_response" | ||
sidebar_current: "docs-aws-resource-api-gateway-gateway-response" | ||
description: |- | ||
Provides an API Gateway Gateway Response for a REST API Gateway. | ||
--- | ||
|
||
# aws\_api\_gateway\_gateway\_response | ||
|
||
Provides an API Gateway Gateway Response for a REST API Gateway. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ... Gateway Gateway ... Gateway 😂 🤷♂️ |
||
|
||
## Example Usage | ||
|
||
```hcl | ||
resource "aws_api_gateway_rest_api" "main" { | ||
name = "MyDemoAPI" | ||
} | ||
|
||
resource "aws_api_gateway_gateway_response" "test" { | ||
rest_api_id = "${aws_api_gateway_rest_api.main.id}" | ||
status_code = "401" | ||
response_type = "UNAUTHORIZED" | ||
|
||
response_templates = { | ||
"application/json" = "{'message':$context.error.messageString}" | ||
} | ||
|
||
response_parameters = { | ||
"gatewayresponse.header.Authorization" = "'Basic'" | ||
} | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
|
||
The following arguments are supported: | ||
|
||
* `rest_api_id` - (Required) The string identifier of the associated REST API. | ||
* `response_type` - (Required) The response type of the associated GatewayResponse. | ||
* `status_code` - (Optional) The HTTP status code of the Gateway Response. | ||
* `response_parameters` - (Optional) A map specifying the templates used to transform the response body. | ||
* `response_templates` - (Optional) A map specifying the parameters (paths, query strings and headers) of the Gateway Response. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if the two fields (
response_templates
&response_parameters
) are optional and user didn't define those we shouldn't be sending them to the API here.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed via Slack, this doesn't matter and we need it for updates, so 👍