From e8ad3d458d7619a3181393380a493f03c66a5f28 Mon Sep 17 00:00:00 2001 From: sreya Date: Tue, 14 Jun 2022 19:44:42 +0000 Subject: [PATCH 1/6] feat: Add template pull cmd --- cli/templatepull.go | 91 ++++++++++++++++++++++++++++++++++ cli/templatepull_test.go | 79 +++++++++++++++++++++++++++++ cli/templates.go | 1 + coderd/provisionerjobs.go | 7 +-- coderd/templateversions.go | 6 +++ codersdk/provisionerdaemons.go | 1 + 6 files changed, 182 insertions(+), 3 deletions(-) create mode 100644 cli/templatepull.go create mode 100644 cli/templatepull_test.go diff --git a/cli/templatepull.go b/cli/templatepull.go new file mode 100644 index 0000000000000..5a9c6fa31d90a --- /dev/null +++ b/cli/templatepull.go @@ -0,0 +1,91 @@ +package cli + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/spf13/cobra" + "golang.org/x/xerrors" + + "github.com/coder/coder/codersdk" +) + +func templatePull() *cobra.Command { + cmd := &cobra.Command{ + Use: "pull [destination]", + Short: "Download the latest version of a template to a path.", + Args: cobra.MaximumNArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + var ( + ctx = cmd.Context() + templateName = args[0] + dest string + ) + + if len(args) > 1 { + dest = args[1] + } + + client, err := createClient(cmd) + if err != nil { + return xerrors.Errorf("create client: %w", err) + } + + // TODO(JonA): Do we need to add a flag for organization? + organization, err := currentOrganization(cmd, client) + if err != nil { + return xerrors.Errorf("current organization: %w", err) + } + + template, err := client.TemplateByName(ctx, organization.ID, templateName) + if err != nil { + return xerrors.Errorf("template by name: %w", err) + } + + 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) + } + + // TemplateVersionsByTemplate returns the versions in order from newest + // to oldest. + latest := versions[0] + + raw, ctype, err := client.Download(ctx, latest.Job.SourceHash) + if err != nil { + return xerrors.Errorf("download template: %w", err) + } + + if ctype != codersdk.ContentTypeTar { + return xerrors.Errorf("unexpected Content-Type %q, expecting %q", ctype, codersdk.ContentTypeTar) + } + + if dest == "" { + _, err = cmd.OutOrStdout().Write(raw) + if err != nil { + return xerrors.Errorf("write stdout: %w", err) + } + return nil + } + + name := fmt.Sprintf("%s.tar", templateName) + err = os.WriteFile(filepath.Join(dest, name), raw, 0600) + if err != nil { + return xerrors.Errorf("write to path: %w", err) + } + + // TODO(Handle '~') + + return nil + }, + } + + return cmd +} diff --git a/cli/templatepull_test.go b/cli/templatepull_test.go new file mode 100644 index 0000000000000..fe1ac8cffdf81 --- /dev/null +++ b/cli/templatepull_test.go @@ -0,0 +1,79 @@ +package cli_test + +import ( + "bytes" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/coder/coder/cli/clitest" + "github.com/coder/coder/coderd/coderdtest" + "github.com/coder/coder/provisioner/echo" + "github.com/coder/coder/provisionersdk/proto" + "github.com/coder/coder/pty/ptytest" +) + +func TestTemplatePull(t *testing.T) { + t.Parallel() + + client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true}) + user := coderdtest.CreateFirstUser(t, client) + + templateSource := &echo.Responses{ + Parse: []*proto.Parse_Response{ + { + Type: &proto.Parse_Response_Log{ + Log: &proto.Log{Output: "yahoo"}, + }, + }, + + { + Type: &proto.Parse_Response_Complete{ + Complete: &proto.Parse_Complete{}, + }, + }, + }, + Provision: echo.ProvisionComplete, + } + + templateSource2 := &echo.Responses{ + Parse: []*proto.Parse_Response{ + { + Type: &proto.Parse_Response_Log{ + Log: &proto.Log{Output: "wahoo"}, + }, + }, + + { + Type: &proto.Parse_Response_Complete{ + Complete: &proto.Parse_Complete{}, + }, + }, + }, + Provision: echo.ProvisionComplete, + } + + expected, err := echo.Tar(templateSource2) + require.NoError(t, err) + + version1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, templateSource) + _ = coderdtest.AwaitTemplateVersionJob(t, client, version1.ID) + template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version1.ID) + + _ = coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, templateSource2, template.ID) + + cmd, root := clitest.New(t, "templates", "pull", template.Name) + clitest.SetupConfig(t, client, root) + + buf := &bytes.Buffer{} + pty := ptytest.New(t) + cmd.SetOut(buf) + + err = cmd.Execute() + require.NoError(t, err) + + err = pty.Close() + require.NoError(t, err) + + require.True(t, bytes.Equal(expected, buf.Bytes()), "Bytes differ") +} diff --git a/cli/templates.go b/cli/templates.go index c737bb6c134c0..e06e60ab33e93 100644 --- a/cli/templates.go +++ b/cli/templates.go @@ -33,6 +33,7 @@ func templates() *cobra.Command { templateUpdate(), templateVersions(), templateDelete(), + templatePull(), ) return cmd diff --git a/coderd/provisionerjobs.go b/coderd/provisionerjobs.go index 325c2aaccb7d7..acdd822c8be5c 100644 --- a/coderd/provisionerjobs.go +++ b/coderd/provisionerjobs.go @@ -287,9 +287,10 @@ func convertProvisionerJobLog(provisionerJobLog database.ProvisionerJobLog) code func convertProvisionerJob(provisionerJob database.ProvisionerJob) codersdk.ProvisionerJob { job := codersdk.ProvisionerJob{ - ID: provisionerJob.ID, - CreatedAt: provisionerJob.CreatedAt, - Error: provisionerJob.Error.String, + ID: provisionerJob.ID, + CreatedAt: provisionerJob.CreatedAt, + Error: provisionerJob.Error.String, + SourceHash: provisionerJob.StorageSource, } // Applying values optional to the struct. if provisionerJob.StartedAt.Valid { diff --git a/coderd/templateversions.go b/coderd/templateversions.go index 64345457e969c..4949c0c6d38c0 100644 --- a/coderd/templateversions.go +++ b/coderd/templateversions.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "net/http" + "sort" "github.com/go-chi/chi/v5" "github.com/google/uuid" @@ -473,6 +474,11 @@ func (api *API) templateVersionsByTemplate(rw http.ResponseWriter, r *http.Reque return } + // Sort the slice from newest to oldest template. + sort.SliceStable(apiVersions, func(i, j int) bool { + return apiVersions[i].CreatedAt.After(apiVersions[j].CreatedAt) + }) + httpapi.Write(rw, http.StatusOK, apiVersions) } diff --git a/codersdk/provisionerdaemons.go b/codersdk/provisionerdaemons.go index d9d232bb0ec0d..9c272fabfa018 100644 --- a/codersdk/provisionerdaemons.go +++ b/codersdk/provisionerdaemons.go @@ -67,6 +67,7 @@ type ProvisionerJob struct { Error string `json:"error,omitempty"` Status ProvisionerJobStatus `json:"status"` WorkerID *uuid.UUID `json:"worker_id,omitempty"` + SourceHash string } type ProvisionerJobLog struct { From c274b27a897f6fbec3f8a6c0354921640fb15d5b Mon Sep 17 00:00:00 2001 From: sreya Date: Tue, 14 Jun 2022 20:05:03 +0000 Subject: [PATCH 2/6] add some minor comments --- cli/templatepull_test.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cli/templatepull_test.go b/cli/templatepull_test.go index fe1ac8cffdf81..6b8da66502cb0 100644 --- a/cli/templatepull_test.go +++ b/cli/templatepull_test.go @@ -10,7 +10,6 @@ import ( "github.com/coder/coder/coderd/coderdtest" "github.com/coder/coder/provisioner/echo" "github.com/coder/coder/provisionersdk/proto" - "github.com/coder/coder/pty/ptytest" ) func TestTemplatePull(t *testing.T) { @@ -19,6 +18,7 @@ func TestTemplatePull(t *testing.T) { client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true}) user := coderdtest.CreateFirstUser(t, client) + // Create an initial template bundle. templateSource := &echo.Responses{ Parse: []*proto.Parse_Response{ { @@ -36,6 +36,8 @@ func TestTemplatePull(t *testing.T) { Provision: echo.ProvisionComplete, } + // Create an updated template bundle. This will be used to ensure + // that templates are correctly returned in order from latest to oldest. templateSource2 := &echo.Responses{ Parse: []*proto.Parse_Response{ { @@ -60,20 +62,18 @@ func TestTemplatePull(t *testing.T) { _ = coderdtest.AwaitTemplateVersionJob(t, client, version1.ID) template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version1.ID) + // Update the template version so that we can assert that templates + // are being sorted correctly. _ = coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, templateSource2, template.ID) cmd, root := clitest.New(t, "templates", "pull", template.Name) clitest.SetupConfig(t, client, root) buf := &bytes.Buffer{} - pty := ptytest.New(t) cmd.SetOut(buf) err = cmd.Execute() require.NoError(t, err) - err = pty.Close() - require.NoError(t, err) - require.True(t, bytes.Equal(expected, buf.Bytes()), "Bytes differ") } From 4ff6a5bd6d37349841bffc0c9ba1e91aec82cdfe Mon Sep 17 00:00:00 2001 From: sreya Date: Wed, 15 Jun 2022 00:07:18 +0000 Subject: [PATCH 3/6] update some tests --- cli/clitest/clitest.go | 25 ++++++ cli/templatepull.go | 41 ++++++++-- cli/templatepull_test.go | 163 +++++++++++++++++++++++-------------- coderd/templateversions.go | 6 -- 4 files changed, 162 insertions(+), 73 deletions(-) diff --git a/cli/clitest/clitest.go b/cli/clitest/clitest.go index 5e0e38b7718d0..7d3366474807c 100644 --- a/cli/clitest/clitest.go +++ b/cli/clitest/clitest.go @@ -9,6 +9,7 @@ import ( "path/filepath" "testing" + "github.com/google/uuid" "github.com/spf13/cobra" "github.com/stretchr/testify/require" @@ -16,6 +17,7 @@ import ( "github.com/coder/coder/cli/config" "github.com/coder/coder/codersdk" "github.com/coder/coder/provisioner/echo" + "github.com/coder/coder/provisionersdk/proto" ) // New creates a CLI instance with a configuration pointed to a @@ -46,6 +48,29 @@ func CreateTemplateVersionSource(t *testing.T, responses *echo.Responses) string return directory } +// GenTemplateVersion returns a unique bundle that can be used to create +// a template version source. +func GenTemplateVersion() *echo.Responses { + return &echo.Responses{ + Parse: []*proto.Parse_Response{ + { + Type: &proto.Parse_Response_Log{ + Log: &proto.Log{ + Output: uuid.NewString(), + }, + }, + }, + + { + Type: &proto.Parse_Response_Complete{ + Complete: &proto.Parse_Complete{}, + }, + }, + }, + Provision: echo.ProvisionComplete, + } +} + func extractTar(t *testing.T, data []byte, directory string) { reader := tar.NewReader(bytes.NewBuffer(data)) for { diff --git a/cli/templatepull.go b/cli/templatepull.go index 5a9c6fa31d90a..eca3efa2bf578 100644 --- a/cli/templatepull.go +++ b/cli/templatepull.go @@ -2,12 +2,14 @@ package cli import ( "fmt" + "io/fs" "os" - "path/filepath" + "sort" "github.com/spf13/cobra" "golang.org/x/xerrors" + "github.com/coder/coder/cli/cliui" "github.com/coder/coder/codersdk" ) @@ -54,6 +56,11 @@ func templatePull() *cobra.Command { 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) + }) + // TemplateVersionsByTemplate returns the versions in order from newest // to oldest. latest := versions[0] @@ -67,6 +74,8 @@ func templatePull() *cobra.Command { return xerrors.Errorf("unexpected Content-Type %q, expecting %q", ctype, codersdk.ContentTypeTar) } + // If the destination is empty then we write to stdout + // and bail early. if dest == "" { _, err = cmd.OutOrStdout().Write(raw) if err != nil { @@ -75,17 +84,39 @@ func templatePull() *cobra.Command { return nil } - name := fmt.Sprintf("%s.tar", templateName) - err = os.WriteFile(filepath.Join(dest, name), raw, 0600) + // Stat the destination to ensure nothing exists already. + fi, err := os.Stat(dest) + if err != nil && !xerrors.Is(err, fs.ErrNotExist) { + return xerrors.Errorf("stat destination: %w", err) + } + + if fi != nil && fi.IsDir() { + // If the destination is a directory we just bail. + return xerrors.Errorf("%q already exists.", dest) + } + + // If a file exists at the destination prompt the user + // to ensure we don't overwrite something valuable. + if fi != nil { + _, err = cliui.Prompt(cmd, cliui.PromptOptions{ + Text: fmt.Sprintf("%q already exists, do you want to overwrite it?", dest), + IsConfirm: true, + }) + if err != nil { + return xerrors.Errorf("parse prompt: %w", err) + } + } + + err = os.WriteFile(dest, raw, 0600) if err != nil { return xerrors.Errorf("write to path: %w", err) } - // TODO(Handle '~') - return nil }, } + cliui.AllowSkipPrompt(cmd) + return cmd } diff --git a/cli/templatepull_test.go b/cli/templatepull_test.go index 6b8da66502cb0..1c59b3552b6ff 100644 --- a/cli/templatepull_test.go +++ b/cli/templatepull_test.go @@ -2,6 +2,8 @@ package cli_test import ( "bytes" + "os" + "path/filepath" "testing" "github.com/stretchr/testify/require" @@ -9,71 +11,108 @@ import ( "github.com/coder/coder/cli/clitest" "github.com/coder/coder/coderd/coderdtest" "github.com/coder/coder/provisioner/echo" - "github.com/coder/coder/provisionersdk/proto" + "github.com/coder/coder/pty/ptytest" ) func TestTemplatePull(t *testing.T) { t.Parallel() - client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true}) - user := coderdtest.CreateFirstUser(t, client) - - // Create an initial template bundle. - templateSource := &echo.Responses{ - Parse: []*proto.Parse_Response{ - { - Type: &proto.Parse_Response_Log{ - Log: &proto.Log{Output: "yahoo"}, - }, - }, - - { - Type: &proto.Parse_Response_Complete{ - Complete: &proto.Parse_Complete{}, - }, - }, - }, - Provision: echo.ProvisionComplete, - } - - // Create an updated template bundle. This will be used to ensure - // that templates are correctly returned in order from latest to oldest. - templateSource2 := &echo.Responses{ - Parse: []*proto.Parse_Response{ - { - Type: &proto.Parse_Response_Log{ - Log: &proto.Log{Output: "wahoo"}, - }, - }, - - { - Type: &proto.Parse_Response_Complete{ - Complete: &proto.Parse_Complete{}, - }, - }, - }, - Provision: echo.ProvisionComplete, - } - - expected, err := echo.Tar(templateSource2) - require.NoError(t, err) - - version1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, templateSource) - _ = coderdtest.AwaitTemplateVersionJob(t, client, version1.ID) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version1.ID) - - // Update the template version so that we can assert that templates - // are being sorted correctly. - _ = coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, templateSource2, template.ID) - - cmd, root := clitest.New(t, "templates", "pull", template.Name) - clitest.SetupConfig(t, client, root) - - buf := &bytes.Buffer{} - cmd.SetOut(buf) - - err = cmd.Execute() - require.NoError(t, err) - - require.True(t, bytes.Equal(expected, buf.Bytes()), "Bytes differ") + // Stdout tests that 'templates pull' pulls down the latest template + // and writes it to stdout. + t.Run("Stdout", func(t *testing.T) { + t.Parallel() + + client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true}) + user := coderdtest.CreateFirstUser(t, client) + + // Create an initial template bundle. + source1 := clitest.GenTemplateVersion() + // Create an updated template bundle. This will be used to ensure + // that templates are correctly returned in order from latest to oldest. + source2 := clitest.GenTemplateVersion() + + expected, err := echo.Tar(source2) + require.NoError(t, err) + + version1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, source1) + _ = coderdtest.AwaitTemplateVersionJob(t, client, version1.ID) + + template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version1.ID) + + // Update the template version so that we can assert that templates + // are being sorted correctly. + _ = coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, source2, template.ID) + + cmd, root := clitest.New(t, "templates", "pull", template.Name) + clitest.SetupConfig(t, client, root) + + var buf bytes.Buffer + cmd.SetOut(&buf) + + err = cmd.Execute() + require.NoError(t, err) + + require.True(t, bytes.Equal(expected, buf.Bytes()), "tar files differ") + }) + + // ToFile tests that 'templates pull' pulls down the latest template + // and writes it to the correct directory. + t.Run("ToFile", func(t *testing.T) { + t.Parallel() + + client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerD: true}) + user := coderdtest.CreateFirstUser(t, client) + + // Create an initial template bundle. + source1 := clitest.GenTemplateVersion() + // Create an updated template bundle. This will be used to ensure + // that templates are correctly returned in order from latest to oldest. + source2 := clitest.GenTemplateVersion() + + expected, err := echo.Tar(source2) + require.NoError(t, err) + + version1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, source1) + _ = coderdtest.AwaitTemplateVersionJob(t, client, version1.ID) + + template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version1.ID) + + // Update the template version so that we can assert that templates + // are being sorted correctly. + _ = coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, source2, template.ID) + + dir := t.TempDir() + + dest := filepath.Join(dir, "actual.tar") + + // Create the file so that we can test that the command + // warns the user before overwriting a preexisting file. + fi, err := os.OpenFile(dest, os.O_CREATE|os.O_RDONLY, 0600) + require.NoError(t, err) + _ = fi.Close() + + cmd, root := clitest.New(t, "templates", "pull", template.Name, dest) + clitest.SetupConfig(t, client, root) + + pty := ptytest.New(t) + cmd.SetIn(pty.Input()) + cmd.SetOut(pty.Output()) + + errChan := make(chan error) + go func() { + defer close(errChan) + errChan <- cmd.Execute() + }() + + // We expect to be prompted that a file already exists. + pty.ExpectMatch("already exists") + pty.WriteLine("yes") + + require.NoError(t, <-errChan) + + actual, err := os.ReadFile(dest) + require.NoError(t, err) + + require.True(t, bytes.Equal(actual, expected), "tar files differ") + }) } diff --git a/coderd/templateversions.go b/coderd/templateversions.go index 4949c0c6d38c0..64345457e969c 100644 --- a/coderd/templateversions.go +++ b/coderd/templateversions.go @@ -6,7 +6,6 @@ import ( "errors" "fmt" "net/http" - "sort" "github.com/go-chi/chi/v5" "github.com/google/uuid" @@ -474,11 +473,6 @@ func (api *API) templateVersionsByTemplate(rw http.ResponseWriter, r *http.Reque return } - // Sort the slice from newest to oldest template. - sort.SliceStable(apiVersions, func(i, j int) bool { - return apiVersions[i].CreatedAt.After(apiVersions[j].CreatedAt) - }) - httpapi.Write(rw, http.StatusOK, apiVersions) } From 67fd76edf54c3464285d73986c103858d9b519cd Mon Sep 17 00:00:00 2001 From: sreya Date: Wed, 15 Jun 2022 00:38:12 +0000 Subject: [PATCH 4/6] some generated types --- codersdk/provisionerdaemons.go | 2 +- site/src/api/typesGenerated.ts | 3 ++- site/src/testHelpers/entities.ts | 2 ++ 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/codersdk/provisionerdaemons.go b/codersdk/provisionerdaemons.go index 9c272fabfa018..3190704020833 100644 --- a/codersdk/provisionerdaemons.go +++ b/codersdk/provisionerdaemons.go @@ -67,7 +67,7 @@ type ProvisionerJob struct { Error string `json:"error,omitempty"` Status ProvisionerJobStatus `json:"status"` WorkerID *uuid.UUID `json:"worker_id,omitempty"` - SourceHash string + SourceHash string `json:"source_hash"` } type ProvisionerJobLog struct { diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 49ae60058a061..b32072815bbb6 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -211,9 +211,10 @@ export interface ProvisionerJob { readonly error?: string readonly status: ProvisionerJobStatus readonly worker_id?: string + readonly source_hash: string } -// From codersdk/provisionerdaemons.go:72:6 +// From codersdk/provisionerdaemons.go:73:6 export interface ProvisionerJobLog { readonly id: string readonly created_at: string diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index b37e038529dbc..454acf1f373e0 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -69,7 +69,9 @@ export const MockProvisionerJob: TypesGen.ProvisionerJob = { created_at: "", id: "test-provisioner-job", status: "succeeded", + source_hash: "asdf", } + export const MockFailedProvisionerJob: TypesGen.ProvisionerJob = { ...MockProvisionerJob, status: "failed", From dbca68245e641daee19ee6f407015c455230955b Mon Sep 17 00:00:00 2001 From: sreya Date: Wed, 15 Jun 2022 16:35:47 +0000 Subject: [PATCH 5/6] pr comments --- cli/clitest/clitest.go | 25 ------------------------ cli/templatepull.go | 5 +++-- cli/templatepull_test.go | 33 ++++++++++++++++++++++++++++---- codersdk/provisionerdaemons.go | 16 ++++++++-------- site/src/api/typesGenerated.ts | 2 +- site/src/testHelpers/entities.ts | 2 +- 6 files changed, 42 insertions(+), 41 deletions(-) diff --git a/cli/clitest/clitest.go b/cli/clitest/clitest.go index 7d3366474807c..5e0e38b7718d0 100644 --- a/cli/clitest/clitest.go +++ b/cli/clitest/clitest.go @@ -9,7 +9,6 @@ import ( "path/filepath" "testing" - "github.com/google/uuid" "github.com/spf13/cobra" "github.com/stretchr/testify/require" @@ -17,7 +16,6 @@ import ( "github.com/coder/coder/cli/config" "github.com/coder/coder/codersdk" "github.com/coder/coder/provisioner/echo" - "github.com/coder/coder/provisionersdk/proto" ) // New creates a CLI instance with a configuration pointed to a @@ -48,29 +46,6 @@ func CreateTemplateVersionSource(t *testing.T, responses *echo.Responses) string return directory } -// GenTemplateVersion returns a unique bundle that can be used to create -// a template version source. -func GenTemplateVersion() *echo.Responses { - return &echo.Responses{ - Parse: []*proto.Parse_Response{ - { - Type: &proto.Parse_Response_Log{ - Log: &proto.Log{ - Output: uuid.NewString(), - }, - }, - }, - - { - Type: &proto.Parse_Response_Complete{ - Complete: &proto.Parse_Complete{}, - }, - }, - }, - Provision: echo.ProvisionComplete, - } -} - func extractTar(t *testing.T, data []byte, directory string) { reader := tar.NewReader(bytes.NewBuffer(data)) for { diff --git a/cli/templatepull.go b/cli/templatepull.go index eca3efa2bf578..552aebf952c87 100644 --- a/cli/templatepull.go +++ b/cli/templatepull.go @@ -45,6 +45,8 @@ func templatePull() *cobra.Command { return xerrors.Errorf("template 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, }) @@ -61,10 +63,9 @@ func templatePull() *cobra.Command { return versions[i].CreatedAt.After(versions[j].CreatedAt) }) - // TemplateVersionsByTemplate returns the versions in order from newest - // to oldest. latest := versions[0] + // Download the tar archive. raw, ctype, err := client.Download(ctx, latest.Job.SourceHash) if err != nil { return xerrors.Errorf("download template: %w", err) diff --git a/cli/templatepull_test.go b/cli/templatepull_test.go index 1c59b3552b6ff..249733c8c043b 100644 --- a/cli/templatepull_test.go +++ b/cli/templatepull_test.go @@ -6,11 +6,13 @@ import ( "path/filepath" "testing" + "github.com/google/uuid" "github.com/stretchr/testify/require" "github.com/coder/coder/cli/clitest" "github.com/coder/coder/coderd/coderdtest" "github.com/coder/coder/provisioner/echo" + "github.com/coder/coder/provisionersdk/proto" "github.com/coder/coder/pty/ptytest" ) @@ -26,10 +28,10 @@ func TestTemplatePull(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) // Create an initial template bundle. - source1 := clitest.GenTemplateVersion() + source1 := genTemplateVersionSource() // Create an updated template bundle. This will be used to ensure // that templates are correctly returned in order from latest to oldest. - source2 := clitest.GenTemplateVersion() + source2 := genTemplateVersionSource() expected, err := echo.Tar(source2) require.NoError(t, err) @@ -64,10 +66,10 @@ func TestTemplatePull(t *testing.T) { user := coderdtest.CreateFirstUser(t, client) // Create an initial template bundle. - source1 := clitest.GenTemplateVersion() + source1 := genTemplateVersionSource() // Create an updated template bundle. This will be used to ensure // that templates are correctly returned in order from latest to oldest. - source2 := clitest.GenTemplateVersion() + source2 := genTemplateVersionSource() expected, err := echo.Tar(source2) require.NoError(t, err) @@ -116,3 +118,26 @@ func TestTemplatePull(t *testing.T) { require.True(t, bytes.Equal(actual, expected), "tar files differ") }) } + +// genTemplateVersionSource returns a unique bundle that can be used to create +// a template version source. +func genTemplateVersionSource() *echo.Responses { + return &echo.Responses{ + Parse: []*proto.Parse_Response{ + { + Type: &proto.Parse_Response_Log{ + Log: &proto.Log{ + Output: uuid.NewString(), + }, + }, + }, + + { + Type: &proto.Parse_Response_Complete{ + Complete: &proto.Parse_Complete{}, + }, + }, + }, + Provision: echo.ProvisionComplete, + } +} diff --git a/codersdk/provisionerdaemons.go b/codersdk/provisionerdaemons.go index 3190704020833..5027d30ab9d60 100644 --- a/codersdk/provisionerdaemons.go +++ b/codersdk/provisionerdaemons.go @@ -60,14 +60,14 @@ const ( ) type ProvisionerJob struct { - ID uuid.UUID `json:"id"` - CreatedAt time.Time `json:"created_at"` - StartedAt *time.Time `json:"started_at,omitempty"` - CompletedAt *time.Time `json:"completed_at,omitempty"` - Error string `json:"error,omitempty"` - Status ProvisionerJobStatus `json:"status"` - WorkerID *uuid.UUID `json:"worker_id,omitempty"` - SourceHash string `json:"source_hash"` + ID uuid.UUID `json:"id"` + CreatedAt time.Time `json:"created_at"` + StartedAt *time.Time `json:"started_at,omitempty"` + CompletedAt *time.Time `json:"completed_at,omitempty"` + Error string `json:"error,omitempty"` + Status ProvisionerJobStatus `json:"status"` + WorkerID *uuid.UUID `json:"worker_id,omitempty"` + StorageSource string `json:"storage_source"` } type ProvisionerJobLog struct { diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index b32072815bbb6..3a142b208cb53 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -211,7 +211,7 @@ export interface ProvisionerJob { readonly error?: string readonly status: ProvisionerJobStatus readonly worker_id?: string - readonly source_hash: string + readonly storage_source: string } // From codersdk/provisionerdaemons.go:73:6 diff --git a/site/src/testHelpers/entities.ts b/site/src/testHelpers/entities.ts index 454acf1f373e0..1c8a513a3027e 100644 --- a/site/src/testHelpers/entities.ts +++ b/site/src/testHelpers/entities.ts @@ -69,7 +69,7 @@ export const MockProvisionerJob: TypesGen.ProvisionerJob = { created_at: "", id: "test-provisioner-job", status: "succeeded", - source_hash: "asdf", + storage_source: "asdf", } export const MockFailedProvisionerJob: TypesGen.ProvisionerJob = { From 09196be17745507d831ec9e10efc6b22d13a60a2 Mon Sep 17 00:00:00 2001 From: sreya Date: Wed, 15 Jun 2022 16:39:23 +0000 Subject: [PATCH 6/6] missed some files --- cli/templatepull.go | 2 +- coderd/provisionerjobs.go | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/cli/templatepull.go b/cli/templatepull.go index 552aebf952c87..61cc7e7b8e62b 100644 --- a/cli/templatepull.go +++ b/cli/templatepull.go @@ -66,7 +66,7 @@ func templatePull() *cobra.Command { latest := versions[0] // Download the tar archive. - raw, ctype, err := client.Download(ctx, latest.Job.SourceHash) + raw, ctype, err := client.Download(ctx, latest.Job.StorageSource) if err != nil { return xerrors.Errorf("download template: %w", err) } diff --git a/coderd/provisionerjobs.go b/coderd/provisionerjobs.go index acdd822c8be5c..f10ba0358aa2c 100644 --- a/coderd/provisionerjobs.go +++ b/coderd/provisionerjobs.go @@ -287,10 +287,10 @@ func convertProvisionerJobLog(provisionerJobLog database.ProvisionerJobLog) code func convertProvisionerJob(provisionerJob database.ProvisionerJob) codersdk.ProvisionerJob { job := codersdk.ProvisionerJob{ - ID: provisionerJob.ID, - CreatedAt: provisionerJob.CreatedAt, - Error: provisionerJob.Error.String, - SourceHash: provisionerJob.StorageSource, + ID: provisionerJob.ID, + CreatedAt: provisionerJob.CreatedAt, + Error: provisionerJob.Error.String, + StorageSource: provisionerJob.StorageSource, } // Applying values optional to the struct. if provisionerJob.StartedAt.Valid {