providers/aws/api_gateway.go (410 lines of code) (raw):
// Copyright 2020 The Terraformer Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package aws
import (
"context"
"log"
"strings"
"github.com/GoogleCloudPlatform/terraformer/terraformutils"
"github.com/GoogleCloudPlatform/terraformer/terraformutils/terraformerstring"
"github.com/aws/aws-sdk-go-v2/service/apigateway"
"github.com/aws/aws-sdk-go-v2/service/apigateway/types"
)
var apiGatewayAllowEmptyValues = []string{"tags.", "parent_id", "path_part"}
type APIGatewayGenerator struct {
AWSService
}
func (g *APIGatewayGenerator) InitResources() error {
config, e := g.generateConfig()
if e != nil {
return e
}
svc := apigateway.NewFromConfig(config)
if err := g.loadRestApis(svc); err != nil {
return err
}
if err := g.loadVpcLinks(svc); err != nil {
return err
}
if err := g.loadUsagePlans(svc); err != nil {
return err
}
if err := g.loadAPIKeys(svc); err != nil {
return err
}
return nil
}
func (g *APIGatewayGenerator) loadRestApis(svc *apigateway.Client) error {
p := apigateway.NewGetRestApisPaginator(svc, &apigateway.GetRestApisInput{})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return err
}
for _, restAPI := range page.Items {
if g.shouldFilterRestAPI(restAPI.Tags) {
continue
}
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
*restAPI.Id,
*restAPI.Id+"_"+*restAPI.Name,
"aws_api_gateway_rest_api",
"aws",
apiGatewayAllowEmptyValues))
if err := g.loadStages(svc, restAPI.Id); err != nil {
return err
}
if err := g.loadResources(svc, restAPI.Id); err != nil {
return err
}
if err := g.loadModels(svc, restAPI.Id); err != nil {
return err
}
if err := g.loadResponses(svc, restAPI.Id); err != nil {
return err
}
if err := g.loadDocumentationParts(svc, restAPI.Id); err != nil {
return err
}
if err := g.loadAuthorizers(svc, restAPI.Id); err != nil {
return err
}
}
}
return nil
}
func (g *APIGatewayGenerator) shouldFilterRestAPI(tags map[string]string) bool {
for _, filter := range g.Filter {
if strings.HasPrefix(filter.FieldPath, "tags.") && filter.IsApplicable("api_gateway_rest_api") {
tagName := strings.Replace(filter.FieldPath, "tags.", "", 1)
if val, ok := tags[tagName]; ok {
return !terraformerstring.ContainsString(filter.AcceptableValues, val)
}
return true
}
}
return false
}
func (g *APIGatewayGenerator) loadStages(svc *apigateway.Client, restAPIID *string) error {
output, err := svc.GetStages(context.TODO(), &apigateway.GetStagesInput{
RestApiId: restAPIID,
})
if err != nil {
return err
}
for _, stage := range output.Item {
stageID := *restAPIID + "/" + StringValue(stage.StageName)
g.Resources = append(g.Resources, terraformutils.NewResource(
stageID,
stageID,
"aws_api_gateway_stage",
"aws",
map[string]string{
"rest_api_id": *restAPIID,
"stage_name": *stage.StageName,
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
}
return nil
}
func (g *APIGatewayGenerator) loadResources(svc *apigateway.Client, restAPIID *string) error {
p := apigateway.NewGetResourcesPaginator(svc, &apigateway.GetResourcesInput{
RestApiId: restAPIID,
})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return err
}
for _, resource := range page.Items {
resourceID := *restAPIID + "/" + *resource.Id
g.Resources = append(g.Resources, terraformutils.NewResource(
resourceID,
resourceID,
"aws_api_gateway_resource",
"aws",
map[string]string{
"path": StringValue(resource.Path),
"path_part": StringValue(resource.PathPart),
"partent_id": StringValue(resource.ParentId),
"rest_api_id": StringValue(restAPIID),
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
err := g.loadResourceMethods(svc, restAPIID, resource)
if err != nil {
log.Println(err)
}
}
}
return nil
}
func (g *APIGatewayGenerator) loadModels(svc *apigateway.Client, restAPIID *string) error {
p := apigateway.NewGetModelsPaginator(svc, &apigateway.GetModelsInput{
RestApiId: restAPIID,
})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return nil
}
for _, model := range page.Items {
resourceID := *restAPIID + "/" + *model.Id
g.Resources = append(g.Resources, terraformutils.NewResource(
resourceID,
resourceID,
"aws_api_gateway_model",
"aws",
map[string]string{
"name": StringValue(model.Name),
"content_type": StringValue(model.ContentType),
"schema": StringValue(model.Schema),
"rest_api_id": StringValue(restAPIID),
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
}
}
return nil
}
func (g *APIGatewayGenerator) loadResourceMethods(svc *apigateway.Client, restAPIID *string, resource types.Resource) error {
for httpMethod, method := range resource.ResourceMethods {
methodID := *restAPIID + "/" + *resource.Id + "/" + httpMethod
authorizationType := "NONE"
if method.AuthorizationType != nil {
authorizationType = *method.AuthorizationType
}
g.Resources = append(g.Resources, terraformutils.NewResource(
methodID,
methodID,
"aws_api_gateway_method",
"aws",
map[string]string{
"rest_api_id": *restAPIID,
"resource_id": *resource.Id,
"http_method": httpMethod,
"authorization": authorizationType,
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
methodDetails, err := svc.GetMethod(context.TODO(), &apigateway.GetMethodInput{
HttpMethod: &httpMethod,
ResourceId: resource.Id,
RestApiId: restAPIID,
})
if err != nil {
return err
}
if methodDetails.MethodIntegration != nil {
typeString := string(methodDetails.MethodIntegration.Type)
g.Resources = append(g.Resources, terraformutils.NewResource(
methodID,
methodID,
"aws_api_gateway_integration",
"aws",
map[string]string{
"rest_api_id": *restAPIID,
"resource_id": *resource.Id,
"http_method": httpMethod,
"type": typeString,
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
integrationDetails, err := svc.GetIntegration(context.TODO(), &apigateway.GetIntegrationInput{
HttpMethod: &httpMethod,
ResourceId: resource.Id,
RestApiId: restAPIID,
})
if err != nil {
return err
}
for responseCode := range integrationDetails.IntegrationResponses {
integrationResponseID := *restAPIID + "/" + *resource.Id + "/" + httpMethod + "/" + responseCode
g.Resources = append(g.Resources, terraformutils.NewResource(
integrationResponseID,
integrationResponseID,
"aws_api_gateway_integration_response",
"aws",
map[string]string{
"rest_api_id": *restAPIID,
"resource_id": *resource.Id,
"http_method": httpMethod,
"status_code": responseCode,
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
}
}
for responseCode := range methodDetails.MethodResponses {
responseID := *restAPIID + "/" + *resource.Id + "/" + httpMethod + "/" + responseCode
g.Resources = append(g.Resources, terraformutils.NewResource(
responseID,
responseID,
"aws_api_gateway_method_response",
"aws",
map[string]string{
"rest_api_id": *restAPIID,
"resource_id": *resource.Id,
"http_method": httpMethod,
"status_code": responseCode,
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
}
}
return nil
}
func (g *APIGatewayGenerator) loadResponses(svc *apigateway.Client, restAPIID *string) error {
var position *string
for {
response, err := svc.GetGatewayResponses(context.TODO(), &apigateway.GetGatewayResponsesInput{
RestApiId: restAPIID,
Position: position,
})
if err != nil {
return err
}
for _, response := range response.Items {
if response.DefaultResponse {
continue
}
responseTypeString := string(response.ResponseType)
responseID := *restAPIID + "/" + responseTypeString
g.Resources = append(g.Resources, terraformutils.NewResource(
responseID,
responseID,
"aws_api_gateway_gateway_response",
"aws",
map[string]string{
"rest_api_id": *restAPIID,
"response_type": responseTypeString,
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
}
position = response.Position
if position == nil {
break
}
}
return nil
}
func (g *APIGatewayGenerator) loadDocumentationParts(svc *apigateway.Client, restAPIID *string) error {
var position *string
for {
response, err := svc.GetDocumentationParts(context.TODO(), &apigateway.GetDocumentationPartsInput{
RestApiId: restAPIID,
Position: position,
})
if err != nil {
return err
}
for _, documentationPart := range response.Items {
documentationPartID := *restAPIID + "/" + *documentationPart.Id
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
documentationPartID,
documentationPartID,
"aws_api_gateway_documentation_part",
"aws",
apiGatewayAllowEmptyValues,
))
}
position = response.Position
if position == nil {
break
}
}
return nil
}
func (g *APIGatewayGenerator) loadAuthorizers(svc *apigateway.Client, restAPIID *string) error {
var position *string
for {
response, err := svc.GetAuthorizers(context.TODO(), &apigateway.GetAuthorizersInput{
RestApiId: restAPIID,
Position: position,
})
if err != nil {
return err
}
for _, authorizer := range response.Items {
g.Resources = append(g.Resources, terraformutils.NewResource(
*authorizer.Id,
*authorizer.Id,
"aws_api_gateway_authorizer",
"aws",
map[string]string{
"rest_api_id": *restAPIID,
"name": StringValue(authorizer.Name),
},
apiGatewayAllowEmptyValues,
map[string]interface{}{},
))
}
position = response.Position
if position == nil {
break
}
}
return nil
}
func (g *APIGatewayGenerator) loadVpcLinks(svc *apigateway.Client) error {
p := apigateway.NewGetVpcLinksPaginator(svc, &apigateway.GetVpcLinksInput{})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return err
}
for _, vpcLink := range page.Items {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
*vpcLink.Id,
*vpcLink.Name,
"aws_api_gateway_vpc_link",
"aws",
apiGatewayAllowEmptyValues))
}
}
return nil
}
func (g *APIGatewayGenerator) loadUsagePlans(svc *apigateway.Client) error {
p := apigateway.NewGetUsagePlansPaginator(svc, &apigateway.GetUsagePlansInput{})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return err
}
for _, usagePlan := range page.Items {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
*usagePlan.Id,
*usagePlan.Name,
"aws_api_gateway_usage_plan",
"aws",
apiGatewayAllowEmptyValues))
}
}
return nil
}
func (g *APIGatewayGenerator) loadAPIKeys(svc *apigateway.Client) error {
p := apigateway.NewGetApiKeysPaginator(svc, &apigateway.GetApiKeysInput{})
for p.HasMorePages() {
page, err := p.NextPage(context.TODO())
if err != nil {
return err
}
for _, apiKey := range page.Items {
g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
*apiKey.Id,
*apiKey.Name,
"aws_api_gateway_api_key",
"aws",
apiGatewayAllowEmptyValues))
}
}
return nil
}