-
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
Conversation
…execution modes in tf
…r depedency between agent pool and organization
342c8c9
to
7d6056e
Compare
…using a version of tfe that supports default execution modes
26264f9
to
7e14b3a
Compare
…to the organization default execution mode
…e same agent pool but explicitly set/overwritten
@@ -274,7 +275,7 @@ func resourceTFETeamDelete(d *schema.ResourceData, meta interface{}) error { | |||
log.Printf("[DEBUG] Delete team: %s", d.Id()) | |||
err := config.Client.Teams.Delete(ctx, d.Id()) | |||
if err != nil { | |||
if err == tfe.ErrResourceNotFound { | |||
if errors.Is(err, tfe.ErrResourceNotFound) { |
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.
These changes aren't related to my PR, but they showed up in the lint and I figured I might as well address them.
@@ -725,6 +725,7 @@ resource "tfe_organization" "foobar" { | |||
resource "tfe_workspace" "foobar" { | |||
name = "workspace-test" | |||
organization = tfe_organization.foobar.id | |||
execution_mode = "remote" |
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.
This test uses an old provider version for the first step, so applying with the modern provider will produce a diff because the setting_overwrites
need to be set in order for the provider to know that it is communicating with a version of TFE that supports setting_overwrites
.
Explicitly setting the execution_mode
eliminates this diff, without affecting the test's assertions in any way.
…ying behavior of computed attributes
"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 comment
The reason will be displayed to describe this comment to others. Learn more.
^ the only line that really changed
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.
Nothing blocking! I couldn't break it, although I had to be careful about when my workspace was created relative to the new resource.
resource "tfe_organization_default_execution_mode" "org_default" { | ||
organization = tfe_organization.test.name | ||
default_execution_mode = "agent" | ||
default_agent_pool_id = tfe_agent_pool.my_agents.id | ||
} |
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.
One interesting consequence of this design is that workspaces have to wait on this in order to assume the default. I wonder if we can add to the docs to demonstrate how to ensure a workspace in the same config uses the org default. I can't really think of a great way to reference the execution mode, so perhaps we can just fallback to depends_on
resource "tfe_workspace" "workspace_with_org_default" {
organization = tfe_organization.test.name
name = "workspace-with-org-default"
# Ensure workspaces are created after the org default execution mode is set
depends_on = [tfe_organization_default_execution_mode.org_default]
}
It's either that or something like a precondition
resource "tfe_workspace" "workspace_with_org_default" {
organization = tfe_organization.test.name
name = "workspace-with-org-default"
# Ensure workspaces are created after the org default execution mode is set
lifecycle {
precondition {
error_message = "Must use org default execution"
condition = tfe_organization_default_execution_mode.name.default_execution_mode != ""
}
}
}
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.
This wouldn't matter if the execution_mode
and agent_pool_id
wouldn't be copied from the organization defaults to the state. The actual workspace will anyway follow the upstream settings, right?
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.
True. The workspace's execution mode is evaluated (more or less) in realtime, so no depends_on
needed here.
* `setting_overwrites` - Can be used to check whether a setting is currently inheriting its value from another resource. | ||
- `execution_mode` - Set to `true` if the execution mode of the workspace is being determined by the setting on the workspace itself. It will be `false` if the execution mode is inherited from another resource (e.g. the organization's default execution mode) | ||
- `agent_pool` - Set to `true` if the agent pool of the workspace is being determined by the setting on the workspace itself. It will be `false` if the agent pool is inherited from another resource (e.g. the organization's default agent pool) |
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.
Even though we could perhaps conceive of a more ergonomic schema, I like that this reflects the API. At least we are only committed to what we're already committed to.
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 don't like the setting_overwrites
at all. 😂
Although if I get it right, it shouldn't actually be needed to be specified, if the user just doesn't specify execution_mode
.
But I still find it confusing to copy the upstream execution mode and agent pool to the state. I think it even causes state drift and a need for terraform apply
if the upstream setting is changed (in another module or by web console).
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.
Sorry, only now I realized that this is a computed (i.e. read only) attribute. So basically the new feature is that the default execution mode is the "upstream" default. Maybe add a comment in the first example, too?
The last point should still be valid. I don't think it's according to the design principals for resources to have attribute values controlled by other resources. State drifts are annoying. 😅
If someone really needs to know what the default execution mode is, they can use the (still missing) tfw_organization_default_execution_mode
data source. And also the tfe_organization
should be changed accordingly to set the execution_mode
and agent_pool_id
to null
if setting_overwrites
so says. (And here I'm not so sure that the null
is the best value to control this feature in the first place.)
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.
And maybe some additional import docs !
|
||
## Import | ||
|
||
This resource does not manage the creation of an organization and there is no need to import it. |
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.
Oh! I think you might as well include instructions since you would need to import the resource if you did not wish to manipulate config during an import process.
This resource does not manage the creation of an organization and there is no need to import it. | |
Organization default execution mode can be imported; use `<ORGANIZATION NAME>` as the import ID. For | |
example: | |
(backticks)shell | |
terraform import tfe_organization_default_execution_mode.test my-org-name | |
(backticks) |
@@ -4,6 +4,8 @@ | |||
|
|||
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 comment
The 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 comment
The 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 comment
The reason will be displayed to describe this comment to others. Learn more.
If you don't change the default at the org level
Yeah but what if someone does? 🙂
The provider is still pre-1.0 so everything is allowed. I'm just suggesting to add a specific note about this in the changelog.
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.
That's a fair point. Previously, I was thinking setting the default execution_mode
in an admission that you were prepared for that change to affect all the workspaces in your organization, but adding a note here couldn't hurt!
resource "tfe_organization_default_execution_mode" "org_default" { | ||
organization = tfe_organization.test.name | ||
default_execution_mode = "agent" | ||
default_agent_pool_id = tfe_agent_pool.my_agents.id | ||
} |
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.
This wouldn't matter if the execution_mode
and agent_pool_id
wouldn't be copied from the organization defaults to the state. The actual workspace will anyway follow the upstream settings, right?
to be set to `agent`. This value _must not_ be provided if `default_execution_mode` is set to any other value or if `operations` is | ||
provided. |
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.
No operations
argument here
to be set to `agent`. This value _must not_ be provided if `default_execution_mode` is set to any other value or if `operations` is | |
provided. | |
to be set to `agent`. This value _must not_ be provided if `default_execution_mode` is set to any other value. |
* `setting_overwrites` - Can be used to check whether a setting is currently inheriting its value from another resource. | ||
- `execution_mode` - Set to `true` if the execution mode of the workspace is being determined by the setting on the workspace itself. It will be `false` if the execution mode is inherited from another resource (e.g. the organization's default execution mode) | ||
- `agent_pool` - Set to `true` if the agent pool of the workspace is being determined by the setting on the workspace itself. It will be `false` if the agent pool is inherited from another resource (e.g. the organization's default agent pool) |
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 don't like the setting_overwrites
at all. 😂
Although if I get it right, it shouldn't actually be needed to be specified, if the user just doesn't specify execution_mode
.
But I still find it confusing to copy the upstream execution mode and agent pool to the state. I think it even causes state drift and a need for terraform apply
if the upstream setting is changed (in another module or by web console).
@tmatilai The reason why we store settings_overwrites in state is to simplify reading execution mode from the workspace, even if that value comes from the organization. Since this is a computed field, it is allowed to vary without drift if the org default changes. This means that changing the org default should never result in an unplanned change unless you are reading the execution mode into some other value, like an output, in which case that would be useful to know about! It's often the case that resources will change the value of computed attributes on other resources. Here's what terraform does when I apply a default change to the org and a workspace "foo" is using the default:
|
@brandonc thanks a lot for taking the time to answer! 🤗
I can't think why that would be useful, but maybe there is a use case for it? 🤔 And then in the I just find it really strange to have a dynamically changing default, and even changing not only on resource creation.
But it's not purely computed, as it's also optional. Not sure if I can agree on "ofter". 😄
Btw, who do those changes force recreation? I wonder if the |
And I admit that I missed this. |
Hiya @tmatilai 👋 I thought I'd try and give some background context on why
The original reason for A big reason why I believe we need Another reason (albeit opinionated) is that matching the underlying API is one of the provider design principles, and one that I personally have felt particularly attached to. I've found time and time again that straying from the underlying API, or creating abstractions in the provider over concepts in the API makes for some very painful and unpredictable design challenges further down the road.
You and I are totally in agreement there! That being said, we do technically have a "default" that can change. So, I think it's super important the provider reflects this reality, rather than try to abstract over it. This is why I actually personally don't recommend users to use the organization-level default unless it is something they really truly need. Instead, I recommend users to use this provider to provision their workspaces, and to set the
I think maybe what @brandonc meant by "purely computed" was "read only", in which case the field NEEDS to be both computed and optional.
This is totally just a choice in implementation. By making the resource just support CREATE/READ/DELETE, it makes things quite a bit simpler! Less things to implement, less things to test, less things to break 🎉 |
@@ -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: |
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.
Hi @SwiftEngineer, I really appreciate your explanations! 🙌
Fair point. I was locked in the TF provider context only. These are not easy choices.
Sure. But in case needed, maybe look at e.g. the Vault provider which has helpers to enable features based on the Vault version queried over API.
I indeed don't have the experience of maintaining a provider. But with my long history of Terraform user I tend to like the providers and resources with nice UX, and am not so interested in the underlying API implementation. 😅
100% agree. I guess I should not have even got into so attached to the whole implementation because of that. 😄 My current use case for the organization level default is to set it to
Maybe doesn't matter with this resource, but in general I've seen people getting scared when resources are destroyed in their plans. And some cases it might cause cascading Anyway, thanks again for all the effort with the provider. It really makes my life easier when I'm trying to automate all the things. 😆 |
Description
Adds support for organization-level default execution modes and agent pools 🎉
Remember to:
Testing plan
agent
, then again with the default set toremote
. Flip back and forth between the execution mode being set at the workspace-level and the organization-leveloperations
setting still works as expected, and that workspaces created with theoperations
setting can be migrated to use the organization default execution mode. Do this by creating a workspace withoperations
set to some value. Then remove the operations setting and apply the configuration.remote
is always the default execution mode).External links
Include any links here that might be helpful for people reviewing your PR. If there are none, feel free to delete this section.