简体   繁体   中英

Terratest - How to pass Terraform outputs between functions

I tried to use 'test_structure.SaveTerraformOptions' but it doesn't save resources IDs. For example, I'm running 2 modules - Module 1 creating the networking and the subnets, module 2 needs module's 1 subnets ids. How can I pass this info between them?

When I'm running both functions in the same 'test_structure.RunTestStage' I am able to pass resource id from one function to another, but it doesn't test the first function and doesn't destroy at the end.

I am going to write a helper function that will only load everything and the other functions will do the testing. Maybe this will help.

However, what is the best practice to this?

This is my code:

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)
}

I think the best way you can use the test_structure is separate by stages ( https://pkg.go.dev/github.com/gruntwork-io/terratest/modules/test-structure#RunTestStage ):

  1. Configure terratest, save the options for your specific configuration to 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. Destroy your infra at the end of the testing --> TEARDOWN

     defer test_structure.RunTestStage(t, "TEARDOWN", func() { terraformOptions:= test_structure.LoadTerraformOptions(t, directory) terraform.Destroy(t, terraformOptions) })
  3. Your test cases --> TESTS

     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) }) })

Microsoft have one example more explain https://docs.microsoft.com/en-us/azure/developer/terraform/best-practices-end-to-end-testing :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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