github.com/danp/terraform@v0.9.5-0.20170426144147-39d740081351/builtin/providers/aws/resource_aws_api_gateway_integration.go (about) 1 package aws 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "log" 7 "time" 8 9 "github.com/aws/aws-sdk-go/aws" 10 "github.com/aws/aws-sdk-go/aws/awserr" 11 "github.com/aws/aws-sdk-go/service/apigateway" 12 "github.com/hashicorp/terraform/helper/resource" 13 "github.com/hashicorp/terraform/helper/schema" 14 "strings" 15 ) 16 17 func resourceAwsApiGatewayIntegration() *schema.Resource { 18 return &schema.Resource{ 19 Create: resourceAwsApiGatewayIntegrationCreate, 20 Read: resourceAwsApiGatewayIntegrationRead, 21 Update: resourceAwsApiGatewayIntegrationUpdate, 22 Delete: resourceAwsApiGatewayIntegrationDelete, 23 24 Schema: map[string]*schema.Schema{ 25 "rest_api_id": { 26 Type: schema.TypeString, 27 Required: true, 28 ForceNew: true, 29 }, 30 31 "resource_id": { 32 Type: schema.TypeString, 33 Required: true, 34 ForceNew: true, 35 }, 36 37 "http_method": { 38 Type: schema.TypeString, 39 Required: true, 40 ForceNew: true, 41 ValidateFunc: validateHTTPMethod, 42 }, 43 44 "type": { 45 Type: schema.TypeString, 46 Required: true, 47 ForceNew: true, 48 ValidateFunc: validateApiGatewayIntegrationType, 49 }, 50 51 "uri": { 52 Type: schema.TypeString, 53 Optional: true, 54 ForceNew: true, 55 }, 56 57 "credentials": { 58 Type: schema.TypeString, 59 Optional: true, 60 ForceNew: true, 61 }, 62 63 "integration_http_method": { 64 Type: schema.TypeString, 65 Optional: true, 66 ForceNew: true, 67 ValidateFunc: validateHTTPMethod, 68 }, 69 70 "request_templates": { 71 Type: schema.TypeMap, 72 Optional: true, 73 Elem: schema.TypeString, 74 }, 75 76 "request_parameters": { 77 Type: schema.TypeMap, 78 Elem: schema.TypeString, 79 Optional: true, 80 ConflictsWith: []string{"request_parameters_in_json"}, 81 }, 82 83 "request_parameters_in_json": { 84 Type: schema.TypeString, 85 Optional: true, 86 ConflictsWith: []string{"request_parameters"}, 87 Deprecated: "Use field request_parameters instead", 88 }, 89 90 "content_handling": { 91 Type: schema.TypeString, 92 Optional: true, 93 ForceNew: true, 94 ValidateFunc: validateApiGatewayIntegrationContentHandling, 95 }, 96 97 "passthrough_behavior": { 98 Type: schema.TypeString, 99 Optional: true, 100 Computed: true, 101 ForceNew: true, 102 ValidateFunc: validateApiGatewayIntegrationPassthroughBehavior, 103 }, 104 }, 105 } 106 } 107 108 func resourceAwsApiGatewayIntegrationCreate(d *schema.ResourceData, meta interface{}) error { 109 conn := meta.(*AWSClient).apigateway 110 111 log.Print("[DEBUG] Creating API Gateway Integration") 112 var integrationHttpMethod *string 113 if v, ok := d.GetOk("integration_http_method"); ok { 114 integrationHttpMethod = aws.String(v.(string)) 115 } 116 var uri *string 117 if v, ok := d.GetOk("uri"); ok { 118 uri = aws.String(v.(string)) 119 } 120 templates := make(map[string]string) 121 for k, v := range d.Get("request_templates").(map[string]interface{}) { 122 templates[k] = v.(string) 123 } 124 125 parameters := make(map[string]string) 126 if kv, ok := d.GetOk("request_parameters"); ok { 127 for k, v := range kv.(map[string]interface{}) { 128 parameters[k] = v.(string) 129 } 130 } 131 132 if v, ok := d.GetOk("request_parameters_in_json"); ok { 133 if err := json.Unmarshal([]byte(v.(string)), ¶meters); err != nil { 134 return fmt.Errorf("Error unmarshaling request_parameters_in_json: %s", err) 135 } 136 } 137 138 var passthroughBehavior *string 139 if v, ok := d.GetOk("passthrough_behavior"); ok { 140 passthroughBehavior = aws.String(v.(string)) 141 } 142 143 var credentials *string 144 if val, ok := d.GetOk("credentials"); ok { 145 credentials = aws.String(val.(string)) 146 } 147 148 var contentHandling *string 149 if val, ok := d.GetOk("content_handling"); ok { 150 contentHandling = aws.String(val.(string)) 151 } 152 153 _, err := conn.PutIntegration(&apigateway.PutIntegrationInput{ 154 HttpMethod: aws.String(d.Get("http_method").(string)), 155 ResourceId: aws.String(d.Get("resource_id").(string)), 156 RestApiId: aws.String(d.Get("rest_api_id").(string)), 157 Type: aws.String(d.Get("type").(string)), 158 IntegrationHttpMethod: integrationHttpMethod, 159 Uri: uri, 160 RequestParameters: aws.StringMap(parameters), 161 RequestTemplates: aws.StringMap(templates), 162 Credentials: credentials, 163 CacheNamespace: nil, 164 CacheKeyParameters: nil, 165 PassthroughBehavior: passthroughBehavior, 166 ContentHandling: contentHandling, 167 }) 168 if err != nil { 169 return fmt.Errorf("Error creating API Gateway Integration: %s", err) 170 } 171 172 d.SetId(fmt.Sprintf("agi-%s-%s-%s", d.Get("rest_api_id").(string), d.Get("resource_id").(string), d.Get("http_method").(string))) 173 174 return resourceAwsApiGatewayIntegrationRead(d, meta) 175 } 176 177 func resourceAwsApiGatewayIntegrationRead(d *schema.ResourceData, meta interface{}) error { 178 conn := meta.(*AWSClient).apigateway 179 180 log.Printf("[DEBUG] Reading API Gateway Integration: %s", d.Id()) 181 integration, err := conn.GetIntegration(&apigateway.GetIntegrationInput{ 182 HttpMethod: aws.String(d.Get("http_method").(string)), 183 ResourceId: aws.String(d.Get("resource_id").(string)), 184 RestApiId: aws.String(d.Get("rest_api_id").(string)), 185 }) 186 if err != nil { 187 if awsErr, ok := err.(awserr.Error); ok && awsErr.Code() == "NotFoundException" { 188 d.SetId("") 189 return nil 190 } 191 return err 192 } 193 log.Printf("[DEBUG] Received API Gateway Integration: %s", integration) 194 d.SetId(fmt.Sprintf("agi-%s-%s-%s", d.Get("rest_api_id").(string), d.Get("resource_id").(string), d.Get("http_method").(string))) 195 196 // AWS converts "" to null on their side, convert it back 197 if v, ok := integration.RequestTemplates["application/json"]; ok && v == nil { 198 integration.RequestTemplates["application/json"] = aws.String("") 199 } 200 201 d.Set("request_templates", aws.StringValueMap(integration.RequestTemplates)) 202 d.Set("type", integration.Type) 203 d.Set("request_parameters", aws.StringValueMap(integration.RequestParameters)) 204 d.Set("request_parameters_in_json", aws.StringValueMap(integration.RequestParameters)) 205 d.Set("passthrough_behavior", integration.PassthroughBehavior) 206 207 if integration.Uri != nil { 208 d.Set("uri", integration.Uri) 209 } 210 211 if integration.Credentials != nil { 212 d.Set("credentials", integration.Credentials) 213 } 214 215 if integration.ContentHandling != nil { 216 d.Set("content_handling", integration.ContentHandling) 217 } 218 219 return nil 220 } 221 222 func resourceAwsApiGatewayIntegrationUpdate(d *schema.ResourceData, meta interface{}) error { 223 conn := meta.(*AWSClient).apigateway 224 225 log.Printf("[DEBUG] Updating API Gateway Integration: %s", d.Id()) 226 operations := make([]*apigateway.PatchOperation, 0) 227 228 // https://docs.aws.amazon.com/apigateway/api-reference/link-relation/integration-update/#remarks 229 // According to the above documentation, only a few parts are addable / removable. 230 if d.HasChange("request_templates") { 231 o, n := d.GetChange("request_templates") 232 prefix := "requestTemplates" 233 234 os := o.(map[string]interface{}) 235 ns := n.(map[string]interface{}) 236 237 // Handle Removal 238 for k := range os { 239 if _, ok := ns[k]; !ok { 240 operations = append(operations, &apigateway.PatchOperation{ 241 Op: aws.String("remove"), 242 Path: aws.String(fmt.Sprintf("/%s/%s", prefix, strings.Replace(k, "/", "~1", -1))), 243 }) 244 } 245 } 246 247 for k, v := range ns { 248 // Handle replaces 249 if _, ok := os[k]; ok { 250 operations = append(operations, &apigateway.PatchOperation{ 251 Op: aws.String("replace"), 252 Path: aws.String(fmt.Sprintf("/%s/%s", prefix, strings.Replace(k, "/", "~1", -1))), 253 Value: aws.String(v.(string)), 254 }) 255 } 256 257 // Handle additions 258 if _, ok := os[k]; !ok { 259 operations = append(operations, &apigateway.PatchOperation{ 260 Op: aws.String("add"), 261 Path: aws.String(fmt.Sprintf("/%s/%s", prefix, strings.Replace(k, "/", "~1", -1))), 262 Value: aws.String(v.(string)), 263 }) 264 } 265 } 266 } 267 268 if d.HasChange("request_parameters") { 269 o, n := d.GetChange("request_parameters") 270 prefix := "requestParameters" 271 272 os := o.(map[string]interface{}) 273 ns := n.(map[string]interface{}) 274 275 // Handle Removal 276 for k := range os { 277 if _, ok := ns[k]; !ok { 278 operations = append(operations, &apigateway.PatchOperation{ 279 Op: aws.String("remove"), 280 Path: aws.String(fmt.Sprintf("/%s/%s", prefix, strings.Replace(k, "/", "~1", -1))), 281 }) 282 } 283 } 284 285 for k, v := range ns { 286 // Handle replaces 287 if _, ok := os[k]; ok { 288 operations = append(operations, &apigateway.PatchOperation{ 289 Op: aws.String("replace"), 290 Path: aws.String(fmt.Sprintf("/%s/%s", prefix, strings.Replace(k, "/", "~1", -1))), 291 Value: aws.String(v.(string)), 292 }) 293 } 294 295 // Handle additions 296 if _, ok := os[k]; !ok { 297 operations = append(operations, &apigateway.PatchOperation{ 298 Op: aws.String("add"), 299 Path: aws.String(fmt.Sprintf("/%s/%s", prefix, strings.Replace(k, "/", "~1", -1))), 300 Value: aws.String(v.(string)), 301 }) 302 } 303 } 304 } 305 306 params := &apigateway.UpdateIntegrationInput{ 307 HttpMethod: aws.String(d.Get("http_method").(string)), 308 ResourceId: aws.String(d.Get("resource_id").(string)), 309 RestApiId: aws.String(d.Get("rest_api_id").(string)), 310 PatchOperations: operations, 311 } 312 313 _, err := conn.UpdateIntegration(params) 314 if err != nil { 315 return fmt.Errorf("Error updating API Gateway Integration: %s", err) 316 } 317 318 d.SetId(fmt.Sprintf("agi-%s-%s-%s", d.Get("rest_api_id").(string), d.Get("resource_id").(string), d.Get("http_method").(string))) 319 320 return resourceAwsApiGatewayIntegrationRead(d, meta) 321 } 322 323 func resourceAwsApiGatewayIntegrationDelete(d *schema.ResourceData, meta interface{}) error { 324 conn := meta.(*AWSClient).apigateway 325 log.Printf("[DEBUG] Deleting API Gateway Integration: %s", d.Id()) 326 327 return resource.Retry(5*time.Minute, func() *resource.RetryError { 328 _, err := conn.DeleteIntegration(&apigateway.DeleteIntegrationInput{ 329 HttpMethod: aws.String(d.Get("http_method").(string)), 330 ResourceId: aws.String(d.Get("resource_id").(string)), 331 RestApiId: aws.String(d.Get("rest_api_id").(string)), 332 }) 333 if err == nil { 334 return nil 335 } 336 337 apigatewayErr, ok := err.(awserr.Error) 338 if apigatewayErr.Code() == "NotFoundException" { 339 return nil 340 } 341 342 if !ok { 343 return resource.NonRetryableError(err) 344 } 345 346 return resource.NonRetryableError(err) 347 }) 348 }