简体   繁体   English

Terratest - 使用模拟 AWS 服务

[英]Terratest - Use mock AWS services

I am trying to do AWS resource provisioning through terraform and planning to have a CICD pipeline with terratest unit test cases for the terraform code.我正在尝试通过 terraform 进行 AWS 资源配置,并计划拥有一个 CICD 管道,其中包含用于 terraform 代码的 terratest 单元测试用例。 My problem is I have CloudFront in my infrastructure and it takes about 20 mins for the creation and around the same time for removal.我的问题是我的基础架构中有 CloudFront,创建和删除大约需要 20 分钟。 I don't want the CI build to take around 45 mins just for running unit test cases.我不希望 CI 构建仅仅为了运行单元测试用例而花费大约 45 分钟。

I came across localstack to mock the AWS environment but didn't find ways to point terratest to localstack resources.我遇到了 localstack 来模拟 AWS 环境,但没有找到将 terratest 指向 localstack 资源的方法。 This is what I tried这是我试过的

  • Created a localstack docker container创建了一个 localstack docker 容器
  • Configured the terraform to point to localstack - added endpoint url in the provider section.将 terraform 配置为指向 localstack - 在提供程序部分中添加了端点 url。
  • Applied the terraform config and verified bucket created in the localstack.应用了在 localstack 中创建的 terraform 配置和经过验证的存储桶。
  • Wrote a simple terratest test case to assert if the bucket exists.编写了一个简单的 terratest 测试用例来断言存储桶是否存在。

Terraform code is as follows, Terraform代码如下,

terraform {
  backend "s3" {
    bucket  = "<bucket-name>"
    key     = "state/terraform.tfstate"
    region  = "us-east-1"
    profile = "default"
  }
}

provider "aws" {
  region = "us-east-1"
  s3_force_path_style = true
  skip_metadata_api_check = true
  endpoints {
    s3             = "http://localhost:4572"
  }
}

resource "aws_s3_bucket" "test_bucket" {

  bucket = "test-bucket"
  acl    = "public-read-write"
  cors_rule {
    allowed_headers = ["*"]
    allowed_methods = ["GET", "HEAD", "PUT"]
    allowed_origins = ["*"]
    expose_headers  = ["ETag"]
  }
  region = "us-east-1"
}

output "name" {
  value = "${aws_s3_bucket.test_bucket.bucket}"
}

output "region" {
  value = "${aws_s3_bucket.test_bucket.region}"
}

When the terratest test case as given below was executed a bucket was created in the localstack.当执行下面给出的 terratest 测试用例时,在 localstack 中创建了一个存储桶。 But I couldn't find any api or config that would point the terratest AWS module to localstack endpoints.但是我找不到任何将 terratest AWS 模块指向 localstack 端点的 api 或配置。 AssertS3BucketExists by default check the AWS environment for the bucket and the assertion fails. AssertS3BucketExists 默认检查存储桶的 AWS 环境并且断言失败。

Terratest code is as follows. Terratest代码如下。

package aws

import (
"fmt"
"testing"

"github.com/gruntwork-io/terratest/modules/aws"
"github.com/gruntwork-io/terratest/modules/terraform"
)

func TestWebServer(t *testing.T) {
    terraformOptions := &terraform.Options{
    // The path to where your Terraform code is located
    TerraformDir: ".",
}


terraform.InitAndApply(t, terraformOptions)

name := terraform.Output(t, terraformOptions, "name")
region := terraform.Output(t, terraformOptions, "region")
aws.AssertS3BucketExists(t, region, name)

Any help here would be much appreciated.任何帮助在这里将不胜感激。

To accomplish mocking AWS with terratest without modifying the library, you could use something like moto 's standalone server mode .要在不修改库的情况下使用terratest完成terratest AWS,您可以使用类似moto的独立服务器模式 Since there's no (obvious) way to change endpoints in terratest , it may be necessary to modify local DNS resolution to point endpoints at the local moto server.由于没有(明显的)方法来更改terratest端点,因此可能需要修改本地 DNS 解析以将端点指向本地moto服务器。

With terratest , there's no way to inject a mock AWS into the library itself since the interface used for connecting to AWS is not exposed.使用terratest ,无法将模拟 AWS 注入库本身,因为用于连接到 AWS 的接口未公开。

There's a working PR that will get Terratest to verify resources in Localstack.有一个有效的PR可以让 Terratest 验证 Localstack 中的资源。

You can update your go.mod file with the replace directive to test it.您可以使用替换指令更新 go.mod 文件来测试它。

module github.com/GITHUB_USERNAME/REPO_NAME

go 1.15

require (
    github.com/gruntwork-io/terratest v0.30.0
    github.com/stretchr/testify v1.6.1
)

replace github.com/gruntwork-io/terratest v0.30.0 => github.com/ffernandezcast/terratest v0.28.6-0.20200915124510-25813206bebc

Then update your Terratest test with the following vars to configure the custom endpoints for the aws package.然后使用以下变量更新您的 Terratest 测试以配置aws包的自定义端点。

    var LocalEndpoints = map[string]string{
        "apigateway":     "http://localhost:4566",
        "cloudformation": "http://localhost:4566",
        "cloudwatch":     "http://localhost:4566",
        "dynamodb":       "http://localhost:4566",
        "es":             "http://localhost:4566",
        "firehose":       "http://localhost:4566",
        "iam":            "http://localhost:4566",
        "kinesis":        "http://localhost:4566",
        "lambda":         "http://localhost:4566",
        "route53":        "http://localhost:4566",
        "redshift":       "http://localhost:4566",
        "s3":             "http://localhost:4566",
        "secretsmanager": "http://localhost:4566",
        "ses":            "http://localhost:4566",
        "sns":            "http://localhost:4566",
        "sqs":            "http://localhost:4566",
        "ssm":            "http://localhost:4566",
        "stepfunctions":  "http://localhost:4566",
        "sts":            "http://localhost:4566",
    }
    aws.SetAwsEndpointsOverrides(LocalEndpoints)

Then, run go test and Terratest will now verify resources in LocalStack.然后,运行go test ,Terratest 现在将验证 LocalStack 中的资源。 I detailed more of this here https://jq1.io/posts/go_mod_terratest_localstack/ .我在这里详细介绍了https://jq1.io/posts/go_mod_terratest_localstack/

Hopefully, that PR will be merged into Terratest master branch soon.希望该 PR 将很快合并到 Terratest master分支中。

~jq1 ~jq1

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM