简体   繁体   English

使用 Go 任务的 Yaml Azure 管道安装 Terratest 问题 - 在子文件夹中触发 terratest 测试

[英]Issue installing Terratest using Go Task's Yaml Azure pipeline - issue triggering terratest tests in sub-folder

I'm facing this issue while installing terratest by azure yaml pipeline:我在通过 azure yaml 管道安装 terratest 时遇到了这个问题:

C:\hostedtoolcache\windows\go\1.17.1\x64\bin\go.exe install -v github.com/gruntwork-io/terratest@v0.40.6
go: downloading github.com/gruntwork-io/terratest v0.40.6
go install: github.com/gruntwork-io/terratest@v0.40.6: module github.com/gruntwork-io/terratest@v0.40.6 found, but does not contain package github.com/gruntwork-io/terratest
##[error]The Go task failed with an error: Error: The process 'C:\hostedtoolcache\windows\go\1.17.1\x64\bin\go.exe' failed with exit code 1
Finishing: Install Go Terratest module - v0.40.6

My code for installation is bellow:我的安装代码如下:

            - task: Go@0
              displayName: Install Go Terratest module - v$(TERRATEST_VERSION)
              inputs:
                command: custom
                customCommand: install
                arguments: $(TF_LOG) github.com/gruntwork-io/terratest@v$(TERRATEST_VERSION)
                workingDirectory: $(pipeline_artefact_folder_extract)/$(pathToTerraformRootModule)

But peharps I made mistakes in the use of terratest.但是很明显我在使用 terratest 时犯了错误。

Bellow is a screenshot of my code tree:下面是我的代码树的截图:

图片

I have terraform code in (for exemple) Terraform\azure_v2_X\ResourceModules sub-directory , and terratest test in Terraform\azure_v2_X\Tests_Unit_ResourceModules subdirectories (in screenshot app_configuration tests for app_configuration resourceModules).我在(例如) Terraform\azure_v2_X\ResourceModules 子目录中有 terraform 代码,在Terraform\azure_v2_X\Tests_Unit_ResourceModules子目录中有 terratest 测试(在 app_configuration 资源模块的截图 app_configuration 测试中)。

In my terratest module, I'm calling for my resourceModule as in the following code:在我的 terratest 模块中,我正在调用我的 resourceModule,如下面的代码所示:

######test in a un isolated Resource Group defined in locals
module "app_configuration_tobetested" {    
    source = "../../ResourceModules/app_configuration"
    resource_group_name = local.rg_name
    location = local.location
    environment = var.ENVIRONMENT
    sku = "standard"
    // rem : here app_service_shared prefix and app_config_shared prefix are the same !
    app_service_prefix = module.app_configuration_list_fortests.settings.frontEnd_prefix
#    stage = var.STAGE
    app_config_list = module.app_configuration_list_fortests.settings.list_app_config
}

And in my Go file, I test my module result regarding the expected result I want:在我的 Go 文件中,我根据我想要的预期结果测试了我的模块结果:

package RM_app_configuration_Test

import (
    "os"
    "testing"

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

var (
    globalBackendConf = make(map[string]interface{})
    globalEnvVars     = make(map[string]string)
)

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

    // terraform Directory
    fixtureFolder := "./"

    // backend specification
    strlocal := "RMapCfg_"

    // input value
    inputStage       := "sbx_we"
    inputEnvironment := "SBX"
    inputApplication := "DEMO"

    // expected value
    expectedRsgName := "z-adf-ftnd-shrd-sbx-ew1-rgp01"
    //  expectedAppCfgPrefix := "z-adf-ftnd-shrd"
    expectedAppConfigReader_ID := "[/subscriptions/f04c8fd5-d013-41c3-9102-43b25880d2e2/resourceGroups/z-adf-ftnd-shrd-sbx-ew1-rgp01/providers/Microsoft.AppConfiguration/configurationStores/z-adf-ftnd-shrd-sbx-ew1-blue-sbx-cfg01 /subscriptions/f04c8fd5-d013-41c3-9102-43b25880d2e2/resourceGroups/z-adf-ftnd-shrd-sbx-ew1-rgp01/providers/Microsoft.AppConfiguration/configurationStores/z-adf-ftnd-shrd-sbx-ew1-green-sbx-cfg01]"

    // getting enVars from environment variables
    /*
        Go and Terraform uses two differents methods for Azure authentification.
        ** Terraform authentification is explained bellow :
        - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_client_secret#configuring-the-service-principal-in-terraform
        ** Go authentification is explained bellow
        - https://learn.microsoft.com/en-us/azure/developer/go/azure-sdk-authorization#use-environment-based-authentication

        ** Terratest is using both authentification methods regarding the work it has to be done :
        - azure existences tests uses Go azure authentification :
            - https://github.com/gruntwork-io/terratest/blob/master/modules/azure/authorizer.go#L11
        - terraform commands uses terraform authentification :
            - https://github.com/gruntwork-io/terratest/blob/0d654bd2ab781a52e495f61230cf892dfba9731b/modules/terraform/cmd.go#L12
            - https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/guides/service_principal_client_secret#configuring-the-service-principal-in-terraform
        so both authentification methods have to be implemented
    */
    // getting terraform EnvVars from Azure Go environment variables
    ARM_CLIENT_ID := os.Getenv("AZURE_CLIENT_ID")
    ARM_CLIENT_SECRET := os.Getenv("AZURE_CLIENT_SECRET")
    ARM_TENANT_ID := os.Getenv("AZURE_TENANT_ID")
    ARM_SUBSCRIPTION_ID := os.Getenv("ARM_SUBSCRIPTION_ID")

    if ARM_CLIENT_ID != "" {
        globalEnvVars["ARM_CLIENT_ID"] = ARM_CLIENT_ID
        globalEnvVars["ARM_CLIENT_SECRET"] = ARM_CLIENT_SECRET
        globalEnvVars["ARM_SUBSCRIPTION_ID"] = ARM_SUBSCRIPTION_ID
        globalEnvVars["ARM_TENANT_ID"] = ARM_TENANT_ID
    }

    // getting terraform backend from environment variables
    resource_group_name := os.Getenv("resource_group_name")
    storage_account_name := os.Getenv("storage_account_name")
    container_name := os.Getenv("container_name")
    key := strlocal + os.Getenv("key")

    if resource_group_name != "" {
        globalBackendConf["resource_group_name"] = resource_group_name
        globalBackendConf["storage_account_name"] = storage_account_name
        globalBackendConf["container_name"] = container_name
        globalBackendConf["key"] = key
    }

    // User Terratest to deploy the infrastructure
    terraformOptions := terraform.WithDefaultRetryableErrors(t, &terraform.Options{
        // website::tag::1::Set the path to the Terraform code that will be tested.
        // The path to where our Terraform code is located
        TerraformDir: fixtureFolder,
        // Variables to pass to our Terraform code using -var options
        Vars: map[string]interface{}{
            "STAGE":       inputStage,
            "ENVIRONMENT": inputEnvironment,
            "APPLICATION": inputApplication,
        },

        EnvVars: globalEnvVars,

        // backend values to set when initialziing Terraform
        BackendConfig: globalBackendConf,

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

    // website::tag::4::Clean up resources with "terraform destroy". Using "defer" runs the command at the end of the test, whether the test succeeds or fails.
    // At the end of the test, run `terraform destroy` to clean up any resources that were created
    defer terraform.Destroy(t, terraformOptions)

    // website::tag::2::Run "terraform init" and "terraform apply".
    // This will run `terraform init` and `terraform apply` and fail the test if there are any errors
    terraform.InitAndApply(t, terraformOptions)

    // tests the resource_group for the app_configuration
    /*
        actualAppConfigReaderPrefix := terraform.Output(t, terraformOptions, "app_configuration_tested_prefix")
        assert.Equal(t, expectedAppCfgprefix, actualAppConfigReaderPrefix)
    */
    actualRSGReaderName := terraform.Output(t, terraformOptions, "app_configuration_tested_RG_name")
    assert.Equal(t, expectedRsgName, actualRSGReaderName)

    actualAppConfigReader_ID := terraform.Output(t, terraformOptions, "app_configuration_tobetested_id")
    assert.Equal(t, expectedAppConfigReader_ID, actualAppConfigReader_ID)
}

The fact is locally, I can do, from My main folder Terraform\Azure_v2_X\Tests_Unit_ResourceModules the following command to trigger all my tests in a raw:事实上,我可以在本地执行,从我的主文件夹Terraform\Azure_v2_X\Tests_Unit_ResourceModules中执行以下命令以原始方式触发我的所有测试:

  • (from Go v1.11 ) (来自Go v1.11
Go test ./...

With Go version 1.12, I could set GO111MODULE=auto to have the same results.使用 Go 版本 1.12,我可以设置 GO111MODULE=auto 以获得相同的结果。 But with Go 1.17, I have now to set GO111MODULE=off to trigger my tetst.但是对于 Go 1.17,我现在必须设置 GO111MODULE=off 来触发我的测试。

For now, I have 2 main questions that nagging me:现在,我有两个主要问题困扰着我:

  1. How can I Go import Terratest (and other) modules from azure Pipeline?我 Go 如何从 azure 管道导入 Terratest(和其他)模块?

  2. What I have to do to correctly use Go Modules with terratest?我必须做些什么才能正确使用带有 terratest 的 Go 模块? I have no Go code in my main folder _Terraform\Azure_v2_X\Tests_Unit_ResourceModules_ and would like to trigger all the sub_folder go tests in a simple command line in my Azure Pipeline.我的主文件夹 _Terraform\Azure_v2_X\Tests_Unit_ResourceModules_ 中没有 Go 代码,我想在我的 Azure 管道中的一个简单命令行中触发所有子文件夹 go 测试。

Thank you for any help you could give.感谢您提供的任何帮助。

Best regards,最好的祝福,

I will once again answer my own question.我将再次回答我自己的问题。 :D :D

so, for now, using the following versions:所以,现在,使用以下版本:

  • -- GOVERSION: 1.17.1 -- 治理:1.17.1
  • -- TERRAFORM_VERSION: 1.1.7 -- 地形版本:1.1.7
  • -- TERRATEST_VERSION: 0.40.6 -- TERRATEST_VERSION:0.40.6

The folder hierarchy has changed the following, regarding terratest tests:文件夹层次结构已更改以下内容,关于 terratest 测试:

在此处输入图像描述

I do no longer try to Go import my Terratest module.我不再尝试 Go 导入我的 Terratest 模块。 (so point 1) above is ansered, obviously) (所以上面的第 1 点很明显)

I now just have to:我现在只需要:

  1. Go mod each of my terratest modules Go 修改我的每个 terratest 模块
  2. Trigger each of them individually one by one, using script使用脚本一个一个地触发它们中的每一个

so my pipeline just became the following:所以我的管道变成了以下内容:

    - task: ms-devlabs.custom-terraform-tasks.custom-terraform-installer-task.TerraformInstaller@0
      displayName: Install Terraform $(TERRAFORM_VERSION)
      inputs:
         terraformVersion: $(TERRAFORM_VERSION)

    - task: GoTool@0
      displayName: 'Use Go $(GOVERSION)'
      inputs:
        version: $(GOVERSION)
        goPath: $(GOPATH)
        goBin: $(GOBIN)

    - task: PowerShell@2
      displayName: run Terratest for $(pathToTerraformRootModule)
      inputs:
        targettype : 'filePath'
        filePath: $(pipeline_artefact_folder_extract)/$(pathToTerraformRootModule)/$(Run_Terratest_script)
        workingDirectory: $(pipeline_artefact_folder_extract)/$(pathToTerraformRootModule)
      env:
        # see https://learn.microsoft.com/en-us/azure/developer/go/azure-sdk-authorization#use-environment-based-authentication
        # for Azure authentification with Go
        ARM_SUBSCRIPTION_ID: $(TF_VAR_ARM_SUBSCRIPTION_ID)
        AZURE_CLIENT_ID: $(TF_VAR_ARM_CLIENT_ID)
        AZURE_TENANT_ID: $(TF_VAR_ARM_TENANT_ID)
        AZURE_CLIENT_SECRET: $(TF_VAR_ARM_CLIENT_SECRET) # set as pipeline secret
        resource_group_name: $(storageAccountResourceGroup)
        storage_account_name: $(storageAccount)
        container_name: $(stateBlobContainer)
        key: '$(MODULE)-$(TF_VAR_APPLICATION)-$(TF_VAR_ENVIRONMENT).tfstate'
        GO111MODULE: 'auto'

And in my main folder for my terratest sub-folders, I have the run_terratests.ps1 script and the Terratests list file as bellow:在我的 terratest 子文件夹的主文件夹中,我有run_terratests.ps1脚本和Terratests列表文件,如下所示:

run_terratests.ps1 run_terratests.ps1

# this file is based on https://github.com/google/go-cloud/blob/master/internal/testing/runchecks.sh
#
# This script runs all go Terratest suites,
# compatibility checks, consistency checks, Wire, etc.

$moduleListFile = "./Terratests"
# regex to filter : not began with #
$regexFilter = "^[^#]"

# read the ModuleListFile
[object] $arrayFromFile = Get-Content -Path $moduleListFile | Where-Object { $_ -match $regexFilter} | ConvertFrom-String -PropertyNames folder, totest

$result = 0 # set no error by default
# get the actual folder 
$main_path = Get-Location | select -ExpandProperty "Path"
#read the array to show if to be tested !
foreach ($line in $arrayFromFile) {
    # write-Host $line
    if ($line.totest -eq "yes") {
        $path = $line.folder
        set-location $main_path\$path
        $myPath = Get-Location
        # Write-Host $myPath
        # trigger terratest for files
        Go test ./...
    }
    if ($false -eq $?)
    {
        $result = 1
    }    
}
# back to school :D
set-location $main_path

if ($result -eq 1)
{
    Write-Error "Msbuild exit code indicate test failure."
    Write-Host "##vso[task.logissue type=error]Msbuild exit code indicate test failure."
    exit(1)
}

the code代码

  if ($false -eq $?)
    {
        $result = 1
    }  

is usefull to make the pipeline fail on test error without escaping the other tests.对于在没有 escaping 其他测试的情况下使管道因测试错误而失败很有用。

Terratests地测

# this file lists all the modules to be tested in the "Tests_Unit_ConfigHelpers" repository.
# it us used by the "run_terratest.ps1" powershell script to trigger terratest for each test.
#
# Any line that doesn't begin with a '#' character and isn't empty is treated
# as a path relative to the top of the repository that has a module in it.
# The 'tobetested' field specifies whether this is a module that have to be tested.
#
# this file is based on https://github.com/google/go-cloud/blob/master/allmodules

# module-directory              tobetested
azure_constants                     yes
configure_app_srv_etc               yes
configure_frontdoor_etc             yes
configure_hostnames                 yes
constants                           yes
FrontEnd_AppService_slots/_main     yes
FrontEnd_AppService_slots/settings  yes
merge_maps_of_strings               yes
name                                yes
name_template                       yes
network/hostname_generator          yes
network/hostnames_generator         yes
replace_2vars_into_string_etc       yes
replace_var_into_string_etc         yes
sorting_map_with_an_other_map       yes

And the change in each terratest folder is that I will add the go.mod and go.sum files:每个 terratest 文件夹的变化是我将添加 go.mod 和 go.sum 文件:

$ go mod init mytest
go: creating new go.mod: module mytest
go: to add module requirements and sums:
go mod tidy

and

$ go mod tidy
# link each of the go modules needed for your terratest module

so, with that, the go test./... from the powershell script will downlaod the needed go modules and run the test for that particulary test.因此, go test./...来自 powershell 脚本将下载所需的 go 模块并运行该特定测试的测试。

Thanks for reading and vote if you think that can help:)感谢阅读,如果您认为有帮助,请投票:)

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

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