Skip to content

Commit 8e312df

Browse files
committed
[TF-27883] Add agent execution mode and pool to test config
Introduces 'agent_execution_mode' and 'agent_pool_id' fields to the registry module test_config schema, supporting both agent and remote execution modes. Adds validation to prevent agent_pool_id from being set when execution mode is 'remote', updates create, update, and read logic, and provides comprehensive acceptance tests for new behaviors. Also updates dependencies to latest versions.
1 parent 02ebd7e commit 8e312df

File tree

4 files changed

+450
-8
lines changed

4 files changed

+450
-8
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ BREAKING CHANGES:
2121
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.
2222

2323
ENHANCEMENTS:
24+
* `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)
2425
* `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)
2526

2627
FEATURES:

internal/provider/resource_tfe_registry_module.go

Lines changed: 93 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,10 @@ func resourceTFERegistryModule() *schema.Resource {
3333
},
3434

3535
CustomizeDiff: func(c context.Context, d *schema.ResourceDiff, meta interface{}) error {
36-
return validateVcsRepo(d)
36+
if err := validateVcsRepo(d); err != nil {
37+
return err
38+
}
39+
return validateTestConfig(d)
3740
},
3841
Schema: map[string]*schema.Schema{
3942
"organization": {
@@ -146,6 +149,19 @@ func resourceTFERegistryModule() *schema.Resource {
146149
Type: schema.TypeBool,
147150
Optional: true,
148151
},
152+
"agent_execution_mode": {
153+
Type: schema.TypeString,
154+
Optional: true,
155+
Computed: true,
156+
ValidateFunc: validation.StringInSlice(
157+
[]string{"agent", "remote"},
158+
false,
159+
),
160+
},
161+
"agent_pool_id": {
162+
Type: schema.TypeString,
163+
Optional: true,
164+
},
149165
},
150166
},
151167
},
@@ -212,9 +228,21 @@ func resourceTFERegistryModuleCreateWithVCS(v interface{}, meta interface{}, d *
212228
options.VCSRepo.OAuthTokenID = tfe.String(vcsRepo["oauth_token_id"].(string))
213229
}
214230

215-
if testsEnabled, ok := testConfig["tests_enabled"].(bool); ok {
216-
options.TestConfig = &tfe.RegistryModuleTestConfigOptions{
217-
TestsEnabled: tfe.Bool(testsEnabled),
231+
if testConfig != nil {
232+
options.TestConfig = &tfe.RegistryModuleTestConfigOptions{}
233+
234+
if testsEnabled, ok := testConfig["tests_enabled"].(bool); ok {
235+
options.TestConfig.TestsEnabled = tfe.Bool(testsEnabled)
236+
}
237+
238+
if agentExecutionMode, ok := testConfig["agent_execution_mode"].(string); ok && agentExecutionMode != "" {
239+
mode := tfe.AgentExecutionMode(agentExecutionMode)
240+
options.TestConfig.AgentExecutionMode = &mode
241+
}
242+
243+
// Handle agent pool ID - only set if explicitly provided and not empty
244+
if agentPoolID, ok := testConfig["agent_pool_id"].(string); ok && agentPoolID != "" {
245+
options.TestConfig.AgentPoolID = tfe.String(agentPoolID)
218246
}
219247
}
220248

@@ -224,6 +252,7 @@ func resourceTFERegistryModuleCreateWithVCS(v interface{}, meta interface{}, d *
224252
return nil, fmt.Errorf(
225253
"Error creating registry module from repository %s: %w", *options.VCSRepo.Identifier, err)
226254
}
255+
227256
return registryModule, nil
228257
}
229258

@@ -357,6 +386,13 @@ func resourceTFERegistryModuleUpdate(d *schema.ResourceData, meta interface{}) e
357386
if testsEnabled, ok := testConfig["tests_enabled"].(bool); ok {
358387
options.TestConfig.TestsEnabled = tfe.Bool(testsEnabled)
359388
}
389+
390+
if agentExecutionMode, ok := testConfig["agent_execution_mode"].(string); ok && agentExecutionMode != "" {
391+
mode := tfe.AgentExecutionMode(agentExecutionMode)
392+
options.TestConfig.AgentExecutionMode = &mode
393+
}
394+
395+
handleAgentPoolID(testConfig, d, options.TestConfig)
360396
}
361397

362398
err = retry.Retry(time.Duration(5)*time.Minute, func() *retry.RetryError {
@@ -434,6 +470,13 @@ func resourceTFERegistryModuleRead(d *schema.ResourceData, meta interface{}) err
434470
"tests_enabled": registryModule.TestConfig.TestsEnabled,
435471
}
436472

473+
if registryModule.TestConfig.AgentExecutionMode != nil {
474+
testConfigValues["agent_execution_mode"] = *registryModule.TestConfig.AgentExecutionMode
475+
}
476+
477+
if registryModule.TestConfig.AgentPoolID != nil && *registryModule.TestConfig.AgentPoolID != "" {
478+
testConfigValues["agent_pool_id"] = *registryModule.TestConfig.AgentPoolID
479+
}
437480
testConfig = append(testConfig, testConfigValues)
438481
}
439482

@@ -530,3 +573,49 @@ func validateVcsRepo(d *schema.ResourceDiff) error {
530573

531574
return nil
532575
}
576+
577+
func validateTestConfig(d *schema.ResourceDiff) error {
578+
testConfig, ok := d.GetRawConfig().AsValueMap()["test_config"]
579+
if !ok || testConfig.LengthInt() == 0 {
580+
return nil
581+
}
582+
583+
testConfigValue := testConfig.AsValueSlice()[0]
584+
585+
// Check if test_config block is empty (no tests_enabled field)
586+
testsEnabledValue := testConfigValue.GetAttr("tests_enabled")
587+
if testsEnabledValue.IsNull() {
588+
return fmt.Errorf("tests_enabled must be provided when configuring a test_config")
589+
}
590+
591+
agentExecutionModeValue := testConfigValue.GetAttr("agent_execution_mode")
592+
agentPoolIDValue := testConfigValue.GetAttr("agent_pool_id")
593+
594+
// Skip validation if values are unknown (during plan phase)
595+
if !agentExecutionModeValue.IsKnown() || !agentPoolIDValue.IsKnown() {
596+
return nil
597+
}
598+
599+
if !agentExecutionModeValue.IsNull() && !agentPoolIDValue.IsNull() {
600+
executionMode := agentExecutionModeValue.AsString()
601+
agentPoolID := agentPoolIDValue.AsString()
602+
603+
if executionMode == "remote" && agentPoolID != "" {
604+
return fmt.Errorf("agent_pool_id cannot be set when agent_execution_mode is 'remote'")
605+
}
606+
}
607+
608+
return nil
609+
}
610+
611+
func handleAgentPoolID(testConfig map[string]interface{}, d *schema.ResourceData, options *tfe.RegistryModuleTestConfigOptions) {
612+
if agentPoolID, ok := testConfig["agent_pool_id"].(string); ok {
613+
if agentPoolID != "" {
614+
options.AgentPoolID = tfe.String(agentPoolID)
615+
} else if d.HasChange("test_config.0.agent_pool_id") {
616+
options.AgentPoolID = tfe.String("")
617+
}
618+
} else if d.HasChange("test_config.0.agent_pool_id") {
619+
options.AgentPoolID = tfe.String("")
620+
}
621+
}

0 commit comments

Comments
 (0)