Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat: add--version flag tocoder templates pull, default to active version#10153

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 58 additions & 21 deletionscli/templatepull.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -15,12 +15,15 @@ import (
)

func (r *RootCmd) templatePull() *clibase.Cmd {
var tarMode bool
var (
tarMode bool
versionName string
)

client := new(codersdk.Client)
cmd := &clibase.Cmd{
Use: "pull <name> [destination]",
Short: "Download the latest version of a template to a path.",
Short: "Download theactive,latest, or specified version of a template to a path.",
Middleware: clibase.Chain(
clibase.RequireRangeArgs(1, 2),
r.InitClient(client),
Expand All@@ -36,39 +39,67 @@ func (r *RootCmd) templatePull() *clibase.Cmd {
dest = inv.Args[1]
}

// TODO(JonA): Do we need to add a flag for organization?
organization, err := CurrentOrganization(inv, client)
if err != nil {
return xerrors.Errorf("current organization: %w", err)
return xerrors.Errorf("getcurrent organization: %w", err)
}

template, err := client.TemplateByName(ctx, organization.ID, templateName)
if err != nil {
return xerrors.Errorf("template by name: %w", err)
return xerrors.Errorf("gettemplate by name: %w", err)
}

// Pull the versions for the template. We'll find the latest
// one and download the source.
versions, err := client.TemplateVersionsByTemplate(ctx, codersdk.TemplateVersionsByTemplateRequest{
TemplateID: template.ID,
})
if err != nil {
return xerrors.Errorf("template versions by template: %w", err)
}
var latestVersion codersdk.TemplateVersion
{
// Determine the latest template version and compare with the
// active version. If they aren't the same, warn the user.
versions, err := client.TemplateVersionsByTemplate(ctx, codersdk.TemplateVersionsByTemplateRequest{
TemplateID: template.ID,
})
if err != nil {
return xerrors.Errorf("template versions by template: %w", err)
}

if len(versions) == 0 {
return xerrors.Errorf("no template versions for template %q", templateName)
}

// Sort the slice from newest to oldest template.
sort.SliceStable(versions, func(i, j int) bool {
return versions[i].CreatedAt.After(versions[j].CreatedAt)
})

if len(versions) == 0 {
return xerrors.Errorf("no template versions for template %q", templateName)
latestVersion = versions[0]
}
Comment on lines +52 to 73
Copy link
Member

Choose a reason for hiding this comment

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

You should move this into the switch when you pick latest

Copy link
ContributorAuthor

Choose a reason for hiding this comment

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

I need to know the latest version for the warning when the version isn't specified.

deansheather reacted with thumbs up emoji

// Sort the slice from newest to oldest template.
sort.SliceStable(versions, func(i, j int) bool {
return versions[i].CreatedAt.After(versions[j].CreatedAt)
})
var templateVersion codersdk.TemplateVersion
switch versionName {
case "", "active":
activeVersion, err := client.TemplateVersion(ctx, template.ActiveVersionID)
if err != nil {
return xerrors.Errorf("get active template version: %w", err)
}
if versionName == "" && activeVersion.ID != latestVersion.ID {
cliui.Warn(inv.Stderr,
"A newer template version than the active version exists. Pulling the active version instead.",
"Use "+cliui.Code("--template latest")+" to pull the latest version.",
)
}
templateVersion = activeVersion
case "latest":
templateVersion = latestVersion
default:
version, err := client.TemplateVersionByName(ctx, template.ID, versionName)
if err != nil {
return xerrors.Errorf("get template version: %w", err)
}
templateVersion = version
}

latest := versions[0]
cliui.Info(inv.Stderr, "Pulling template version "+cliui.Bold(templateVersion.Name)+"...")

// Download the tar archive.
raw, ctype, err := client.Download(ctx,latest.Job.FileID)
raw, ctype, err := client.Download(ctx,templateVersion.Job.FileID)
if err != nil {
return xerrors.Errorf("download template: %w", err)
}
Expand DownExpand Up@@ -121,6 +152,12 @@ func (r *RootCmd) templatePull() *clibase.Cmd {

Value: clibase.BoolOf(&tarMode),
},
{
Description: "The name of the template version to pull. Use 'active' to pull the active version, 'latest' to pull the latest version, or the name of the template version to pull.",
Flag: "version",

Value: clibase.StringOf(&versionName),
},
cliui.SkipPromptOption(),
}

Expand Down
130 changes: 126 additions & 4 deletionscli/templatepull_test.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -7,6 +7,7 @@ import (
"encoding/hex"
"os"
"path/filepath"
"strings"
"testing"

"github.com/codeclysm/extract/v3"
Expand DownExpand Up@@ -48,7 +49,7 @@ func TestTemplatePull_NoName(t *testing.T) {
require.Error(t, err)
}

// Stdout tests that 'templates pull' pulls down thelatest template
// Stdout tests that 'templates pull' pulls down theactive template
// and writes it to stdout.
func TestTemplatePull_Stdout(t *testing.T) {
t.Parallel()
Expand All@@ -74,12 +75,129 @@ func TestTemplatePull_Stdout(t *testing.T) {

// Update the template version so that we can assert that templates
// are being sorted correctly.
updatedVersion := coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, source2, template.ID)
_ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, updatedVersion.ID)
coderdtest.UpdateActiveTemplateVersion(t, client, template.ID, updatedVersion.ID)

inv, root := clitest.New(t, "templates", "pull", "--tar", template.Name)
clitest.SetupConfig(t, client, root)

var buf bytes.Buffer
inv.Stdout = &buf

err = inv.Run()
require.NoError(t, err)

require.True(t, bytes.Equal(expected, buf.Bytes()), "tar files differ")
}

// Stdout tests that 'templates pull' pulls down the non-latest active template
// and writes it to stdout.
func TestTemplatePull_ActiveOldStdout(t *testing.T) {
t.Parallel()

client := coderdtest.New(t, &coderdtest.Options{
IncludeProvisionerDaemon: true,
})
user := coderdtest.CreateFirstUser(t, client)

source1 := genTemplateVersionSource()
source2 := genTemplateVersionSource()

expected, err := echo.Tar(source1)
require.NoError(t, err)

version1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, source1)
_ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, version1.ID)

template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version1.ID)

updatedVersion := coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, source2, template.ID)
_ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, updatedVersion.ID)

inv, root := clitest.New(t, "templates", "pull", "--tar", template.Name)
clitest.SetupConfig(t, client, root)

var buf bytes.Buffer
inv.Stdout = &buf
var stderr strings.Builder
inv.Stderr = &stderr

err = inv.Run()
require.NoError(t, err)

require.True(t, bytes.Equal(expected, buf.Bytes()), "tar files differ")
require.Contains(t, stderr.String(), "A newer template version than the active version exists.")
}

// Stdout tests that 'templates pull' pulls down the specified template and
// writes it to stdout.
func TestTemplatePull_SpecifiedStdout(t *testing.T) {
t.Parallel()

client := coderdtest.New(t, &coderdtest.Options{
IncludeProvisionerDaemon: true,
})
user := coderdtest.CreateFirstUser(t, client)

source1 := genTemplateVersionSource()
source2 := genTemplateVersionSource()
source3 := genTemplateVersionSource()

expected, err := echo.Tar(source1)
require.NoError(t, err)

version1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, source1)
_ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, version1.ID)

template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version1.ID)

updatedVersion := coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, source2, template.ID)
_ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, updatedVersion.ID)

updatedVersion2 := coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, source3, template.ID)
_ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, updatedVersion2.ID)
coderdtest.UpdateActiveTemplateVersion(t, client, template.ID, updatedVersion2.ID)

inv, root := clitest.New(t, "templates", "pull", "--tar", template.Name, "--version", version1.Name)
clitest.SetupConfig(t, client, root)

var buf bytes.Buffer
inv.Stdout = &buf

err = inv.Run()
require.NoError(t, err)

require.True(t, bytes.Equal(expected, buf.Bytes()), "tar files differ")
}

// Stdout tests that 'templates pull' pulls down the latest template
// and writes it to stdout.
func TestTemplatePull_LatestStdout(t *testing.T) {
t.Parallel()

client := coderdtest.New(t, &coderdtest.Options{
IncludeProvisionerDaemon: true,
})
user := coderdtest.CreateFirstUser(t, client)

source1 := genTemplateVersionSource()
source2 := genTemplateVersionSource()

expected, err := echo.Tar(source1)
require.NoError(t, err)

version1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, source1)
_ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, version1.ID)

template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version1.ID)

updatedVersion := coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, source2, template.ID)
_ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, updatedVersion.ID)

inv, root := clitest.New(t, "templates", "pull", "--tar", template.Name, "latest")
clitest.SetupConfig(t, client, root)

var buf bytes.Buffer
inv.Stdout = &buf

Expand All@@ -89,7 +207,7 @@ func TestTemplatePull_Stdout(t *testing.T) {
require.True(t, bytes.Equal(expected, buf.Bytes()), "tar files differ")
}

// ToDir tests that 'templates pull' pulls down thelatest template
// ToDir tests that 'templates pull' pulls down theactive template
// and writes it to the correct directory.
func TestTemplatePull_ToDir(t *testing.T) {
t.Parallel()
Expand DownExpand Up@@ -117,6 +235,7 @@ func TestTemplatePull_ToDir(t *testing.T) {
// are being sorted correctly.
updatedVersion := coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, source2, template.ID)
_ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, updatedVersion.ID)
coderdtest.UpdateActiveTemplateVersion(t, client, template.ID, updatedVersion.ID)

dir := t.TempDir()

Expand All@@ -140,8 +259,9 @@ func TestTemplatePull_ToDir(t *testing.T) {
)
}

// ToDir tests that 'templates pull' pulls down the latest template
// and writes it to a directory with the name of the template if the path is not implicitly supplied.
// ToDir tests that 'templates pull' pulls down the active template and writes
// it to a directory with the name of the template if the path is not implicitly
// supplied.
// nolint: paralleltest
func TestTemplatePull_ToImplicit(t *testing.T) {
client := coderdtest.New(t, &coderdtest.Options{
Expand All@@ -167,6 +287,7 @@ func TestTemplatePull_ToImplicit(t *testing.T) {
// are being sorted correctly.
updatedVersion := coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, source2, template.ID)
_ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, updatedVersion.ID)
coderdtest.UpdateActiveTemplateVersion(t, client, template.ID, updatedVersion.ID)

// create a tempdir and change the working directory to it for the duration of the test (cannot run in parallel)
dir := t.TempDir()
Expand DownExpand Up@@ -228,6 +349,7 @@ func TestTemplatePull_FolderConflict(t *testing.T) {
// are being sorted correctly.
updatedVersion := coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, source2, template.ID)
_ = coderdtest.AwaitTemplateVersionJobCompleted(t, client, updatedVersion.ID)
coderdtest.UpdateActiveTemplateVersion(t, client, template.ID, updatedVersion.ID)

dir := t.TempDir()

Expand Down
3 changes: 2 additions & 1 deletioncli/testdata/coder_templates_--help.golden
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,7 +29,8 @@ SUBCOMMANDS:
edit Edit the metadata of a template by name.
init Get started with a templated template.
list List all the templates available for the organization
pull Download the latest version of a template to a path.
pull Download the active, latest, or specified version of a template
to a path.
push Push a new template version from the current directory or as
specified by flag
versions Manage different versions of the specified template
Expand Down
7 changes: 6 additions & 1 deletioncli/testdata/coder_templates_pull_--help.golden
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -3,12 +3,17 @@ coder v0.0.0-devel
USAGE:
coder templates pull [flags] <name> [destination]

Download the latest version of a template to a path.
Download theactive,latest, or specified version of a template to a path.

OPTIONS:
--tar bool
Output the template as a tar archive to stdout.

--version string
The name of the template version to pull. Use 'active' to pull the
active version, 'latest' to pull the latest version, or the name of
the template version to pull.

-y, --yes bool
Bypass prompts.

Expand Down
12 changes: 10 additions & 2 deletionscoderd/coderdtest/coderdtest.go
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -753,11 +753,12 @@ func CreateTemplate(t *testing.T, client *codersdk.Client, organization uuid.UUI
// UpdateTemplateVersion creates a new template version with the "echo" provisioner
// and associates it with the given templateID.
func UpdateTemplateVersion(t *testing.T, client *codersdk.Client, organizationID uuid.UUID, res *echo.Responses, templateID uuid.UUID) codersdk.TemplateVersion {
ctx := context.Background()
data, err := echo.Tar(res)
require.NoError(t, err)
file, err := client.Upload(context.Background(), codersdk.ContentTypeTar, bytes.NewReader(data))
file, err := client.Upload(ctx, codersdk.ContentTypeTar, bytes.NewReader(data))
require.NoError(t, err)
templateVersion, err := client.CreateTemplateVersion(context.Background(), organizationID, codersdk.CreateTemplateVersionRequest{
templateVersion, err := client.CreateTemplateVersion(ctx, organizationID, codersdk.CreateTemplateVersionRequest{
TemplateID: templateID,
FileID: file.ID,
StorageMethod: codersdk.ProvisionerStorageMethodFile,
Expand All@@ -767,6 +768,13 @@ func UpdateTemplateVersion(t *testing.T, client *codersdk.Client, organizationID
return templateVersion
}

func UpdateActiveTemplateVersion(t *testing.T, client *codersdk.Client, templateID, versionID uuid.UUID) {
err := client.UpdateActiveTemplateVersion(context.Background(), templateID, codersdk.UpdateActiveTemplateVersion{
ID: versionID,
})
require.NoError(t, err)
}

// AwaitTemplateVersionJobRunning waits for the build to be picked up by a provisioner.
func AwaitTemplateVersionJobRunning(t *testing.T, client *codersdk.Client, version uuid.UUID) codersdk.TemplateVersion {
t.Helper()
Expand Down
2 changes: 1 addition & 1 deletiondocs/cli/templates.md
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

10 changes: 9 additions & 1 deletiondocs/cli/templates_pull.md
View file
Open in desktop

Some generated files are not rendered by default. Learn more abouthow customized files appear on GitHub.

Loading

[8]ページ先頭

©2009-2025 Movatter.jp