Skip to content

feat(cli): add CLI support for listing presets #18910

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

ssncferreira
Copy link
Contributor

@ssncferreira ssncferreira commented Jul 17, 2025

Description

This PR introduces a new list presets command to display presets correspondent to a template and template version.

Changes

  • The list presets command queries the available presets associated with a template and version, and outputs them in a readable format.
> coder templates versions presets list --help

USAGE:
  coder templates versions presets list [flags] <template> <version>

  List all the presets of the specified template version

OPTIONS:
  -O, --org string, $CODER_ORGANIZATION
          Select which organization (uuid or name) to use.

  -c, --column [name|parameters|default|prebuilds] (default: name,parameters,default,prebuilds)
          Columns to display in table output.

  -o, --output table|json (default: table)
          Output format.

Related PR: #18912 - please consider both PRs together as they’re part of the same workflow
Relates to issue: #16594

Long: FormatExamples(
Example{
Description: "List presets of a specific template version",
Command: "coder templates versions presets list my-template my-template-version",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently, the coder templates versions presets list command requires both a template and a template version as positional arguments. However, it might be more user-friendly to only require the template name, and by default use the active template version.

We could also introduce a --template-version flag for cases where the user wants to explicitly list the presets of a specific template version.

Example usage:

# Lists presets for the active version of the template
coder templates versions presets list my-template

# Lists presets for a specific template version
coder templates versions presets list my-template --template-version my-template-version

Let me know what you think

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

coder templates versions presets list is too verbose. Since we're requiring the template name / version as args/flags, there's no need to mention them in the command IMHO. coder presets should suffice.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like coder presets. I recall seeing the term preset used in unrelated work in the frontend a few months ago. Perhaps just check that we won't have any namespacing conflicts if we shorten the command but otherwise I think its a good idea.

I think template version flag should be optional with the active version as a default.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As an aside, I now see the logic of going for templates versions presets list, since it doesn't give presets any special treatment (or more special than versions which they exist inside of). I think the reasoning should've been spelled out in the description.

I'll just keep quiet about the naming now 😆

@ssncferreira ssncferreira marked this pull request as ready for review July 17, 2025 09:12
@ssncferreira ssncferreira requested a review from aslilac as a code owner July 17, 2025 09:13
Copy link
Contributor

@dannykopping dannykopping left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before I review further, I'd like to just address some confusion I have:

I'm not really understanding the point of this command.

Users need to be able to specify a preset when creating a workspace. Presumably this command is to allow a user to find out which presets exist so they can pass a value to coder create.

However: coder create provides an interactive and non-interactive mode. If you supply a --template argument it'll use that value, otherwise interactively list all templates and prompt the user to select one.

I think presets should have the same experience. In other words, we likely don't need this command at all but rather we can move the logic you've already implemented to coder create.

That will be the most consistent UX, I believe.


Let me put it another way: were we aware of the interactive nature of coder create? If so, did we decide to design it this way for a particular reason? I can see how this design might fall out of not knowing about the interactive mode.

Long: FormatExamples(
Example{
Description: "List presets of a specific template version",
Command: "coder templates versions presets list my-template my-template-version",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

coder templates versions presets list is too verbose. Since we're requiring the template name / version as args/flags, there's no need to mention them in the command IMHO. coder presets should suffice.

@ssncferreira
Copy link
Contributor Author

Before I review further, I'd like to just address some confusion I have:

I'm not really understanding the point of this command.

Users need to be able to specify a preset when creating a workspace. Presumably this command is to allow a user to find out which presets exist so they can pass a value to coder create.

Exactly! One of the goals of this command is to help users discover which presets are available for a given template version, especially in non-interactive, automated environments. The ability to apply a preset during workspace creation is implemented in #18912.

However: coder create provides an interactive and non-interactive mode. If you supply a --template argument it'll use that value, otherwise interactively list all templates and prompt the user to select one.

I think presets should have the same experience. In other words, we likely don't need this command at all but rather we can move the logic you've already implemented to coder create.

That will be the most consistent UX, I believe.

I agree that presets should follow the same behavior in both interactive and non-interactive modes. While the current implementation doesn't include interactive support for presets, I think it absolutely should. I shared some thoughts on this here: https://github.com/coder/coder/pull/18912/files#r2212832022 including ideas on default selection, backward compatibility with scripting workflows, and introducing a "none" option.

That said, I believe this command is still valuable in non-interactive scenarios, where users might need to fetch the name of a preset to use during workspace creation.

Let me put it another way: were we aware of the interactive nature of coder create? If so, did we decide to design it this way for a particular reason? I can see how this design might fall out of not knowing about the interactive mode.

Yes, we’re aware of that! And while the interactive flow is great for users running coder create manually, we also need to support non-interactive usage, which is common in customer scripts and automation.

In those cases, users typically rely on:

  • coder templates list to discover templates,
  • coder templates versions list to discover template versions,
  • and now, coder templates versions presets list to discover presets (but I am open to a less verbose command 😅 )

This new command fits naturally into that pattern. It allows users to look up presets that they can then pass via --preset to coder create, without requiring any prompts.

Right now, the CLI does not provide any information about presets, this command gives users a way to discover and inspect available presets for a given template and version.

Copy link
Contributor

@SasSwart SasSwart left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great @ssncferreira. Some minor comments. I'll check back once we've finalized the thread Danny opened.

@@ -15,6 +15,7 @@ type Preset struct {
Name string
Parameters []PresetParameter
Default bool
Prebuilds *int
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider clarifying the naming to communicate whether this is the desired number of prebuilds or the eligible number of prebuilds. I can see from elsewhere that its the desired number, but we've spoken in the past about showing how many prebuilds are eligible in the frontend before. Would be good to leave room for both.

@@ -38,12 +39,21 @@ func (api *API) templateVersionPresets(rw http.ResponseWriter, r *http.Request)
return
}

getPrebuildInstances := func(desiredInstances sql.NullInt32) *int {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this name implies fetching from somewhere, but it only does a type conversion. perhaps consider a more descriptive name?

}

if len(presets) == 0 {
return xerrors.Errorf("no presets found for template %q and template-version %q", template.Name, version.Name)
Copy link
Contributor

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? Or just an empty list?

@dannykopping dannykopping self-requested a review July 17, 2025 16:56
@dannykopping
Copy link
Contributor

Before I review further, I'd like to just address some confusion I have:
I'm not really understanding the point of this command.
Users need to be able to specify a preset when creating a workspace. Presumably this command is to allow a user to find out which presets exist so they can pass a value to coder create.

Exactly! One of the goals of this command is to help users discover which presets are available for a given template version, especially in non-interactive, automated environments. The ability to apply a preset during workspace creation is implemented in #18912.

However: coder create provides an interactive and non-interactive mode. If you supply a --template argument it'll use that value, otherwise interactively list all templates and prompt the user to select one.
I think presets should have the same experience. In other words, we likely don't need this command at all but rather we can move the logic you've already implemented to coder create.
That will be the most consistent UX, I believe.

I agree that presets should follow the same behavior in both interactive and non-interactive modes. While the current implementation doesn't include interactive support for presets, I think it absolutely should. I shared some thoughts on this here: #18912 (files) including ideas on default selection, backward compatibility with scripting workflows, and introducing a "none" option.

That said, I believe this command is still valuable in non-interactive scenarios, where users might need to fetch the name of a preset to use during workspace creation.

Let me put it another way: were we aware of the interactive nature of coder create? If so, did we decide to design it this way for a particular reason? I can see how this design might fall out of not knowing about the interactive mode.

Yes, we’re aware of that! And while the interactive flow is great for users running coder create manually, we also need to support non-interactive usage, which is common in customer scripts and automation.

In those cases, users typically rely on:

  • coder templates list to discover templates,
  • coder templates versions list to discover template versions,
  • and now, coder templates versions presets list to discover presets (but I am open to a less verbose command 😅 )

This new command fits naturally into that pattern. It allows users to look up presets that they can then pass via --preset to coder create, without requiring any prompts.

Right now, the CLI does not provide any information about presets, this command gives users a way to discover and inspect available presets for a given template and version.

My apologies @ssncferreira! I didn't see the other PR, maybe mention it in the description of this one?
I thought this PR represented the full scope of what was to be done; makes a lot of sense in the wider context.
Thanks!

@ssncferreira
Copy link
Contributor Author

ssncferreira commented Jul 17, 2025

My apologies @ssncferreira! I didn't see the other PR, maybe mention it in the description of this one? I thought this PR represented the full scope of what was to be done; makes a lot of sense in the wider context. Thanks!

No worries @dannykopping 😊 it was a totally fair point, and I really appreciate you taking the time to make sure the UX of the CLI is thoughtfully considered. I've updated the description of both PRs to reference each other for clarity. Let me know if anything else is unclear!

Copy link
Contributor

@dannykopping dannykopping left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No concerns from my side except naming. LGTM!

func (r *RootCmd) templateVersionPresets() *serpent.Command {
cmd := &serpent.Command{
Use: "presets",
Short: "Manage presets of the specified template version",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: we're not managing anything right now, and probably never will from this command.

Long: FormatExamples(
Example{
Description: "List presets of a specific template version",
Command: "coder templates versions presets list my-template my-template-version",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As an aside, I now see the logic of going for templates versions presets list, since it doesn't give presets any special treatment (or more special than versions which they exist inside of). I think the reasoning should've been spelled out in the description.

I'll just keep quiet about the naming now 😆

Name string `json:"-" table:"name,default_sort"`
Parameters string `json:"-" table:"parameters"`
Default bool `json:"-" table:"default"`
Prebuilds string `json:"-" table:"prebuilds"`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

$ ./scripts/coder-dev.sh template versions presets list docker objective_elgamal6
NAME               PARAMETERS              DEFAULT  PREBUILDS
I Like GoLand      cpu=2,jetbrains_ide=GO  false    1
Some Like PyCharm  jetbrains_ide=PY        true     0

PREBUILDS is confusing here (maybe irrelevant?); we could rename it to DESIRED PREBUILT INSTANCES or similar.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants