diff --git a/.github/actions/lint-provider-tfe/action.yml b/.github/actions/lint-provider-tfe/action.yml index 502fc4cae..73a08659a 100644 --- a/.github/actions/lint-provider-tfe/action.yml +++ b/.github/actions/lint-provider-tfe/action.yml @@ -11,6 +11,7 @@ runs: with: go-version-file: "go.mod" cache: true + cache-dependency-path: go.sum - name: fmt check run: make fmtcheck @@ -26,5 +27,6 @@ runs: env: GOLANGCILINT_VERSION: v1.64.8 - - run: make lint + - name: Run golangci-lint + run: make lint shell: bash diff --git a/.github/actions/test-provider-tfe/action.yml b/.github/actions/test-provider-tfe/action.yml index 416ec17a6..3351d902e 100644 --- a/.github/actions/test-provider-tfe/action.yml +++ b/.github/actions/test-provider-tfe/action.yml @@ -60,12 +60,12 @@ runs: with: go-version-file: go.mod cache: true + cache-dependency-path: go.sum - name: Sync dependencies shell: bash run: | go mod download - go mod tidy - name: Install gotestsum shell: bash @@ -116,7 +116,7 @@ runs: MOD_TFE: github.com/hashicorp/terraform-provider-tfe/internal/provider MOD_VERSION: github.com/hashicorp/terraform-provider-tfe/version run: | - gotestsum --junitfile summary.xml --format short-verbose -- $MOD_PROVIDER $MOD_TFE $MOD_VERSION -v -timeout=60m -run "${{ steps.test_split.outputs.run }}" + gotestsum --junitfile summary.xml --format short-verbose -- $MOD_PROVIDER $MOD_TFE $MOD_VERSION -v -timeout=60m -parallel=2 -run "${{ steps.test_split.outputs.run }}" - name: Upload test artifacts uses: actions/upload-artifact@65c4c4a1ddee5b72f698fdd19549f0f0fb45cf08 # v4.6.0 diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index ba4d356ee..cb6f00d92 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,8 +25,8 @@ jobs: fail-fast: false matrix: # If you adjust these parameters, also adjust the jrm input files on the "Merge reports" step below - total: [ 1 ] - index: [ 0 ] + total: [ 8 ] + index: [ 0, 1, 2, 3, 4, 5, 6, 7 ] steps: - name: Fetch Outputs id: tflocal @@ -75,7 +75,7 @@ jobs: run: npm install -g junit-report-merger - name: Merge reports - run: jrm ./ci-summary-provider.xml "junit-test-summary-0/*.xml" "junit-test-summary-1/*.xml" "junit-test-summary-2/*.xml" "junit-test-summary-3/*.xml" "junit-test-summary-4/*.xml" + run: jrm ./ci-summary-provider.xml "junit-test-summary-0/*.xml" "junit-test-summary-1/*.xml" "junit-test-summary-2/*.xml" "junit-test-summary-3/*.xml" "junit-test-summary-4/*.xml" "junit-test-summary-5/*.xml" "junit-test-summary-6/*.xml" "junit-test-summary-7/*.xml" - name: Upload test artifacts uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 diff --git a/CHANGELOG.md b/CHANGELOG.md index 68b5498e1..58b798012 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,7 @@ BREAKING CHANGES: All resources have been upgraded to use the [latest Terraform plugin protocol](https://developer.hashicorp.com/terraform/plugin/terraform-plugin-protocol). This provider now requires a Terraform version of v1.0.0 or later. ENHANCEMENTS: +* `r/tfe_registry_module`: Add support for `agent_execution_mode` and `agent_pool_id` attributes in `test_config` block to enable running registry module tests on custom agent pools. By @hashimoon [#1832](https://github.com/hashicorp/terraform-provider-tfe/pull/1832) * `r/tfe_oauth_client`: The `oauth_token` attribute no longer triggers resource replacement unless combined with other replacement-triggering attributes. Use `terraform apply -replace` to force replacement. By @lilincmu [#1825](https://github.com/hashicorp/terraform-provider-tfe/pull/1825) FEATURES: diff --git a/internal/provider/resource_tfe_registry_module.go b/internal/provider/resource_tfe_registry_module.go index 582b60d26..e2639a3b6 100644 --- a/internal/provider/resource_tfe_registry_module.go +++ b/internal/provider/resource_tfe_registry_module.go @@ -33,7 +33,10 @@ func resourceTFERegistryModule() *schema.Resource { }, CustomizeDiff: func(c context.Context, d *schema.ResourceDiff, meta interface{}) error { - return validateVcsRepo(d) + if err := validateVcsRepo(d); err != nil { + return err + } + return validateTestConfig(d) }, Schema: map[string]*schema.Schema{ "organization": { @@ -146,6 +149,19 @@ func resourceTFERegistryModule() *schema.Resource { Type: schema.TypeBool, Optional: true, }, + "agent_execution_mode": { + Type: schema.TypeString, + Optional: true, + Computed: true, + ValidateFunc: validation.StringInSlice( + []string{"agent", "remote"}, + false, + ), + }, + "agent_pool_id": { + Type: schema.TypeString, + Optional: true, + }, }, }, }, @@ -212,9 +228,21 @@ func resourceTFERegistryModuleCreateWithVCS(v interface{}, meta interface{}, d * options.VCSRepo.OAuthTokenID = tfe.String(vcsRepo["oauth_token_id"].(string)) } - if testsEnabled, ok := testConfig["tests_enabled"].(bool); ok { - options.TestConfig = &tfe.RegistryModuleTestConfigOptions{ - TestsEnabled: tfe.Bool(testsEnabled), + if testConfig != nil { + options.TestConfig = &tfe.RegistryModuleTestConfigOptions{} + + if testsEnabled, ok := testConfig["tests_enabled"].(bool); ok { + options.TestConfig.TestsEnabled = tfe.Bool(testsEnabled) + } + + if agentExecutionMode, ok := testConfig["agent_execution_mode"].(string); ok && agentExecutionMode != "" { + mode := tfe.AgentExecutionMode(agentExecutionMode) + options.TestConfig.AgentExecutionMode = &mode + } + + // Handle agent pool ID - only set if explicitly provided and not empty + if agentPoolID, ok := testConfig["agent_pool_id"].(string); ok && agentPoolID != "" { + options.TestConfig.AgentPoolID = tfe.String(agentPoolID) } } @@ -224,6 +252,7 @@ func resourceTFERegistryModuleCreateWithVCS(v interface{}, meta interface{}, d * return nil, fmt.Errorf( "Error creating registry module from repository %s: %w", *options.VCSRepo.Identifier, err) } + return registryModule, nil } @@ -357,6 +386,13 @@ func resourceTFERegistryModuleUpdate(d *schema.ResourceData, meta interface{}) e if testsEnabled, ok := testConfig["tests_enabled"].(bool); ok { options.TestConfig.TestsEnabled = tfe.Bool(testsEnabled) } + + if agentExecutionMode, ok := testConfig["agent_execution_mode"].(string); ok && agentExecutionMode != "" { + mode := tfe.AgentExecutionMode(agentExecutionMode) + options.TestConfig.AgentExecutionMode = &mode + } + + handleAgentPoolID(testConfig, d, options.TestConfig) } err = retry.Retry(time.Duration(5)*time.Minute, func() *retry.RetryError { @@ -434,6 +470,13 @@ func resourceTFERegistryModuleRead(d *schema.ResourceData, meta interface{}) err "tests_enabled": registryModule.TestConfig.TestsEnabled, } + if registryModule.TestConfig.AgentExecutionMode != nil { + testConfigValues["agent_execution_mode"] = *registryModule.TestConfig.AgentExecutionMode + } + + if registryModule.TestConfig.AgentPoolID != nil && *registryModule.TestConfig.AgentPoolID != "" { + testConfigValues["agent_pool_id"] = *registryModule.TestConfig.AgentPoolID + } testConfig = append(testConfig, testConfigValues) } @@ -530,3 +573,49 @@ func validateVcsRepo(d *schema.ResourceDiff) error { return nil } + +func validateTestConfig(d *schema.ResourceDiff) error { + testConfig, ok := d.GetRawConfig().AsValueMap()["test_config"] + if !ok || testConfig.LengthInt() == 0 { + return nil + } + + testConfigValue := testConfig.AsValueSlice()[0] + + // Check if test_config block is empty (no tests_enabled field) + testsEnabledValue := testConfigValue.GetAttr("tests_enabled") + if testsEnabledValue.IsNull() { + return fmt.Errorf("tests_enabled must be provided when configuring a test_config") + } + + agentExecutionModeValue := testConfigValue.GetAttr("agent_execution_mode") + agentPoolIDValue := testConfigValue.GetAttr("agent_pool_id") + + // Skip validation if values are unknown (during plan phase) + if !agentExecutionModeValue.IsKnown() || !agentPoolIDValue.IsKnown() { + return nil + } + + if !agentExecutionModeValue.IsNull() && !agentPoolIDValue.IsNull() { + executionMode := agentExecutionModeValue.AsString() + agentPoolID := agentPoolIDValue.AsString() + + if executionMode == "remote" && agentPoolID != "" { + return fmt.Errorf("agent_pool_id cannot be set when agent_execution_mode is 'remote'") + } + } + + return nil +} + +func handleAgentPoolID(testConfig map[string]interface{}, d *schema.ResourceData, options *tfe.RegistryModuleTestConfigOptions) { + if agentPoolID, ok := testConfig["agent_pool_id"].(string); ok { + if agentPoolID != "" { + options.AgentPoolID = tfe.String(agentPoolID) + } else if d.HasChange("test_config.0.agent_pool_id") { + options.AgentPoolID = tfe.String("") + } + } else if d.HasChange("test_config.0.agent_pool_id") { + options.AgentPoolID = tfe.String("") + } +} diff --git a/internal/provider/resource_tfe_registry_module_test.go b/internal/provider/resource_tfe_registry_module_test.go index 686bbc646..72781e1a3 100644 --- a/internal/provider/resource_tfe_registry_module_test.go +++ b/internal/provider/resource_tfe_registry_module_test.go @@ -686,7 +686,7 @@ func TestAccTFERegistryModule_invalidTestConfigOnCreate(t *testing.T) { ProtoV6ProviderFactories: testAccMuxedProviders, Steps: []resource.TestStep{ { - Config: testAccTFERegistryModule_vcsInvalidBranch(rInt), + Config: testAccTFERegistryModule_invalidTestConfig(rInt), ExpectError: regexp.MustCompile(`tests_enabled must be provided when configuring a test_config`), }, }, @@ -713,7 +713,7 @@ func TestAccTFERegistryModule_invalidTestConfigOnUpdate(t *testing.T) { ), }, { - Config: testAccTFERegistryModule_vcsInvalidBranch(rInt), + Config: testAccTFERegistryModule_invalidTestConfig(rInt), ExpectError: regexp.MustCompile(`tests_enabled must be provided when configuring a test_config`), }, }, @@ -1213,7 +1213,7 @@ resource "tfe_registry_module" "foobar" { envGithubRegistryModuleIdentifer, envGithubRegistryModuleIdentifer) } -func testAccTFERegistryModule_vcsInvalidBranch(rInt int) string { +func testAccTFERegistryModule_invalidTestConfig(rInt int) string { return fmt.Sprintf(` resource "tfe_organization" "foobar" { name = "tst-terraform-%d" @@ -1767,6 +1767,129 @@ resource "tfe_registry_module" "foobar" { }` } +func TestAccTFERegistryModule_agentExecutionModeWithAgentPool(t *testing.T) { + registryModule := &tfe.RegistryModule{} + rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int() + orgName := fmt.Sprintf("tst-terraform-%d", rInt) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheckTFERegistryModule(t) + }, + ProtoV6ProviderFactories: testAccMuxedProviders, + CheckDestroy: testAccCheckTFERegistryModuleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccTFERegistryModule_agentExecutionModeWithAgentPool(orgName, rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckTFERegistryModuleExists( + "tfe_registry_module.foobar", + tfe.RegistryModuleID{ + Organization: orgName, + Name: getRegistryModuleName(), + Provider: getRegistryModuleProvider(), + RegistryName: tfe.PrivateRegistry, + Namespace: orgName, + }, + registryModule, + ), + resource.TestCheckResourceAttr("tfe_registry_module.foobar", "test_config.0.tests_enabled", strconv.FormatBool(true)), + resource.TestCheckResourceAttr("tfe_registry_module.foobar", "test_config.0.agent_execution_mode", "agent"), + resource.TestCheckResourceAttrSet("tfe_registry_module.foobar", "test_config.0.agent_pool_id"), + ), + }, + }, + }) +} + +func TestAccTFERegistryModule_remoteExecutionModeWithoutAgentPool(t *testing.T) { + registryModule := &tfe.RegistryModule{} + rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int() + orgName := fmt.Sprintf("tst-terraform-%d", rInt) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheckTFERegistryModule(t) + }, + ProtoV6ProviderFactories: testAccMuxedProviders, + CheckDestroy: testAccCheckTFERegistryModuleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccTFERegistryModule_remoteExecutionModeWithoutAgentPool(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckTFERegistryModuleExists( + "tfe_registry_module.foobar", + tfe.RegistryModuleID{ + Organization: orgName, + Name: getRegistryModuleName(), + Provider: getRegistryModuleProvider(), + RegistryName: tfe.PrivateRegistry, + Namespace: orgName, + }, + registryModule, + ), + resource.TestCheckResourceAttr("tfe_registry_module.foobar", "test_config.0.tests_enabled", strconv.FormatBool(true)), + resource.TestCheckResourceAttr("tfe_registry_module.foobar", "test_config.0.agent_execution_mode", "remote"), + resource.TestCheckResourceAttr("tfe_registry_module.foobar", "test_config.0.agent_pool_id", ""), + ), + }, + }, + }) +} + +func TestAccTFERegistryModule_agentPoolFieldClearing(t *testing.T) { + registryModule := &tfe.RegistryModule{} + rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int() + orgName := fmt.Sprintf("tst-terraform-%d", rInt) + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheckTFERegistryModule(t) + }, + ProtoV6ProviderFactories: testAccMuxedProviders, + CheckDestroy: testAccCheckTFERegistryModuleDestroy, + Steps: []resource.TestStep{ + { + Config: testAccTFERegistryModule_remoteExecutionModeWithoutAgentPool(rInt), + Check: resource.ComposeTestCheckFunc( + testAccCheckTFERegistryModuleExists( + "tfe_registry_module.foobar", + tfe.RegistryModuleID{ + Organization: orgName, + Name: getRegistryModuleName(), + Provider: getRegistryModuleProvider(), + RegistryName: tfe.PrivateRegistry, + Namespace: orgName, + }, + registryModule, + ), + resource.TestCheckResourceAttr("tfe_registry_module.foobar", "test_config.0.tests_enabled", strconv.FormatBool(true)), + resource.TestCheckResourceAttr("tfe_registry_module.foobar", "test_config.0.agent_execution_mode", "remote"), + resource.TestCheckResourceAttr("tfe_registry_module.foobar", "test_config.0.agent_pool_id", ""), + ), + }, + }, + }) +} + +func TestAccTFERegistryModule_remoteExecutionModeWithAgentPoolError(t *testing.T) { + rInt := rand.New(rand.NewSource(time.Now().UnixNano())).Int() + + resource.Test(t, resource.TestCase{ + PreCheck: func() { + testAccPreCheckTFERegistryModule(t) + }, + ProtoV6ProviderFactories: testAccMuxedProviders, + Steps: []resource.TestStep{ + { + Config: testAccTFERegistryModule_remoteExecutionModeWithAgentPoolErrorSimple(rInt), + PlanOnly: true, + ExpectError: regexp.MustCompile(`agent_pool_id cannot be set when agent_execution_mode is 'remote'`), + }, + }, + }) +} + func testAccTFERegistryModule_invalidWithModuleProviderAndNoName() string { return ` resource "tfe_registry_module" "foobar" { @@ -1804,3 +1927,179 @@ resource "tfe_registry_module" "foobar" { registry_name = "private" }` } + +func testAccTFERegistryModule_agentExecutionModeWithAgentPool(organization string, rInt int) string { + return fmt.Sprintf(` +resource "tfe_organization" "foobar" { + name = "%s" + email = "admin@company.com" +} + +resource "tfe_oauth_client" "foobar" { + organization = tfe_organization.foobar.name + api_url = "https://api.github.com" + http_url = "https://github.com" + oauth_token = "%s" + service_provider = "github" +} + +resource "tfe_agent_pool" "foobar" { + name = "agent-pool-test-%d" + organization = tfe_organization.foobar.name +} + +resource "tfe_registry_module" "foobar" { + organization = tfe_organization.foobar.name + + vcs_repo { + display_identifier = "%s" + identifier = "%s" + oauth_token_id = tfe_oauth_client.foobar.oauth_token_id + branch = "main" + tags = false + } + + initial_version = "1.0.0" + + test_config { + tests_enabled = true + agent_execution_mode = "agent" + agent_pool_id = tfe_agent_pool.foobar.id + } +}`, organization, envGithubToken, rInt, envGithubRegistryModuleIdentifer, envGithubRegistryModuleIdentifer) +} + +func testAccTFERegistryModule_remoteExecutionModeWithoutAgentPool(rInt int) string { + return fmt.Sprintf(` +resource "tfe_organization" "foobar" { + name = "tst-terraform-%d" + email = "admin@company.com" +} + +resource "tfe_oauth_client" "foobar" { + organization = tfe_organization.foobar.name + api_url = "https://api.github.com" + http_url = "https://github.com" + oauth_token = "%s" + service_provider = "github" +} + +resource "tfe_registry_module" "foobar" { + organization = tfe_organization.foobar.name + + vcs_repo { + display_identifier = "%s" + identifier = "%s" + oauth_token_id = tfe_oauth_client.foobar.oauth_token_id + branch = "main" + tags = false + } + + initial_version = "1.0.0" + + test_config { + tests_enabled = true + agent_execution_mode = "remote" + } +}`, rInt, envGithubToken, envGithubRegistryModuleIdentifer, envGithubRegistryModuleIdentifer) +} + +func testAccTFERegistryModule_remoteExecutionModeWithAgentPoolError(organization string, rInt int) string { + return fmt.Sprintf(` +resource "tfe_agent_pool" "foobar" { + name = "agent-pool-test-%d" + organization = "%s" +} + +resource "tfe_registry_module" "foobar" { + organization = "%s" + + vcs_repo { + display_identifier = "%s" + identifier = "%s" + oauth_token_id = "%s" + branch = "main" + tags = false + } + + initial_version = "1.0.0" + + test_config { + tests_enabled = true + agent_execution_mode = "remote" + agent_pool_id = tfe_agent_pool.foobar.id + } +}`, rInt, organization, organization, envGithubRegistryModuleIdentifer, envGithubRegistryModuleIdentifer, envGithubToken) +} + +func testAccTFERegistryModule_remoteExecutionModeWithAgentPoolErrorSimple(rInt int) string { + return fmt.Sprintf(` +resource "tfe_organization" "foobar" { + name = "tst-terraform-%d" + email = "admin@company.com" +} + +resource "tfe_oauth_client" "foobar" { + organization = tfe_organization.foobar.name + api_url = "https://api.github.com" + http_url = "https://github.com" + oauth_token = "%s" + service_provider = "github" +} + +resource "tfe_registry_module" "foobar" { + organization = tfe_organization.foobar.name + + vcs_repo { + display_identifier = "%s" + identifier = "%s" + oauth_token_id = tfe_oauth_client.foobar.oauth_token_id + branch = "main" + tags = false + } + + initial_version = "1.0.0" + + test_config { + tests_enabled = true + agent_execution_mode = "remote" + agent_pool_id = "apool-fake-id" + } +}`, rInt, envGithubToken, envGithubRegistryModuleIdentifer, envGithubRegistryModuleIdentifer) +} + +func testAccTFERegistryModule_agentExecutionModeWithFakeAgentPool(rInt int) string { + return fmt.Sprintf(` +resource "tfe_organization" "foobar" { + name = "tst-terraform-%d" + email = "admin@company.com" +} + +resource "tfe_oauth_client" "foobar" { + organization = tfe_organization.foobar.name + api_url = "https://api.github.com" + http_url = "https://github.com" + oauth_token = "%s" + service_provider = "github" +} + +resource "tfe_registry_module" "foobar" { + organization = tfe_organization.foobar.name + + vcs_repo { + display_identifier = "%s" + identifier = "%s" + oauth_token_id = tfe_oauth_client.foobar.oauth_token_id + branch = "main" + tags = false + } + + initial_version = "1.0.0" + + test_config { + tests_enabled = true + agent_execution_mode = "agent" + agent_pool_id = "apool-fake-id" + } +}`, rInt, envGithubToken, envGithubRegistryModuleIdentifer, envGithubRegistryModuleIdentifer) +} diff --git a/website/docs/r/registry_module.html.markdown b/website/docs/r/registry_module.html.markdown index 8d3720fd0..65fcdedc9 100644 --- a/website/docs/r/registry_module.html.markdown +++ b/website/docs/r/registry_module.html.markdown @@ -9,6 +9,8 @@ description: |- HCP Terraform's private module registry helps you share Terraform modules across your organization. +~> **NOTE:** The `agent_execution_mode` and `agent_pool_id` fields in the `test_config` block are currently in beta and are not available to all users. These features are subject to change or be removed. + ## Example Usage Basic usage with VCS: @@ -66,6 +68,43 @@ resource "tfe_registry_module" "test-registry-module" { } ``` +Create private registry module with agent pool (BETA): + +```hcl +resource "tfe_organization" "test-organization" { + name = "my-org-name" + email = "admin@company.com" +} + +resource "tfe_agent_pool" "test-agent-pool" { + name = "my-agent-pool-name" + organization = tfe_organization.test-organization.name +} + +resource "tfe_oauth_client" "test-oauth-client" { + organization = tfe_organization.test-organization.name + api_url = "https://api.github.com" + http_url = "https://github.com" + oauth_token = "my-vcs-provider-token" + service_provider = "github" +} + +resource "tfe_registry_module" "test-registry-module" { + test_config { + tests_enabled = true + agent_execution_mode = "agent" + agent_pool_id = tfe_agent_pool.test-agent-pool.id + } + + vcs_repo { + display_identifier = "my-org-name/terraform-provider-name" + identifier = "my-org-name/terraform-provider-name" + oauth_token_id = tfe_oauth_client.test-oauth-client.oauth_token_id + branch = "main" + } +} +``` + Create private registry module with GitHub App: ```hcl @@ -156,8 +195,10 @@ The following arguments are supported: * `registry_name` - (Optional) Whether the registry module is private or public. It can be used if `module_provider` is set. * `initial_version` - (Optional) This specifies the initial version for a branch based module. It can be used if `vcs_repo.branch` is set. If it is omitted, the initial modules version will default to `0.0.0`. -The `test_config` block supports +The `test_config` block supports: * `tests_enabled` - (Optional) Specifies whether tests run for the registry module. Tests are only supported for branch-based publishing. +* `agent_execution_mode` - (Optional) Which [execution mode](https://developer.hashicorp.com/terraform/cloud-docs/workspaces/settings#execution-mode) to use for registry module tests. Valid values are `agent` and `remote`. Defaults to `remote`. This feature is currently in beta and is not available to all users. +* `agent_pool_id` - (Optional) The ID of an agent pool to assign to the registry module for testing. Requires `agent_execution_mode` to be set to `agent`. This value _must not_ be provided if `agent_execution_mode` is set to `remote`. This feature is currently in beta and is not available to all users. The `vcs_repo` block supports: @@ -183,6 +224,10 @@ The `vcs_repo` block supports: * `namespace` - The namespace of the module. For private modules this is the name of the organization that owns the module. * `publishing_mechanism` - The publishing mechanism used when releasing new versions of the module. * `registry_name` - The registry name of the registry module depicting whether the registry module is private or public. +* `test_config` - The test configuration for the registry module. + * `tests_enabled` - Whether tests are enabled for the registry module. + * `agent_execution_mode` - The execution mode used for registry module tests. + * `agent_pool_id` - The ID of the agent pool used for registry module tests. * `no_code` - **Deprecated** The property that will enable or disable a module as no-code provisioning ready. Use the tfe_no_code_module resource instead.