-
Notifications
You must be signed in to change notification settings - Fork 161
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
support for organization-level default execution mode and agent pool #1137
Changes from all commits
c819ce6
e09d1b9
1e3c62c
7d6056e
7e14b3a
c25d26c
bd56db5
ca9e73d
8f432dc
70d8c7e
7f5df02
f6d3bd9
cdd8f1b
4d4d4df
938dc89
9c38d83
37019aa
9d1b0d4
ca721a3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,8 +2,13 @@ | |
<!-- Add CHANGELOG entry to this section for any PR awaiting the next release --> | ||
<!-- Please also include if this is a Bug Fix, Enhancement, or Feature --> | ||
|
||
BREAKING CHANGES: | ||
* `r/tfe_workspace`: Default value of the `execution_mode` field now uses the organization's `default_execution_mode`. If no `default_execution_mode` has been set, the default `execution_mode` will be unchanged (i.e. `remote`). | ||
|
||
FEATURES: | ||
* `d/tfe_registry_module`: Add `vcs_repo.tags` and `vcs_repo.branch` attributes to allow configuration of `publishing_mechanism`. Add `test_config` to support running tests on `branch`-based registry modules, by @hashimoon [1096](https://github.com/hashicorp/terraform-provider-tfe/pull/1096) | ||
* **New Resource**: `r/tfe_organization_default_execution_mode` is a new resource to set the `default_execution_mode` and `default_agent_pool_id` for an organization, by @SwiftEngineer [1137](https://github.com/hashicorp/terraform-provider-tfe/pull/1137)' | ||
* `r/tfe_workspace`: Now uses the organization's `default_execution_mode` and `default_agent_pool_id` as the default `execution_mode`, by @SwiftEngineer [1137](https://github.com/hashicorp/terraform-provider-tfe/pull/1137)' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a breaking change which should be highlighted There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think this breaks the API of the provider or the platform API itself because it's a purely additive change. If you don't change the default at the org level, everything continues to behave as before. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yeah but what if someone does? 🙂 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That's a fair point. Previously, I was thinking setting the default |
||
|
||
## v0.50.0 | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -106,44 +106,45 @@ func Provider() *schema.Provider { | |
}, | ||
|
||
ResourcesMap: map[string]*schema.Resource{ | ||
"tfe_admin_organization_settings": resourceTFEAdminOrganizationSettings(), | ||
"tfe_agent_pool": resourceTFEAgentPool(), | ||
"tfe_agent_pool_allowed_workspaces": resourceTFEAgentPoolAllowedWorkspaces(), | ||
"tfe_agent_token": resourceTFEAgentToken(), | ||
"tfe_notification_configuration": resourceTFENotificationConfiguration(), | ||
"tfe_oauth_client": resourceTFEOAuthClient(), | ||
"tfe_organization": resourceTFEOrganization(), | ||
"tfe_organization_membership": resourceTFEOrganizationMembership(), | ||
"tfe_organization_module_sharing": resourceTFEOrganizationModuleSharing(), | ||
"tfe_organization_run_task": resourceTFEOrganizationRunTask(), | ||
"tfe_organization_token": resourceTFEOrganizationToken(), | ||
"tfe_policy": resourceTFEPolicy(), | ||
"tfe_policy_set": resourceTFEPolicySet(), | ||
"tfe_policy_set_parameter": resourceTFEPolicySetParameter(), | ||
"tfe_project": resourceTFEProject(), | ||
"tfe_project_policy_set": resourceTFEProjectPolicySet(), | ||
"tfe_project_variable_set": resourceTFEProjectVariableSet(), | ||
"tfe_registry_module": resourceTFERegistryModule(), | ||
"tfe_no_code_module": resourceTFENoCodeModule(), | ||
"tfe_run_trigger": resourceTFERunTrigger(), | ||
"tfe_sentinel_policy": resourceTFESentinelPolicy(), | ||
"tfe_ssh_key": resourceTFESSHKey(), | ||
"tfe_team": resourceTFETeam(), | ||
"tfe_team_access": resourceTFETeamAccess(), | ||
"tfe_team_organization_member": resourceTFETeamOrganizationMember(), | ||
"tfe_team_organization_members": resourceTFETeamOrganizationMembers(), | ||
"tfe_team_project_access": resourceTFETeamProjectAccess(), | ||
"tfe_team_member": resourceTFETeamMember(), | ||
"tfe_team_members": resourceTFETeamMembers(), | ||
"tfe_team_token": resourceTFETeamToken(), | ||
"tfe_terraform_version": resourceTFETerraformVersion(), | ||
"tfe_workspace": resourceTFEWorkspace(), | ||
"tfe_workspace_run_task": resourceTFEWorkspaceRunTask(), | ||
"tfe_variable_set": resourceTFEVariableSet(), | ||
"tfe_workspace_policy_set": resourceTFEWorkspacePolicySet(), | ||
"tfe_workspace_policy_set_exclusion": resourceTFEWorkspacePolicySetExclusion(), | ||
"tfe_workspace_run": resourceTFEWorkspaceRun(), | ||
"tfe_workspace_variable_set": resourceTFEWorkspaceVariableSet(), | ||
"tfe_admin_organization_settings": resourceTFEAdminOrganizationSettings(), | ||
"tfe_agent_pool": resourceTFEAgentPool(), | ||
"tfe_agent_pool_allowed_workspaces": resourceTFEAgentPoolAllowedWorkspaces(), | ||
"tfe_agent_token": resourceTFEAgentToken(), | ||
"tfe_notification_configuration": resourceTFENotificationConfiguration(), | ||
"tfe_oauth_client": resourceTFEOAuthClient(), | ||
"tfe_organization": resourceTFEOrganization(), | ||
"tfe_organization_default_execution_mode": resourceTFEOrganizationDefaultExecutionMode(), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ^ the only line that really changed |
||
"tfe_organization_membership": resourceTFEOrganizationMembership(), | ||
"tfe_organization_module_sharing": resourceTFEOrganizationModuleSharing(), | ||
"tfe_organization_run_task": resourceTFEOrganizationRunTask(), | ||
"tfe_organization_token": resourceTFEOrganizationToken(), | ||
"tfe_policy": resourceTFEPolicy(), | ||
"tfe_policy_set": resourceTFEPolicySet(), | ||
"tfe_policy_set_parameter": resourceTFEPolicySetParameter(), | ||
"tfe_project": resourceTFEProject(), | ||
"tfe_project_policy_set": resourceTFEProjectPolicySet(), | ||
"tfe_project_variable_set": resourceTFEProjectVariableSet(), | ||
"tfe_registry_module": resourceTFERegistryModule(), | ||
"tfe_no_code_module": resourceTFENoCodeModule(), | ||
"tfe_run_trigger": resourceTFERunTrigger(), | ||
"tfe_sentinel_policy": resourceTFESentinelPolicy(), | ||
"tfe_ssh_key": resourceTFESSHKey(), | ||
"tfe_team": resourceTFETeam(), | ||
"tfe_team_access": resourceTFETeamAccess(), | ||
"tfe_team_organization_member": resourceTFETeamOrganizationMember(), | ||
"tfe_team_organization_members": resourceTFETeamOrganizationMembers(), | ||
"tfe_team_project_access": resourceTFETeamProjectAccess(), | ||
"tfe_team_member": resourceTFETeamMember(), | ||
"tfe_team_members": resourceTFETeamMembers(), | ||
"tfe_team_token": resourceTFETeamToken(), | ||
"tfe_terraform_version": resourceTFETerraformVersion(), | ||
"tfe_workspace": resourceTFEWorkspace(), | ||
"tfe_workspace_run_task": resourceTFEWorkspaceRunTask(), | ||
"tfe_variable_set": resourceTFEVariableSet(), | ||
"tfe_workspace_policy_set": resourceTFEWorkspacePolicySet(), | ||
"tfe_workspace_policy_set_exclusion": resourceTFEWorkspacePolicySetExclusion(), | ||
"tfe_workspace_run": resourceTFEWorkspaceRun(), | ||
"tfe_workspace_variable_set": resourceTFEWorkspaceVariableSet(), | ||
}, | ||
ConfigureContextFunc: configure(), | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
package provider | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"fmt" | ||
tfe "github.com/hashicorp/go-tfe" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation" | ||
"log" | ||
) | ||
|
||
func resourceTFEOrganizationDefaultExecutionMode() *schema.Resource { | ||
return &schema.Resource{ | ||
Create: resourceTFEOrganizationDefaultExecutionModeCreate, | ||
Read: resourceTFEOrganizationDefaultExecutionModeRead, | ||
Delete: resourceTFEOrganizationDefaultExecutionModeDelete, | ||
Importer: &schema.ResourceImporter{ | ||
StateContext: resourceTFEOrganizationDefaultExecutionModeImporter, | ||
}, | ||
|
||
Schema: map[string]*schema.Schema{ | ||
"organization": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
Computed: true, | ||
ForceNew: true, | ||
}, | ||
|
||
"default_execution_mode": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ValidateFunc: validation.StringInSlice( | ||
[]string{ | ||
"agent", | ||
"local", | ||
"remote", | ||
}, | ||
false, | ||
), | ||
ForceNew: true, | ||
}, | ||
|
||
"default_agent_pool_id": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
ForceNew: true, | ||
}, | ||
}, | ||
} | ||
} | ||
|
||
func resourceTFEOrganizationDefaultExecutionModeCreate(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(ConfiguredClient) | ||
|
||
// Get the organization name. | ||
organization, err := config.schemaOrDefaultOrganization(d) | ||
if err != nil { | ||
return fmt.Errorf("error getting organization name: %w", err) | ||
} | ||
|
||
// If the "default_agent_pool_id" was provided, get the agent pool | ||
var agentPool *tfe.AgentPool | ||
if v, ok := d.GetOk("default_agent_pool_id"); ok && v.(string) != "" { | ||
agentPool = &tfe.AgentPool{ | ||
ID: v.(string), | ||
} | ||
} | ||
|
||
defaultExecutionMode := "" | ||
if v, ok := d.GetOk("default_execution_mode"); ok { | ||
defaultExecutionMode = v.(string) | ||
} else { | ||
return fmt.Errorf("default_execution_mode was missing from tfstate, please create an issue to report this error") | ||
} | ||
|
||
// set organization default execution mode | ||
_, err = config.Client.Organizations.Update(context.Background(), organization, tfe.OrganizationUpdateOptions{ | ||
DefaultExecutionMode: tfe.String(defaultExecutionMode), | ||
DefaultAgentPool: agentPool, | ||
}) | ||
if err != nil { | ||
return fmt.Errorf("error setting default execution mode of organization %s: %w", d.Id(), err) | ||
} | ||
|
||
d.SetId(organization) | ||
|
||
return resourceTFEOrganizationDefaultExecutionModeRead(d, meta) | ||
} | ||
|
||
func resourceTFEOrganizationDefaultExecutionModeRead(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(ConfiguredClient) | ||
|
||
log.Printf("[DEBUG] Read the organization: %s", d.Id()) | ||
organization, err := config.Client.Organizations.Read(ctx, d.Id()) | ||
if err != nil { | ||
if errors.Is(err, tfe.ErrResourceNotFound) { | ||
log.Printf("[DEBUG] organization %s no longer exists", d.Id()) | ||
d.SetId("") | ||
return nil | ||
} | ||
return fmt.Errorf("error reading organization %s: %w", d.Id(), err) | ||
} | ||
|
||
defaultExecutionMode := "" | ||
if v, ok := d.GetOk("default_execution_mode"); ok { | ||
defaultExecutionMode = v.(string) | ||
} else { | ||
return fmt.Errorf("default_execution_mode was missing from tfstate, please create an issue to report this error") | ||
} | ||
if organization.DefaultExecutionMode != defaultExecutionMode { | ||
// set id to empty string so that the provider knows it needs to set the default execution mode again | ||
d.SetId("") | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceTFEOrganizationDefaultExecutionModeDelete(d *schema.ResourceData, meta interface{}) error { | ||
config := meta.(ConfiguredClient) | ||
|
||
// Get the organization name. | ||
organization, err := config.schemaOrDefaultOrganization(d) | ||
if err != nil { | ||
return fmt.Errorf("error getting organization name: %w", err) | ||
} | ||
|
||
log.Printf("[DEBUG] Reseting default execution mode of organization: %s", organization) | ||
// reset organization default execution mode | ||
_, err = config.Client.Organizations.Update(context.Background(), organization, tfe.OrganizationUpdateOptions{ | ||
DefaultExecutionMode: tfe.String("remote"), | ||
DefaultAgentPool: nil, | ||
}) | ||
if err != nil { | ||
return fmt.Errorf("error updating organization default execution mode: %w", err) | ||
} | ||
|
||
return nil | ||
} | ||
|
||
func resourceTFEOrganizationDefaultExecutionModeImporter(ctx context.Context, d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) { | ||
config := meta.(ConfiguredClient) | ||
|
||
log.Printf("[DEBUG] Read the organization: %s", d.Id()) | ||
organization, err := config.Client.Organizations.Read(ctx, d.Id()) | ||
if err != nil { | ||
if errors.Is(err, tfe.ErrResourceNotFound) { | ||
log.Printf("[DEBUG] organization %s no longer exists", d.Id()) | ||
d.SetId("") | ||
} | ||
return nil, fmt.Errorf("error reading organization %s: %w", d.Id(), err) | ||
} | ||
|
||
// Set the organization field. | ||
d.Set("organization", d.Id()) | ||
d.Set("default_execution_mode", organization.DefaultExecutionMode) | ||
if organization.DefaultAgentPool != nil { | ||
d.Set("default_agent_pool_id", organization.DefaultAgentPool.ID) | ||
} | ||
|
||
return []*schema.ResourceData{d}, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still don't believe this rises to the level of a breaking change, but do think it deserves a special note. I'll think on it some more.