-
Notifications
You must be signed in to change notification settings - Fork 875
feat!: extract provisioner tags from coder_workspace_tags data source #15578
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
Conversation
…when creating a template version
…space-tags-plumbing
…space-tags-plumbing
// Tag order precedence: | ||
// 1) User-specified tags in the request | ||
// 2) Tags parsed from coder_workspace_tags data source in template file | ||
// 2 may clobber 1. | ||
tags := provisionersdk.MutateTags(apiKey.UserID, req.ProvisionerTags, parsedTags) |
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.
TBD: Which is the desired order here? 1 -> 2, 2-> 1, or 1 XOR 2?
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.
Wouldn't it be a potential security issue if a user could override the template tags? The user could then swap to a provisioner they shouldn't be able to access. Just a thought.
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.
As long as a user can't modify owner
or scope
, I think being able to override tags is a feature. It's how I would get a workspace to be provisioned using a provisioner in my specific region if the template defaults to a US region provisioner for example. And MutateTags protects the owner and scope tags afaik.
Although the template may well have a tag sourced from a variable for this.
Bit of an essay 🙈: There's some duplication ( Yesterday, I was in favour of the CLI and frontend checks for provisioners instead of warnings, because:
Currently, it looks to me like it would actually be better to use your more robust endpoint-side check and send a warning, instead of doing the same check in three places. That would eliminate duplication not only in your CLI command but also in my frontend alerts. Another key aspect of this is the configurable health check interval that I can't currently access from the frontend. This might be more accessible in the API than in the other places. |
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.
Nice work!
// Tag order precedence: | ||
// 1) User-specified tags in the request | ||
// 2) Tags parsed from coder_workspace_tags data source in template file | ||
// 2 may clobber 1. | ||
tags := provisionersdk.MutateTags(apiKey.UserID, req.ProvisionerTags, parsedTags) |
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.
Wouldn't it be a potential security issue if a user could override the template tags? The user could then swap to a provisioner they shouldn't be able to access. Just a thought.
} | ||
}`, | ||
}, | ||
wantTags: map[string]string{"owner": "", "scope": "organization"}, |
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.
Should this be an error? Silently replacing seems like a recipe for confusion.
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 was debating that, but you've sold me. 👍
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 might make this a follow-up, as the existing behaviour of provisionersdk.MutateTags
is to overwrite provisionersdk.TagOwner
At this point, the user still needs to be a template admin. a) don't want to use Right now there's no field in |
@@ -31,7 +31,8 @@ type TemplateVersion struct { | |||
CreatedBy MinimalUser `json:"created_by"` | |||
Archived bool `json:"archived"` | |||
|
|||
Warnings []TemplateVersionWarning `json:"warnings,omitempty" enums:"DEPRECATED_PARAMETERS"` | |||
Warnings []TemplateVersionWarning `json:"warnings,omitempty" enums:"DEPRECATED_PARAMETERS"` | |||
MatchedProvisioners MatchedProvisioners `json:"matched_provisioners,omitempty"` |
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.
review: I considered adding as a field on the ProvisionerJob
but it did not seem 100% correct.
However, as it does not make sense to return this from e.g. getting a previous template version, it may make sense instead to make this nullable (e.g. *MatchedProvisioners
). Thoughts?
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.
From what I could see last week, the only way to see tags for a workspace build is to get that workspace's template version. Therefore, I think we need this even for previous template versions.
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.
Looked at where else we use this payload. You're right, it isn't necessary elsewhere. That means we could make it nullable. Whether that would be better for API clients, I'm not sure. Would be happy if you made it nullable. Would be happy if you left it as is.
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'll keep it as-is for now so you can build on top of it. It should be a fairly simple refactor to make it a nullable field later.
return codersdk.MatchedProvisioners{}, xerrors.Errorf("provisioner daemons by organization: %w", err) | ||
} | ||
|
||
threePollsAgo := time.Now().Add(-3 * pollInterval) |
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.
review: this is duplicated from / in line with coderd/healthcheck
:
if opts.StaleInterval == 0 {
opts.StaleInterval = provisionerdserver.DefaultHeartbeatInterval * 3
}
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.
Do we need the above as a code comment or perhaps a test that checks that they remain in sync?
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'm not sure of the value of adding a test for this, but we can possibly refactor where it's defined in a follow-up so that it's consistent. For now, I'll add a comment 👍
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.
On the surface it kinda makes sense to use the same logic (3*poll), but at the same time I feel multiplying by 3 is pretty extreme, I'm more in favor of a fixed time like poll+30s or something like that. In this instance poll+30s would surface the issue in half the time. If poll is ever raised, to say 2min, the multiplication would go from 1.5min to 3.5min longer to surface the issue, etc.
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.
Looks good. There are some comments left, but none of them block merge IMO. I'm going to be actively consuming this shortly, so I'll get to nits in a subsequent PR if we're happy to do that.
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.
Minor nits, and not sold on the three-polls duration (I feel that's longer than what was discussed previously), but otherwise LGTM. 👍🏻
return codersdk.MatchedProvisioners{}, xerrors.Errorf("provisioner daemons by organization: %w", err) | ||
} | ||
|
||
threePollsAgo := time.Now().Add(-3 * pollInterval) |
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.
On the surface it kinda makes sense to use the same logic (3*poll), but at the same time I feel multiplying by 3 is pretty extreme, I'm more in favor of a fixed time like poll+30s or something like that. In this instance poll+30s would surface the issue in half the time. If poll is ever raised, to say 2min, the multiplication would go from 1.5min to 3.5min longer to surface the issue, etc.
// MostRecentlySeen is the most recently seen time of the set of matched | ||
// provisioners. If no provisioners matched, this field will be null. | ||
MostRecentlySeen NullTime `json:"most_recently_seen,omitempty" format:"date-time"` | ||
} |
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 fair; I'd rather have it be consistent though. I'll open a follow-up PR to adjust this. |
Co-authored-by: Mathias Fredriksson <mafredri@gmail.com>
Relates to #15087 and #15427
coder_workspace_tags
on template version creation usingprovisioner/terraform/tfparse
added in feat(provisioner/terraform/tfparse): implement WorkspaceTagDefaultsFromFile #15236codersdk.MatchedProvisioners
struct to theTemplateVersion
response containing details of how many provisioners were around at the time of the insert.NOTE: As this effectively blocks template creation if
coder_workspace_tags
is malformed or references anything other than a Terraform variable orcoder_parameter
, I am marking this as a breaking change.Testing notes:
coderdtest
in favour of just creating the template version and asserting that a provisioner job was created with the expected tags.Checklist:
Manual testing performed:
./develop.sh -- --provisioner-daemons=0
with a separate./scripts/coder-dev.sh --key=foobar
where foobar.keys ={"foo": "bar"}
coder template push
and observed the job get picked uptemplate_version_workspace_tags
:Ran
coder create
and observed the job getting picked up correctly.Failure case:
coder templates push <template>
with no workspace tags available:Remaining work:
/api/v2/organizations/:org/templateversions
returns an error. This will need to be addressed in a follow-up PR.