【问题标题】:Terratest - How to pass Terraform outputs between functionsTerratest - 如何在函数之间传递 Terraform 输出
【发布时间】:2022-05-13 07:20:56
【问题描述】:

我尝试使用“test_structure.SaveTerraformOptions”,但它不保存资源 ID。例如,我正在运行 2 个模块 - 模块 1 创建网络和子网,模块 2 需要模块的 1 个子网 ID。我如何在他们之间传递这些信息?

当我在同一个 'test_structure.RunTestStage' 中运行这两个函数时,我可以将资源 ID 从一个函数传递到另一个函数,但它不会测试第一个函数,也不会在最后销毁。

我将编写一个辅助函数,它只会加载所有内容和其他函数 将进行测试。也许这会有所帮助。

但是,最好的做法是什么?

这是我的代码:

package test

import (
    "testing"

    //"github.com/gruntwork-io/terratest/modules/random"

    "github.com/gruntwork-io/terratest/modules/azure"
    "github.com/gruntwork-io/terratest/modules/terraform"
    test_structure "github.com/gruntwork-io/terratest/modules/test-structure"
    "github.com/stretchr/testify/assert"
)

// An example of how to test the simple Terraform module in examples/terraform-basic-example using Terratest.

func TestRunAll(t *testing.T) {
    t.Parallel()

    environmentName := "dev"
    projectName := "toha"
    rgName := environmentName + "-" + projectName + "-rg"
    subscriptionID := "96b72f1a-1bdc-4fc7-b971-05e7cea7d850"

    rg_net := test_structure.CopyTerraformFolderToTemp(t, "../", "001_networking")

    test_structure.RunTestStage(t, "test_azure_resource_group", func() {
        terraformOptions := testAzureResourceGroup(t, rgName, subscriptionID)
        test_structure.SaveTerraformOptions(t, rg_net, terraformOptions)
        
        testTerraformAzureFunctionApp(t, rgName, terraformOptions)
        terraform.Destroy(t, terraformOptions)
    })
}

func testAzureResourceGroup(t *testing.T, rgName string, subscriptionID string) *terraform.Options {

    //uniquePostfix := strings.ToLower(random.UniqueId())
    terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{

        TerraformDir: "../001_networking",

        Vars: map[string]interface{}{
            "rg_name": rgName,
        },

        VarFiles: []string{"../../environments/dev/vars.tfvars"},

        // Disable colors in Terraform commands so its easier to parse stdout/stderr
        NoColor: true,
    })

    terraform.InitAndApply(t, terraformOptions)
    rg_name_out := terraform.Output(t, terraformOptions, "rg-name")

    assert.Equal(t, rgName, rg_name_out)

    return terraformOptions
}

func testTerraformAzureFunctionApp(t *testing.T, rgName string, netOpts *terraform.Options) {

    azurePortalIPRange := []string{"61.100.129.0/24"}

    subnet_1 := terraform.Output(t, netOpts, "azurerm_subnet_1")
    subnet_2 := terraform.Output(t, netOpts, "azurerm_subnet_2")

    terraformOptions := &terraform.Options{
        TerraformDir: "../002_function_app",

        Vars: map[string]interface{}{
            "subnet_id_1":           subnet_1,
            "subnet_id_2":           subnet_2,
            "rg_name":               rgName,
            "azure_portal_ip_range": azurePortalIPRange,
            "cosmos_db_endpoint":    "test",
            "cosmos_db_password":    "test",
        },

        VarFiles: []string{"../../environments/dev/vars.tfvars"},
    }

    defer terraform.Destroy(t, terraformOptions)
    terraform.InitAndApply(t, terraformOptions)

    resourceGroupName := terraform.Output(t, terraformOptions, "resource_group_name")
    appName := terraform.Output(t, terraformOptions, "function_app_name")

    appId := terraform.Output(t, terraformOptions, "function_app_id")
    appDefaultHostName := terraform.Output(t, terraformOptions, "default_hostname")
    appKind := terraform.Output(t, terraformOptions, "function_app_kind")

    // website::tag::4:: Assert
    assert.True(t, azure.AppExists(t, appName, resourceGroupName, ""))
    site := azure.GetAppService(t, appName, resourceGroupName, "")

    assert.Equal(t, appId, *site.ID)
    assert.Equal(t, appDefaultHostName, *site.DefaultHostName)
    assert.Equal(t, appKind, *site.Kind)

    assert.NotEmpty(t, *site.OutboundIPAddresses)
    assert.Equal(t, "Running", *site.State)
}

【问题讨论】:

    标签: go terratest


    【解决方案1】:

    我认为使用 test_structure 的最佳方式是分阶段 (https://pkg.go.dev/github.com/gruntwork-io/terratest/modules/test-structure#RunTestStage):

    1. 配置terratest,将特定配置的选项保存到terraform --> SETUP

      test_structure.RunTestStage(t, "SETUP", func() {
         terraformOption := &terraform.Options{
            TerraformDir: "your/path/here",
      }
      test_structure.SaveTerraformOptions(t, directory, terraformOption)
         terraform.InitAndApply(t, terraformOption)
      })
      
    2. 在测试结束时销毁你的基础设施 --> TEARDOWN

      defer test_structure.RunTestStage(t, "TEARDOWN", func() {
          terraformOptions := test_structure.LoadTerraformOptions(t, directory)
             terraform.Destroy(t, terraformOptions)
      })
      
    3. 您的测试用例 --> 测试

      test_structure.RunTestStage(t, "TESTS", func() {
           terraformOption := test_structure.LoadTerraformOptions(t, "your/path/")
      
           // Your outputs
           resourceGroupName := terraform.Output(t, terraformOptions, "resource_group_name")
           appName := terraform.Output(t, terraformOptions, "function_app_name")
           appId := terraform.Output(t, terraformOptions, "function_app_id")
      
           // your functions
           // it can receive the outputs or anything
           t.Run("Test1", func(t *testing.T) {
             testAzureResourceGroup(t, resourceGroupName, subscriptionID)
           })
      
           t.Run("Test2", func(t *testing.T) {
             testTerraformAzureFunctionApp(t, appId, appName)
           })
      })
      

    微软还有一个例子解释https://docs.microsoft.com/en-us/azure/developer/terraform/best-practices-end-to-end-testing:)

    【讨论】:

      猜你喜欢
      • 2022-01-18
      • 2021-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多