github.com/GoogleCloudPlatform/terraformer@v0.8.18/providers/aws/api_gateway.go (about)

     1  // Copyright 2020 The Terraformer Authors.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //      http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package aws
    16  
    17  import (
    18  	"context"
    19  	"log"
    20  	"strings"
    21  
    22  	"github.com/GoogleCloudPlatform/terraformer/terraformutils"
    23  	"github.com/GoogleCloudPlatform/terraformer/terraformutils/terraformerstring"
    24  	"github.com/aws/aws-sdk-go-v2/service/apigateway"
    25  	"github.com/aws/aws-sdk-go-v2/service/apigateway/types"
    26  )
    27  
    28  var apiGatewayAllowEmptyValues = []string{"tags.", "parent_id", "path_part"}
    29  
    30  type APIGatewayGenerator struct {
    31  	AWSService
    32  }
    33  
    34  func (g *APIGatewayGenerator) InitResources() error {
    35  	config, e := g.generateConfig()
    36  	if e != nil {
    37  		return e
    38  	}
    39  	svc := apigateway.NewFromConfig(config)
    40  
    41  	if err := g.loadRestApis(svc); err != nil {
    42  		return err
    43  	}
    44  	if err := g.loadVpcLinks(svc); err != nil {
    45  		return err
    46  	}
    47  	if err := g.loadUsagePlans(svc); err != nil {
    48  		return err
    49  	}
    50  
    51  	return nil
    52  }
    53  
    54  func (g *APIGatewayGenerator) loadRestApis(svc *apigateway.Client) error {
    55  	p := apigateway.NewGetRestApisPaginator(svc, &apigateway.GetRestApisInput{})
    56  	for p.HasMorePages() {
    57  		page, err := p.NextPage(context.TODO())
    58  		if err != nil {
    59  			return err
    60  		}
    61  		for _, restAPI := range page.Items {
    62  			if g.shouldFilterRestAPI(restAPI.Tags) {
    63  				continue
    64  			}
    65  			g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
    66  				*restAPI.Id,
    67  				*restAPI.Name,
    68  				"aws_api_gateway_rest_api",
    69  				"aws",
    70  				apiGatewayAllowEmptyValues))
    71  			if err := g.loadStages(svc, restAPI.Id); err != nil {
    72  				return err
    73  			}
    74  			if err := g.loadResources(svc, restAPI.Id); err != nil {
    75  				return err
    76  			}
    77  			if err := g.loadModels(svc, restAPI.Id); err != nil {
    78  				return err
    79  			}
    80  			if err := g.loadResponses(svc, restAPI.Id); err != nil {
    81  				return err
    82  			}
    83  			if err := g.loadDocumentationParts(svc, restAPI.Id); err != nil {
    84  				return err
    85  			}
    86  			if err := g.loadAuthorizers(svc, restAPI.Id); err != nil {
    87  				return err
    88  			}
    89  		}
    90  	}
    91  	return nil
    92  }
    93  
    94  func (g *APIGatewayGenerator) shouldFilterRestAPI(tags map[string]string) bool {
    95  	for _, filter := range g.Filter {
    96  		if strings.HasPrefix(filter.FieldPath, "tags.") && filter.IsApplicable("api_gateway_rest_api") {
    97  			tagName := strings.Replace(filter.FieldPath, "tags.", "", 1)
    98  			if val, ok := tags[tagName]; ok {
    99  				return !terraformerstring.ContainsString(filter.AcceptableValues, val)
   100  			}
   101  			return true
   102  		}
   103  	}
   104  	return false
   105  }
   106  
   107  func (g *APIGatewayGenerator) loadStages(svc *apigateway.Client, restAPIID *string) error {
   108  	output, err := svc.GetStages(context.TODO(), &apigateway.GetStagesInput{
   109  		RestApiId: restAPIID,
   110  	})
   111  	if err != nil {
   112  		return err
   113  	}
   114  	for _, stage := range output.Item {
   115  		stageID := *restAPIID + "/" + StringValue(stage.StageName)
   116  		g.Resources = append(g.Resources, terraformutils.NewResource(
   117  			stageID,
   118  			stageID,
   119  			"aws_api_gateway_stage",
   120  			"aws",
   121  			map[string]string{
   122  				"rest_api_id": *restAPIID,
   123  				"stage_name":  *stage.StageName,
   124  			},
   125  			apiGatewayAllowEmptyValues,
   126  			map[string]interface{}{},
   127  		))
   128  	}
   129  	return nil
   130  }
   131  
   132  func (g *APIGatewayGenerator) loadResources(svc *apigateway.Client, restAPIID *string) error {
   133  	p := apigateway.NewGetResourcesPaginator(svc, &apigateway.GetResourcesInput{
   134  		RestApiId: restAPIID,
   135  	})
   136  	for p.HasMorePages() {
   137  		page, err := p.NextPage(context.TODO())
   138  		if err != nil {
   139  			return err
   140  		}
   141  		for _, resource := range page.Items {
   142  			resourceID := *resource.Id
   143  			g.Resources = append(g.Resources, terraformutils.NewResource(
   144  				resourceID,
   145  				resourceID,
   146  				"aws_api_gateway_resource",
   147  				"aws",
   148  				map[string]string{
   149  					"path":        StringValue(resource.Path),
   150  					"path_part":   StringValue(resource.PathPart),
   151  					"partent_id":  StringValue(resource.ParentId),
   152  					"rest_api_id": StringValue(restAPIID),
   153  				},
   154  				apiGatewayAllowEmptyValues,
   155  				map[string]interface{}{},
   156  			))
   157  			err := g.loadResourceMethods(svc, restAPIID, resource)
   158  			if err != nil {
   159  				log.Println(err)
   160  			}
   161  		}
   162  	}
   163  	return nil
   164  }
   165  
   166  func (g *APIGatewayGenerator) loadModels(svc *apigateway.Client, restAPIID *string) error {
   167  	p := apigateway.NewGetModelsPaginator(svc, &apigateway.GetModelsInput{
   168  		RestApiId: restAPIID,
   169  	})
   170  	for p.HasMorePages() {
   171  		page, err := p.NextPage(context.TODO())
   172  		if err != nil {
   173  			return nil
   174  		}
   175  		for _, model := range page.Items {
   176  			resourceID := *model.Id
   177  			g.Resources = append(g.Resources, terraformutils.NewResource(
   178  				resourceID,
   179  				resourceID,
   180  				"aws_api_gateway_model",
   181  				"aws",
   182  				map[string]string{
   183  					"name":         StringValue(model.Name),
   184  					"content_type": StringValue(model.ContentType),
   185  					"schema":       StringValue(model.Schema),
   186  					"rest_api_id":  StringValue(restAPIID),
   187  				},
   188  				apiGatewayAllowEmptyValues,
   189  				map[string]interface{}{},
   190  			))
   191  		}
   192  	}
   193  	return nil
   194  }
   195  
   196  func (g *APIGatewayGenerator) loadResourceMethods(svc *apigateway.Client, restAPIID *string, resource types.Resource) error {
   197  	for httpMethod, method := range resource.ResourceMethods {
   198  		methodID := *restAPIID + "/" + *resource.Id + "/" + httpMethod
   199  		authorizationType := "NONE"
   200  		if method.AuthorizationType != nil {
   201  			authorizationType = *method.AuthorizationType
   202  		}
   203  
   204  		g.Resources = append(g.Resources, terraformutils.NewResource(
   205  			methodID,
   206  			methodID,
   207  			"aws_api_gateway_method",
   208  			"aws",
   209  			map[string]string{
   210  				"rest_api_id":   *restAPIID,
   211  				"resource_id":   *resource.Id,
   212  				"http_method":   httpMethod,
   213  				"authorization": authorizationType,
   214  			},
   215  			apiGatewayAllowEmptyValues,
   216  			map[string]interface{}{},
   217  		))
   218  
   219  		methodDetails, err := svc.GetMethod(context.TODO(), &apigateway.GetMethodInput{
   220  			HttpMethod: &httpMethod,
   221  			ResourceId: resource.Id,
   222  			RestApiId:  restAPIID,
   223  		})
   224  		if err != nil {
   225  			return err
   226  		}
   227  
   228  		if methodDetails.MethodIntegration != nil {
   229  			typeString := string(methodDetails.MethodIntegration.Type)
   230  			g.Resources = append(g.Resources, terraformutils.NewResource(
   231  				methodID,
   232  				methodID,
   233  				"aws_api_gateway_integration",
   234  				"aws",
   235  				map[string]string{
   236  					"rest_api_id": *restAPIID,
   237  					"resource_id": *resource.Id,
   238  					"http_method": httpMethod,
   239  					"type":        typeString,
   240  				},
   241  				apiGatewayAllowEmptyValues,
   242  				map[string]interface{}{},
   243  			))
   244  			integrationDetails, err := svc.GetIntegration(context.TODO(), &apigateway.GetIntegrationInput{
   245  				HttpMethod: &httpMethod,
   246  				ResourceId: resource.Id,
   247  				RestApiId:  restAPIID,
   248  			})
   249  			if err != nil {
   250  				return err
   251  			}
   252  
   253  			for responseCode := range integrationDetails.IntegrationResponses {
   254  				integrationResponseID := *restAPIID + "/" + *resource.Id + "/" + httpMethod + "/" + responseCode
   255  				g.Resources = append(g.Resources, terraformutils.NewResource(
   256  					integrationResponseID,
   257  					integrationResponseID,
   258  					"aws_api_gateway_integration_response",
   259  					"aws",
   260  					map[string]string{
   261  						"rest_api_id": *restAPIID,
   262  						"resource_id": *resource.Id,
   263  						"http_method": httpMethod,
   264  						"status_code": responseCode,
   265  					},
   266  					apiGatewayAllowEmptyValues,
   267  					map[string]interface{}{},
   268  				))
   269  			}
   270  		}
   271  		for responseCode := range methodDetails.MethodResponses {
   272  			responseID := *restAPIID + "/" + *resource.Id + "/" + httpMethod + "/" + responseCode
   273  
   274  			g.Resources = append(g.Resources, terraformutils.NewResource(
   275  				responseID,
   276  				responseID,
   277  				"aws_api_gateway_method_response",
   278  				"aws",
   279  				map[string]string{
   280  					"rest_api_id": *restAPIID,
   281  					"resource_id": *resource.Id,
   282  					"http_method": httpMethod,
   283  					"status_code": responseCode,
   284  				},
   285  				apiGatewayAllowEmptyValues,
   286  				map[string]interface{}{},
   287  			))
   288  		}
   289  	}
   290  	return nil
   291  }
   292  
   293  func (g *APIGatewayGenerator) loadResponses(svc *apigateway.Client, restAPIID *string) error {
   294  	var position *string
   295  	for {
   296  		response, err := svc.GetGatewayResponses(context.TODO(), &apigateway.GetGatewayResponsesInput{
   297  			RestApiId: restAPIID,
   298  			Position:  position,
   299  		})
   300  		if err != nil {
   301  			return err
   302  		}
   303  		for _, response := range response.Items {
   304  			if response.DefaultResponse {
   305  				continue
   306  			}
   307  			responseTypeString := string(response.ResponseType)
   308  			responseID := *restAPIID + "/" + responseTypeString
   309  			g.Resources = append(g.Resources, terraformutils.NewResource(
   310  				responseID,
   311  				responseID,
   312  				"aws_api_gateway_gateway_response",
   313  				"aws",
   314  				map[string]string{
   315  					"rest_api_id":   *restAPIID,
   316  					"response_type": responseTypeString,
   317  				},
   318  				apiGatewayAllowEmptyValues,
   319  				map[string]interface{}{},
   320  			))
   321  		}
   322  		position = response.Position
   323  		if position == nil {
   324  			break
   325  		}
   326  	}
   327  	return nil
   328  }
   329  
   330  func (g *APIGatewayGenerator) loadDocumentationParts(svc *apigateway.Client, restAPIID *string) error {
   331  	var position *string
   332  	for {
   333  		response, err := svc.GetDocumentationParts(context.TODO(), &apigateway.GetDocumentationPartsInput{
   334  			RestApiId: restAPIID,
   335  			Position:  position,
   336  		})
   337  		if err != nil {
   338  			return err
   339  		}
   340  		for _, documentationPart := range response.Items {
   341  			documentationPartID := *restAPIID + "/" + *documentationPart.Id
   342  			g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
   343  				documentationPartID,
   344  				documentationPartID,
   345  				"aws_api_gateway_documentation_part",
   346  				"aws",
   347  				apiGatewayAllowEmptyValues,
   348  			))
   349  		}
   350  		position = response.Position
   351  		if position == nil {
   352  			break
   353  		}
   354  	}
   355  	return nil
   356  }
   357  
   358  func (g *APIGatewayGenerator) loadAuthorizers(svc *apigateway.Client, restAPIID *string) error {
   359  	var position *string
   360  	for {
   361  		response, err := svc.GetAuthorizers(context.TODO(), &apigateway.GetAuthorizersInput{
   362  			RestApiId: restAPIID,
   363  			Position:  position,
   364  		})
   365  		if err != nil {
   366  			return err
   367  		}
   368  		for _, authorizer := range response.Items {
   369  			g.Resources = append(g.Resources, terraformutils.NewResource(
   370  				*authorizer.Id,
   371  				*authorizer.Id,
   372  				"aws_api_gateway_authorizer",
   373  				"aws",
   374  				map[string]string{
   375  					"rest_api_id": *restAPIID,
   376  					"name":        StringValue(authorizer.Name),
   377  				},
   378  				apiGatewayAllowEmptyValues,
   379  				map[string]interface{}{},
   380  			))
   381  		}
   382  		position = response.Position
   383  		if position == nil {
   384  			break
   385  		}
   386  	}
   387  	return nil
   388  }
   389  
   390  func (g *APIGatewayGenerator) loadVpcLinks(svc *apigateway.Client) error {
   391  	p := apigateway.NewGetVpcLinksPaginator(svc, &apigateway.GetVpcLinksInput{})
   392  	for p.HasMorePages() {
   393  		page, err := p.NextPage(context.TODO())
   394  		if err != nil {
   395  			return err
   396  		}
   397  		for _, vpcLink := range page.Items {
   398  			g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
   399  				*vpcLink.Id,
   400  				*vpcLink.Name,
   401  				"aws_api_gateway_vpc_link",
   402  				"aws",
   403  				apiGatewayAllowEmptyValues))
   404  		}
   405  	}
   406  	return nil
   407  }
   408  
   409  func (g *APIGatewayGenerator) loadUsagePlans(svc *apigateway.Client) error {
   410  	p := apigateway.NewGetUsagePlansPaginator(svc, &apigateway.GetUsagePlansInput{})
   411  	for p.HasMorePages() {
   412  		page, err := p.NextPage(context.TODO())
   413  		if err != nil {
   414  			return err
   415  		}
   416  		for _, usagePlan := range page.Items {
   417  			g.Resources = append(g.Resources, terraformutils.NewSimpleResource(
   418  				*usagePlan.Id,
   419  				*usagePlan.Name,
   420  				"aws_api_gateway_usage_plan",
   421  				"aws",
   422  				apiGatewayAllowEmptyValues))
   423  		}
   424  	}
   425  	return nil
   426  }