diff --git a/cli/templatecreate.go b/cli/templatecreate.go
index d1bc545181f..62ba06dde16 100644
--- a/cli/templatecreate.go
+++ b/cli/templatecreate.go
@@ -21,6 +21,7 @@ func (r *RootCmd) templateCreate() *serpent.Command {
provisionerTags []string
variablesFile string
commandLineVariables []string
+ agentsAllowed bool
disableEveryone bool
requireActiveVersion bool
@@ -159,6 +160,7 @@ func (r *RootCmd) templateCreate() *serpent.Command {
TimeTilDormantAutoDeleteMillis: ptr.Ref(dormancyAutoDeletion.Milliseconds()),
DisableEveryoneGroupAccess: disableEveryone,
RequireActiveVersion: requireActiveVersion,
+ AgentsAllowed: &agentsAllowed,
}
template, err := client.CreateTemplate(inv.Context(), organization.ID, createReq)
@@ -179,6 +181,12 @@ func (r *RootCmd) templateCreate() *serpent.Command {
},
}
cmd.Options = serpent.OptionSet{
+ {
+ Flag: "agents-allowed",
+ Description: "Allow Coder Agents to create workspaces using this template.",
+ Default: "true",
+ Value: serpent.BoolOf(&agentsAllowed),
+ },
{
Flag: "private",
Description: "Disable the default behavior of granting template access to the 'everyone' group. " +
diff --git a/cli/templatecreate_test.go b/cli/templatecreate_test.go
index cb744800430..36c9eff055f 100644
--- a/cli/templatecreate_test.go
+++ b/cli/templatecreate_test.go
@@ -12,6 +12,7 @@ import (
"github.com/coder/coder/v2/cli/clitest"
"github.com/coder/coder/v2/coderd/coderdtest"
"github.com/coder/coder/v2/coderd/database"
+ "github.com/coder/coder/v2/coderd/rbac"
"github.com/coder/coder/v2/provisioner/echo"
"github.com/coder/coder/v2/provisionersdk/proto"
"github.com/coder/coder/v2/testutil"
@@ -58,6 +59,56 @@ func TestCliTemplateCreate(t *testing.T) {
}
}
})
+ t.Run("AgentsAllowed", func(t *testing.T) {
+ t.Parallel()
+
+ client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
+ owner := coderdtest.CreateFirstUser(t, client)
+ templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
+
+ for _, tt := range []struct {
+ name string
+ flag string
+ agentsAllowed bool
+ }{
+ {
+ name: "DefaultTrue",
+ agentsAllowed: true,
+ },
+ {
+ name: "False",
+ flag: "--agents-allowed=false",
+ agentsAllowed: false,
+ },
+ } {
+ t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
+
+ templateName := coderdtest.RandomUsername(t)
+ source := clitest.CreateTemplateVersionSource(t, completeWithAgent())
+ args := []string{
+ "templates",
+ "create",
+ templateName,
+ "--yes",
+ "--directory", source,
+ "--test.provisioner", string(database.ProvisionerTypeEcho),
+ }
+ if tt.flag != "" {
+ args = append(args, tt.flag)
+ }
+ inv, root := clitest.New(t, args...)
+ clitest.SetupConfig(t, templateAdmin, root)
+
+ require.NoError(t, inv.Run())
+
+ template, err := client.TemplateByName(t.Context(), owner.OrganizationID, templateName)
+ require.NoError(t, err)
+ require.Equal(t, tt.agentsAllowed, template.AgentsAllowed)
+ })
+ }
+ })
+
t.Run("CreateNoLockfile", func(t *testing.T) {
t.Parallel()
logger := testutil.Logger(t)
diff --git a/cli/templateedit.go b/cli/templateedit.go
index e25da3462c3..751bb633040 100644
--- a/cli/templateedit.go
+++ b/cli/templateedit.go
@@ -33,6 +33,7 @@ func (r *RootCmd) templateEdit() *serpent.Command {
allowUserCancelWorkspaceJobs bool
allowUserAutostart bool
allowUserAutostop bool
+ agentsAllowed bool
requireActiveVersion bool
deprecationMessage string
disableEveryone bool
@@ -142,6 +143,10 @@ func (r *RootCmd) templateEdit() *serpent.Command {
dormancyAutoDeletion = time.Duration(template.TimeTilDormantAutoDeleteMillis) * time.Millisecond
}
+ if !userSetOption(inv, "agents-allowed") {
+ agentsAllowed = template.AgentsAllowed
+ }
+
if !userSetOption(inv, "require-active-version") {
requireActiveVersion = template.RequireActiveVersion
}
@@ -199,6 +204,7 @@ func (r *RootCmd) templateEdit() *serpent.Command {
AllowUserCancelWorkspaceJobs: &allowUserCancelWorkspaceJobs,
AllowUserAutostart: &allowUserAutostart,
AllowUserAutostop: &allowUserAutostop,
+ AgentsAllowed: &agentsAllowed,
RequireActiveVersion: &requireActiveVersion,
DeprecationMessage: deprecated,
DisableEveryoneGroupAccess: &disableEveryoneGroup,
@@ -292,6 +298,12 @@ func (r *RootCmd) templateEdit() *serpent.Command {
Default: "0h",
Value: serpent.DurationOf(&dormancyAutoDeletion),
},
+ {
+ Flag: "agents-allowed",
+ Description: "Allow Coder Agents to create workspaces using this template.",
+ Default: "true",
+ Value: serpent.BoolOf(&agentsAllowed),
+ },
{
Flag: "allow-user-cancel-workspace-jobs",
Description: "Allow users to cancel in-progress workspace jobs.",
diff --git a/cli/templateedit_test.go b/cli/templateedit_test.go
index d6c8af82b0f..3acc6513daf 100644
--- a/cli/templateedit_test.go
+++ b/cli/templateedit_test.go
@@ -115,6 +115,76 @@ func TestTemplateEdit(t *testing.T) {
assert.Equal(t, template.DefaultTTLMillis, updated.DefaultTTLMillis)
assert.Equal(t, template.AllowUserCancelWorkspaceJobs, updated.AllowUserCancelWorkspaceJobs)
})
+ t.Run("AgentsAllowed", func(t *testing.T) {
+ t.Parallel()
+
+ client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
+ owner := coderdtest.CreateFirstUser(t, client)
+ templateAdmin, _ := coderdtest.CreateAnotherUser(t, client, owner.OrganizationID, rbac.RoleTemplateAdmin())
+
+ for _, tt := range []struct {
+ name string
+ initialAgentsAllowed bool
+ flag string
+ description string
+ wantAgentsAllowed bool
+ }{
+ {
+ name: "ExplicitTrue",
+ initialAgentsAllowed: false,
+ flag: "--agents-allowed=true",
+ wantAgentsAllowed: true,
+ },
+ {
+ name: "ExplicitFalse",
+ initialAgentsAllowed: true,
+ flag: "--agents-allowed=false",
+ wantAgentsAllowed: false,
+ },
+ {
+ name: "OmittedPreservesTrue",
+ initialAgentsAllowed: true,
+ description: "updated description",
+ wantAgentsAllowed: true,
+ },
+ {
+ name: "OmittedPreservesFalse",
+ initialAgentsAllowed: false,
+ description: "updated description",
+ wantAgentsAllowed: false,
+ },
+ } {
+ t.Run(tt.name, func(t *testing.T) {
+ t.Parallel()
+
+ version := coderdtest.CreateTemplateVersion(t, client, owner.OrganizationID, nil)
+ _ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, version.ID)
+ template := coderdtest.CreateTemplate(t, client, owner.OrganizationID, version.ID, func(req *codersdk.CreateTemplateRequest) {
+ req.AgentsAllowed = &tt.initialAgentsAllowed
+ })
+
+ cmdArgs := []string{"templates", "edit", template.Name}
+ if tt.flag != "" {
+ cmdArgs = append(cmdArgs, tt.flag)
+ }
+ if tt.description != "" {
+ cmdArgs = append(cmdArgs, "--description", tt.description)
+ }
+ inv, root := clitest.New(t, cmdArgs...)
+ clitest.SetupConfig(t, templateAdmin, root)
+
+ require.NoError(t, inv.Run())
+
+ updated, err := client.Template(t.Context(), template.ID)
+ require.NoError(t, err)
+ require.Equal(t, tt.wantAgentsAllowed, updated.AgentsAllowed)
+ if tt.description != "" {
+ require.Equal(t, tt.description, updated.Description)
+ }
+ })
+ }
+ })
+
t.Run("InvalidDisplayName", func(t *testing.T) {
t.Parallel()
client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true})
diff --git a/cli/testdata/coder_templates_create_--help.golden b/cli/testdata/coder_templates_create_--help.golden
index c0370d93d21..7ef71d7d1cf 100644
--- a/cli/testdata/coder_templates_create_--help.golden
+++ b/cli/testdata/coder_templates_create_--help.golden
@@ -10,6 +10,9 @@ OPTIONS:
-O, --org string, $CODER_ORGANIZATION
Select which organization (uuid or name) to use.
+ --agents-allowed bool (default: true)
+ Allow Coder Agents to create workspaces using this template.
+
--default-ttl duration (default: 24h)
Specify a default TTL for workspaces created from this template. It is
the default time before shutdown - workspaces created from this
diff --git a/cli/testdata/coder_templates_edit_--help.golden b/cli/testdata/coder_templates_edit_--help.golden
index 73760dadfcb..972437a8e8c 100644
--- a/cli/testdata/coder_templates_edit_--help.golden
+++ b/cli/testdata/coder_templates_edit_--help.golden
@@ -14,6 +14,9 @@ OPTIONS:
template will have their shutdown time bumped by this value when
activity is detected. Maps to "Activity bump" in the UI.
+ --agents-allowed bool (default: true)
+ Allow Coder Agents to create workspaces using this template.
+
--allow-user-autostart bool (default: true)
Allow users to configure autostart for workspaces on this template.
This can only be disabled in enterprise.
diff --git a/docs/reference/cli/templates_create.md b/docs/reference/cli/templates_create.md
index 3f46f3e759f..a3bba84d924 100644
--- a/docs/reference/cli/templates_create.md
+++ b/docs/reference/cli/templates_create.md
@@ -11,6 +11,15 @@ coder templates create [flags] [name]
## Options
+### --agents-allowed
+
+| | |
+|---------|-------------------|
+| Type | bool |
+| Default | true |
+
+Allow Coder Agents to create workspaces using this template.
+
### --private
| | |
diff --git a/docs/reference/cli/templates_edit.md b/docs/reference/cli/templates_edit.md
index 5e9fe477050..2e472d1600e 100644
--- a/docs/reference/cli/templates_edit.md
+++ b/docs/reference/cli/templates_edit.md
@@ -126,6 +126,15 @@ Specify a duration workspaces may be inactive prior to being moved to the dorman
Specify a duration workspaces may be in the dormant state prior to being deleted. This licensed feature's default is 0h (off). Maps to "Dormancy Auto-Deletion" in the UI.
+### --agents-allowed
+
+| | |
+|---------|-------------------|
+| Type | bool |
+| Default | true |
+
+Allow Coder Agents to create workspaces using this template.
+
### --allow-user-cancel-workspace-jobs
| | |