From b4dc0ed508290edea9be2f3dd4f116c37f096db7 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Fri, 25 Aug 2023 12:32:27 +0400 Subject: [PATCH 1/3] fix: fix coder template pull on Windows Signed-off-by: Spike Curtis --- cli/templatepull.go | 2 +- cli/templatepull_test.go | 274 +++++++++++++++++++++++---------------- 2 files changed, 165 insertions(+), 111 deletions(-) diff --git a/cli/templatepull.go b/cli/templatepull.go index 8f234447a6dba..eb772379b9611 100644 --- a/cli/templatepull.go +++ b/cli/templatepull.go @@ -83,7 +83,7 @@ func (r *RootCmd) templatePull() *clibase.Cmd { } if dest == "" { - dest = templateName + "/" + dest = templateName } err = os.MkdirAll(dest, 0o750) diff --git a/cli/templatepull_test.go b/cli/templatepull_test.go index 95b0a6cf9aa30..17c578197d462 100644 --- a/cli/templatepull_test.go +++ b/cli/templatepull_test.go @@ -40,165 +40,219 @@ func dirSum(t *testing.T, dir string) string { return hex.EncodeToString(sum.Sum(nil)) } -func TestTemplatePull(t *testing.T) { +func TestTemplatePull_NoName(t *testing.T) { t.Parallel() - t.Run("NoName", func(t *testing.T) { - t.Parallel() + inv, _ := clitest.New(t, "templates", "pull") + err := inv.Run() + require.Error(t, err) +} - inv, _ := clitest.New(t, "templates", "pull") - err := inv.Run() - require.Error(t, err) - }) +// Stdout tests that 'templates pull' pulls down the latest template +// and writes it to stdout. +func TestTemplatePull_Stdout(t *testing.T) { + t.Parallel() - // 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{IncludeProvisionerDaemon: true}) + user := coderdtest.CreateFirstUser(t, client) - client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) - user := coderdtest.CreateFirstUser(t, client) + // Create an initial template bundle. + 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 := genTemplateVersionSource() - // Create an initial template bundle. - 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 := genTemplateVersionSource() + expected, err := echo.Tar(source2) + require.NoError(t, err) - expected, err := echo.Tar(source2) - require.NoError(t, err) + version1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, source1) + _ = coderdtest.AwaitTemplateVersionJob(t, client, version1.ID) - version1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, source1) - _ = coderdtest.AwaitTemplateVersionJob(t, client, version1.ID) + template := coderdtest.CreateTemplate(t, client, user.OrganizationID, 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) - // Update the template version so that we can assert that templates - // are being sorted correctly. - _ = coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, source2, template.ID) + inv, root := clitest.New(t, "templates", "pull", "--tar", template.Name) + clitest.SetupConfig(t, client, root) - inv, root := clitest.New(t, "templates", "pull", "--tar", template.Name) - clitest.SetupConfig(t, client, root) + var buf bytes.Buffer + inv.Stdout = &buf - var buf bytes.Buffer - inv.Stdout = &buf + err = inv.Run() + require.NoError(t, err) - err = inv.Run() - require.NoError(t, err) + require.True(t, bytes.Equal(expected, buf.Bytes()), "tar files differ") +} - require.True(t, bytes.Equal(expected, buf.Bytes()), "tar files differ") - }) +// ToDir tests that 'templates pull' pulls down the latest template +// and writes it to the correct directory. +func TestTemplatePull_ToDir(t *testing.T) { + t.Parallel() - // ToDir tests that 'templates pull' pulls down the latest template - // and writes it to the correct directory. - t.Run("ToDir", func(t *testing.T) { - t.Parallel() + client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) + user := coderdtest.CreateFirstUser(t, client) - client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) - user := coderdtest.CreateFirstUser(t, client) + // Create an initial template bundle. + 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 := genTemplateVersionSource() - // Create an initial template bundle. - 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 := genTemplateVersionSource() + expected, err := echo.Tar(source2) + require.NoError(t, err) - 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) - version1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, source1) - _ = coderdtest.AwaitTemplateVersionJob(t, client, 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) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version1.ID) + dir := t.TempDir() - // Update the template version so that we can assert that templates - // are being sorted correctly. - _ = coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, source2, template.ID) + expectedDest := filepath.Join(dir, "expected") + actualDest := filepath.Join(dir, "actual") + ctx := context.Background() - dir := t.TempDir() + err = extract.Tar(ctx, bytes.NewReader(expected), expectedDest, nil) + require.NoError(t, err) - expectedDest := filepath.Join(dir, "expected") - actualDest := filepath.Join(dir, "actual") - ctx := context.Background() + inv, root := clitest.New(t, "templates", "pull", template.Name, actualDest) + clitest.SetupConfig(t, client, root) - err = extract.Tar(ctx, bytes.NewReader(expected), expectedDest, nil) - require.NoError(t, err) + ptytest.New(t).Attach(inv) + + require.NoError(t, inv.Run()) - inv, root := clitest.New(t, "templates", "pull", template.Name, actualDest) - clitest.SetupConfig(t, client, root) + require.Equal(t, + dirSum(t, expectedDest), + dirSum(t, actualDest), + ) +} - ptytest.New(t).Attach(inv) +// 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. +// nolint: paralleltest +func TestTemplatePull_ToImplicit(t *testing.T) { - require.NoError(t, inv.Run()) + client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) + user := coderdtest.CreateFirstUser(t, client) - require.Equal(t, - dirSum(t, expectedDest), - dirSum(t, actualDest), - ) - }) + // Create an initial template bundle. + 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 := genTemplateVersionSource() - // FolderConflict tests that 'templates pull' fails when a folder with has - // existing - t.Run("FolderConflict", func(t *testing.T) { - t.Parallel() + expected, err := echo.Tar(source2) + require.NoError(t, err) - client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) - user := coderdtest.CreateFirstUser(t, client) + version1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, source1) + _ = coderdtest.AwaitTemplateVersionJob(t, client, version1.ID) - // Create an initial template bundle. - 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 := genTemplateVersionSource() + template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version1.ID) - expected, err := echo.Tar(source2) + // Update the template version so that we can assert that templates + // are being sorted correctly. + _ = coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, source2, template.ID) + + // create a tempdir and change the working directory to it for the duration of the test (cannot run in parallel) + dir := t.TempDir() + wd, err := os.Getwd() + require.NoError(t, err) + err = os.Chdir(dir) + require.NoError(t, err) + defer func() { + err := os.Chdir(wd) require.NoError(t, err) + }() - version1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, source1) - _ = coderdtest.AwaitTemplateVersionJob(t, client, version1.ID) + expectedDest := filepath.Join(dir, "expected") + actualDest := filepath.Join(dir, template.Name) - template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version1.ID) + ctx := context.Background() - // Update the template version so that we can assert that templates - // are being sorted correctly. - _ = coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, source2, template.ID) + err = extract.Tar(ctx, bytes.NewReader(expected), expectedDest, nil) + require.NoError(t, err) - dir := t.TempDir() + inv, root := clitest.New(t, "templates", "pull", template.Name) + clitest.SetupConfig(t, client, root) - expectedDest := filepath.Join(dir, "expected") - conflictDest := filepath.Join(dir, "conflict") + ptytest.New(t).Attach(inv) - err = os.MkdirAll(conflictDest, 0o700) - require.NoError(t, err) + require.NoError(t, inv.Run()) - err = os.WriteFile( - filepath.Join(conflictDest, "conflict-file"), - []byte("conflict"), 0o600, - ) - require.NoError(t, err) + require.Equal(t, + dirSum(t, expectedDest), + dirSum(t, actualDest), + ) +} - ctx := context.Background() +// FolderConflict tests that 'templates pull' fails when a folder with has +// existing +func TestTemplatePull_FolderConflict(t *testing.T) { + t.Parallel() - err = extract.Tar(ctx, bytes.NewReader(expected), expectedDest, nil) - require.NoError(t, err) + client := coderdtest.New(t, &coderdtest.Options{IncludeProvisionerDaemon: true}) + user := coderdtest.CreateFirstUser(t, client) - inv, root := clitest.New(t, "templates", "pull", template.Name, conflictDest) - clitest.SetupConfig(t, client, root) + // Create an initial template bundle. + 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 := genTemplateVersionSource() - pty := ptytest.New(t).Attach(inv) + expected, err := echo.Tar(source2) + require.NoError(t, err) - waiter := clitest.StartWithWaiter(t, inv) + version1 := coderdtest.CreateTemplateVersion(t, client, user.OrganizationID, source1) + _ = coderdtest.AwaitTemplateVersionJob(t, client, version1.ID) - pty.ExpectMatch("not empty") - pty.WriteLine("no") + template := coderdtest.CreateTemplate(t, client, user.OrganizationID, version1.ID) - waiter.RequireError() + // Update the template version so that we can assert that templates + // are being sorted correctly. + _ = coderdtest.UpdateTemplateVersion(t, client, user.OrganizationID, source2, template.ID) - ents, err := os.ReadDir(conflictDest) - require.NoError(t, err) + dir := t.TempDir() + + expectedDest := filepath.Join(dir, "expected") + conflictDest := filepath.Join(dir, "conflict") + + err = os.MkdirAll(conflictDest, 0o700) + require.NoError(t, err) + + err = os.WriteFile( + filepath.Join(conflictDest, "conflict-file"), + []byte("conflict"), 0o600, + ) + require.NoError(t, err) + + ctx := context.Background() + + err = extract.Tar(ctx, bytes.NewReader(expected), expectedDest, nil) + require.NoError(t, err) + + inv, root := clitest.New(t, "templates", "pull", template.Name, conflictDest) + clitest.SetupConfig(t, client, root) + + pty := ptytest.New(t).Attach(inv) + + waiter := clitest.StartWithWaiter(t, inv) + + pty.ExpectMatch("not empty") + pty.WriteLine("no") + + waiter.RequireError() + + ents, err := os.ReadDir(conflictDest) + require.NoError(t, err) - require.Len(t, ents, 1, "conflict folder should have single conflict file") - }) + require.Len(t, ents, 1, "conflict folder should have single conflict file") } // genTemplateVersionSource returns a unique bundle that can be used to create From 1563223d437be4b8b5ab1c25ee650f077699c9b7 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Fri, 25 Aug 2023 08:40:15 +0000 Subject: [PATCH 2/3] appease linter Signed-off-by: Spike Curtis --- cli/templatepull_test.go | 1 - 1 file changed, 1 deletion(-) diff --git a/cli/templatepull_test.go b/cli/templatepull_test.go index 17c578197d462..f4a20b88651a7 100644 --- a/cli/templatepull_test.go +++ b/cli/templatepull_test.go @@ -138,7 +138,6 @@ func TestTemplatePull_ToDir(t *testing.T) { // 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{IncludeProvisionerDaemon: true}) user := coderdtest.CreateFirstUser(t, client) From 1a9878a7c435e0f286c5ae57566108b207d21742 Mon Sep 17 00:00:00 2001 From: Spike Curtis Date: Fri, 25 Aug 2023 08:48:34 +0000 Subject: [PATCH 3/3] improvements from code review Signed-off-by: Spike Curtis --- cli/templatepull_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cli/templatepull_test.go b/cli/templatepull_test.go index f4a20b88651a7..5a5e7bc6c9e06 100644 --- a/cli/templatepull_test.go +++ b/cli/templatepull_test.go @@ -167,7 +167,7 @@ func TestTemplatePull_ToImplicit(t *testing.T) { require.NoError(t, err) defer func() { err := os.Chdir(wd) - require.NoError(t, err) + require.NoError(t, err, "if this fails, it can break other subsequent tests due to wrong working directory") }() expectedDest := filepath.Join(dir, "expected")