mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
feat(cli): add --agents-allowed to template commands (#27517)
Relates to CODAGT-713 Depends on #27515 This adds `--agents-allowed` to `coder templates create` and `coder templates edit`. Template creation defaults the option to true, matching the per-template API and database default, while template editing only changes the value when the flag is explicitly supplied so unrelated edits preserve the existing setting. The generated CLI help and reference documentation include the new option. #27518 updates the Coder Agents platform controls documentation to describe the completed per-template model.
This commit is contained in:
@@ -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. " +
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.",
|
||||
|
||||
@@ -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})
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user