Skip to content

Commit 032e608

Browse files
committed
Add aws_api_gateway_method resource
1 parent 7ead800 commit 032e608

7 files changed

Lines changed: 397 additions & 0 deletions

File tree

builtin/providers/aws/provider.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ func Provider() terraform.ResourceProvider {
116116
"aws_ami_from_instance": resourceAwsAmiFromInstance(),
117117
"aws_api_gateway_rest_api": resourceAwsApiGatewayRestApi(),
118118
"aws_api_gateway_resource": resourceAwsApiGatewayResource(),
119+
"aws_api_gateway_method": resourceAwsApiGatewayMethod(),
119120
"aws_app_cookie_stickiness_policy": resourceAwsAppCookieStickinessPolicy(),
120121
"aws_autoscaling_group": resourceAwsAutoscalingGroup(),
121122
"aws_autoscaling_notification": resourceAwsAutoscalingNotification(),
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
package aws
2+
3+
import (
4+
"fmt"
5+
"log"
6+
"time"
7+
8+
"github.com/aws/aws-sdk-go/aws"
9+
"github.com/aws/aws-sdk-go/aws/awserr"
10+
"github.com/aws/aws-sdk-go/service/apigateway"
11+
"github.com/hashicorp/terraform/helper/resource"
12+
"github.com/hashicorp/terraform/helper/schema"
13+
)
14+
15+
func resourceAwsApiGatewayMethod() *schema.Resource {
16+
return &schema.Resource{
17+
Create: resourceAwsApiGatewayMethodCreate,
18+
Read: resourceAwsApiGatewayMethodRead,
19+
Update: resourceAwsApiGatewayMethodUpdate,
20+
Delete: resourceAwsApiGatewayMethodDelete,
21+
22+
Schema: map[string]*schema.Schema{
23+
"rest_api_id": &schema.Schema{
24+
Type: schema.TypeString,
25+
Required: true,
26+
ForceNew: true,
27+
},
28+
29+
"resource_id": &schema.Schema{
30+
Type: schema.TypeString,
31+
Required: true,
32+
ForceNew: true,
33+
},
34+
35+
"http_method": &schema.Schema{
36+
Type: schema.TypeString,
37+
Required: true,
38+
ForceNew: true,
39+
ValidateFunc: validateHTTPMethod,
40+
},
41+
42+
"authorization": &schema.Schema{
43+
Type: schema.TypeString,
44+
Required: true,
45+
},
46+
47+
"api_key_required": &schema.Schema{
48+
Type: schema.TypeBool,
49+
Optional: true,
50+
Default: false,
51+
},
52+
53+
"request_models": &schema.Schema{
54+
Type: schema.TypeMap,
55+
Optional: true,
56+
Elem: schema.TypeString,
57+
},
58+
},
59+
}
60+
}
61+
62+
func resourceAwsApiGatewayMethodCreate(d *schema.ResourceData, meta interface{}) error {
63+
conn := meta.(*AWSClient).apigateway
64+
65+
models := make(map[string]string)
66+
for k, v := range d.Get("request_models").(map[string]interface{}) {
67+
models[k] = v.(string)
68+
}
69+
70+
parameters := make(map[string]bool)
71+
if parameterData, ok := d.GetOk("request_parameters"); ok {
72+
params := parameterData.(*schema.Set).List()
73+
for k := range params {
74+
parameters[params[k].(string)] = true
75+
}
76+
}
77+
78+
_, err := conn.PutMethod(&apigateway.PutMethodInput{
79+
AuthorizationType: aws.String(d.Get("authorization").(string)),
80+
HttpMethod: aws.String(d.Get("http_method").(string)),
81+
ResourceId: aws.String(d.Get("resource_id").(string)),
82+
RestApiId: aws.String(d.Get("rest_api_id").(string)),
83+
RequestModels: aws.StringMap(models),
84+
// TODO implement once [GH-2143](https://github.com/hashicorp/terraform/issues/2143) has been implemented
85+
RequestParameters: nil,
86+
ApiKeyRequired: aws.Bool(d.Get("api_key_required").(bool)),
87+
})
88+
if err != nil {
89+
return fmt.Errorf("Error creating API Gateway Method: %s", err)
90+
}
91+
92+
d.SetId(fmt.Sprintf("agm-%s-%s-%s", d.Get("rest_api_id").(string), d.Get("resource_id").(string), d.Get("http_method").(string)))
93+
log.Printf("[DEBUG] API Gateway Method ID: %s", d.Id())
94+
95+
return nil
96+
}
97+
98+
func resourceAwsApiGatewayMethodRead(d *schema.ResourceData, meta interface{}) error {
99+
conn := meta.(*AWSClient).apigateway
100+
101+
log.Printf("[DEBUG] Reading API Gateway Method %s", d.Id())
102+
out, err := conn.GetMethod(&apigateway.GetMethodInput{
103+
HttpMethod: aws.String(d.Get("http_method").(string)),
104+
ResourceId: aws.String(d.Get("resource_id").(string)),
105+
RestApiId: aws.String(d.Get("rest_api_id").(string)),
106+
})
107+
if err != nil {
108+
if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "NotFoundException" {
109+
d.SetId("")
110+
return nil
111+
}
112+
return err
113+
}
114+
log.Printf("[DEBUG] Received API Gateway Method: %s", out)
115+
d.SetId(fmt.Sprintf("agm-%s-%s-%s", d.Get("rest_api_id").(string), d.Get("resource_id").(string), d.Get("http_method").(string)))
116+
117+
return nil
118+
}
119+
120+
func resourceAwsApiGatewayMethodUpdate(d *schema.ResourceData, meta interface{}) error {
121+
conn := meta.(*AWSClient).apigateway
122+
123+
log.Printf("[DEBUG] Reading API Gateway Method %s", d.Id())
124+
operations := make([]*apigateway.PatchOperation, 0)
125+
if d.HasChange("resource_id") {
126+
operations = append(operations, &apigateway.PatchOperation{
127+
Op: aws.String("replace"),
128+
Path: aws.String("/resourceId"),
129+
Value: aws.String(d.Get("resource_id").(string)),
130+
})
131+
}
132+
133+
if d.HasChange("request_models") {
134+
operations = append(operations, expandApiGatewayRequestResponseModelOperations(d, "request_models", "requestModels")...)
135+
}
136+
137+
method, err := conn.UpdateMethod(&apigateway.UpdateMethodInput{
138+
HttpMethod: aws.String(d.Get("http_method").(string)),
139+
ResourceId: aws.String(d.Get("resource_id").(string)),
140+
RestApiId: aws.String(d.Get("rest_api_id").(string)),
141+
PatchOperations: operations,
142+
})
143+
144+
if err != nil {
145+
return err
146+
}
147+
148+
log.Printf("[DEBUG] Received API Gateway Method: %s", method)
149+
150+
return resourceAwsApiGatewayMethodRead(d, meta)
151+
}
152+
153+
func resourceAwsApiGatewayMethodDelete(d *schema.ResourceData, meta interface{}) error {
154+
conn := meta.(*AWSClient).apigateway
155+
log.Printf("[DEBUG] Deleting API Gateway Method: %s", d.Id())
156+
157+
resourceId := d.Get("resource_id").(string)
158+
if o, n := d.GetChange("resource_id"); o.(string) != n.(string) {
159+
resourceId = o.(string)
160+
}
161+
httpMethod := d.Get("http_method").(string)
162+
if o, n := d.GetChange("http_method"); o.(string) != n.(string) {
163+
httpMethod = o.(string)
164+
}
165+
restApiID := d.Get("rest_api_id").(string)
166+
if o, n := d.GetChange("rest_api_id"); o.(string) != n.(string) {
167+
restApiID = o.(string)
168+
}
169+
170+
return resource.Retry(5*time.Minute, func() error {
171+
log.Printf("[DEBUG] schema is %#v", d)
172+
_, err := conn.DeleteMethod(&apigateway.DeleteMethodInput{
173+
HttpMethod: aws.String(httpMethod),
174+
ResourceId: aws.String(resourceId),
175+
RestApiId: aws.String(restApiID),
176+
})
177+
if err == nil {
178+
return nil
179+
}
180+
181+
apigatewayErr, ok := err.(awserr.Error)
182+
if apigatewayErr.Code() == "NotFoundException" {
183+
return nil
184+
}
185+
186+
if !ok {
187+
return resource.RetryError{Err: err}
188+
}
189+
190+
return resource.RetryError{Err: err}
191+
})
192+
}
Lines changed: 134 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,134 @@
1+
package aws
2+
3+
import (
4+
"fmt"
5+
"testing"
6+
7+
"github.com/aws/aws-sdk-go/aws"
8+
"github.com/aws/aws-sdk-go/aws/awserr"
9+
"github.com/aws/aws-sdk-go/service/apigateway"
10+
"github.com/hashicorp/terraform/helper/resource"
11+
"github.com/hashicorp/terraform/terraform"
12+
)
13+
14+
func TestAccAWSAPIGatewayMethod_basic(t *testing.T) {
15+
var conf apigateway.Method
16+
17+
resource.Test(t, resource.TestCase{
18+
PreCheck: func() { testAccPreCheck(t) },
19+
Providers: testAccProviders,
20+
CheckDestroy: testAccCheckAWSAPIGatewayMethodDestroy,
21+
Steps: []resource.TestStep{
22+
resource.TestStep{
23+
Config: testAccAWSAPIGatewayMethodConfig,
24+
Check: resource.ComposeTestCheckFunc(
25+
testAccCheckAWSAPIGatewayMethodExists("aws_api_gateway_method.test", &conf),
26+
testAccCheckAWSAPIGatewayMethodAttributes(&conf),
27+
resource.TestCheckResourceAttr(
28+
"aws_api_gateway_method.test", "http_method", "GET"),
29+
resource.TestCheckResourceAttr(
30+
"aws_api_gateway_method.test", "authorization", "NONE"),
31+
resource.TestCheckResourceAttr(
32+
"aws_api_gateway_method.test", "request_models.application/json", "Error"),
33+
),
34+
},
35+
},
36+
})
37+
}
38+
39+
func testAccCheckAWSAPIGatewayMethodAttributes(conf *apigateway.Method) resource.TestCheckFunc {
40+
return func(s *terraform.State) error {
41+
if *conf.HttpMethod != "GET" {
42+
return fmt.Errorf("Wrong HttpMethod: %q", *conf.HttpMethod)
43+
}
44+
if *conf.AuthorizationType != "NONE" {
45+
return fmt.Errorf("Wrong Authorization: %q", *conf.AuthorizationType)
46+
}
47+
return nil
48+
}
49+
}
50+
51+
func testAccCheckAWSAPIGatewayMethodExists(n string, res *apigateway.Method) resource.TestCheckFunc {
52+
return func(s *terraform.State) error {
53+
rs, ok := s.RootModule().Resources[n]
54+
if !ok {
55+
return fmt.Errorf("Not found: %s", n)
56+
}
57+
58+
if rs.Primary.ID == "" {
59+
return fmt.Errorf("No API Gateway Method ID is set")
60+
}
61+
62+
conn := testAccProvider.Meta().(*AWSClient).apigateway
63+
64+
req := &apigateway.GetMethodInput{
65+
HttpMethod: aws.String("GET"),
66+
ResourceId: aws.String(s.RootModule().Resources["aws_api_gateway_resource.test"].Primary.ID),
67+
RestApiId: aws.String(s.RootModule().Resources["aws_api_gateway_rest_api.test"].Primary.ID),
68+
}
69+
describe, err := conn.GetMethod(req)
70+
if err != nil {
71+
return err
72+
}
73+
74+
*res = *describe
75+
76+
return nil
77+
}
78+
}
79+
80+
func testAccCheckAWSAPIGatewayMethodDestroy(s *terraform.State) error {
81+
conn := testAccProvider.Meta().(*AWSClient).apigateway
82+
83+
for _, rs := range s.RootModule().Resources {
84+
if rs.Type != "aws_api_gateway_method" {
85+
continue
86+
}
87+
88+
req := &apigateway.GetMethodInput{
89+
HttpMethod: aws.String("GET"),
90+
ResourceId: aws.String(s.RootModule().Resources["aws_api_gateway_resource.test"].Primary.ID),
91+
RestApiId: aws.String(s.RootModule().Resources["aws_api_gateway_rest_api.test"].Primary.ID),
92+
}
93+
_, err := conn.GetMethod(req)
94+
95+
if err == nil {
96+
return fmt.Errorf("API Gateway Method still exists")
97+
}
98+
99+
aws2err, ok := err.(awserr.Error)
100+
if !ok {
101+
return err
102+
}
103+
if aws2err.Code() != "NotFoundException" {
104+
return err
105+
}
106+
107+
return nil
108+
}
109+
110+
return nil
111+
}
112+
113+
const testAccAWSAPIGatewayMethodConfig = `
114+
resource "aws_api_gateway_rest_api" "test" {
115+
name = "test"
116+
}
117+
118+
resource "aws_api_gateway_resource" "test" {
119+
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
120+
parent_id = "${aws_api_gateway_rest_api.test.root_resource_id}"
121+
path_part = "test"
122+
}
123+
124+
resource "aws_api_gateway_method" "test" {
125+
rest_api_id = "${aws_api_gateway_rest_api.test.id}"
126+
resource_id = "${aws_api_gateway_resource.test.id}"
127+
http_method = "GET"
128+
authorization = "NONE"
129+
130+
request_models = {
131+
"application/json" = "Error"
132+
}
133+
}
134+
`

builtin/providers/aws/validators.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,3 +299,12 @@ func validateCIDRNetworkAddress(v interface{}, k string) (ws []string, errors []
299299

300300
return
301301
}
302+
303+
func validateHTTPMethod(v interface{}, k string) (ws []string, errors []error) {
304+
value := v.(string)
305+
if value != "GET" && value != "HEAD" && value != "OPTIONS" && value != "PUT" && value != "POST" && value != "PATCH" && value != "DELETE" {
306+
errors = append(errors, fmt.Errorf(
307+
"%q must be one of 'GET', 'HEAD', 'OPTIONS', 'PUT', 'POST', 'PATCH', 'DELETE'", k))
308+
}
309+
return
310+
}

builtin/providers/aws/validators_test.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -274,3 +274,14 @@ func TestValidateCIDRNetworkAddress(t *testing.T) {
274274
}
275275
}
276276
}
277+
278+
func TestValidateHTTPMethod(t *testing.T) {
279+
validCases := []string{"GET", "PUT", "POST", "DELETE", "OPTIONS", "HEAD", "PATCH"}
280+
for i, method := range validCases {
281+
_, errs := validateHTTPMethod(method, "foo")
282+
if len(errs) != 0 {
283+
t.Fatalf("%d/%d: Expected no error, got errs: %#v",
284+
i+1, len(validCases), errs)
285+
}
286+
}
287+
}

0 commit comments

Comments
 (0)