Thanks to visit codestin.com
Credit goes to github.com

Skip to content

chore: stream template upload #6035

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 our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Feb 4, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 0 additions & 2 deletions cli/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ var updateGoldenFiles = flag.Bool("update", false, "update .golden files")

//nolint:tparallel,paralleltest // These test sets env vars.
func TestCommandHelp(t *testing.T) {
t.Parallel()

commonEnv := map[string]string{
"CODER_CONFIG_DIR": "/tmp/coder-cli-test-config",
}
Expand Down
3 changes: 2 additions & 1 deletion cli/templateinit.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cli

import (
"bytes"
"fmt"
"os"
"path/filepath"
Expand Down Expand Up @@ -70,7 +71,7 @@ func templateInit() *cobra.Command {
if err != nil {
return err
}
err = provisionersdk.Untar(directory, archive)
err = provisionersdk.Untar(directory, bytes.NewReader(archive))
if err != nil {
return err
}
Expand Down
29 changes: 21 additions & 8 deletions cli/templatepush.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package cli

import (
"bufio"
"fmt"
"io"
"os"
Expand Down Expand Up @@ -34,14 +35,17 @@ func (pf *templateUploadFlags) stdin() bool {

func (pf *templateUploadFlags) upload(cmd *cobra.Command, client *codersdk.Client) (*codersdk.UploadResponse, error) {
var (
content []byte
err error
content io.Reader
pipeErrCh = make(chan error, 1)
)
if pf.stdin() {
content, err = io.ReadAll(cmd.InOrStdin())
content = cmd.InOrStdin()
// No piping if reading from stdin.
pipeErrCh <- nil
close(pipeErrCh)
} else {
prettyDir := prettyDirectoryPath(pf.directory)
_, err = cliui.Prompt(cmd, cliui.PromptOptions{
_, err := cliui.Prompt(cmd, cliui.PromptOptions{
Text: fmt.Sprintf("Upload %q?", prettyDir),
IsConfirm: true,
Default: cliui.ConfirmYes,
Expand All @@ -50,10 +54,16 @@ func (pf *templateUploadFlags) upload(cmd *cobra.Command, client *codersdk.Clien
return nil, err
}

content, err = provisionersdk.Tar(pf.directory, provisionersdk.TemplateArchiveLimit)
}
if err != nil {
return nil, xerrors.Errorf("read tar: %w", err)
pipeReader, pipeWriter := io.Pipe()
go func() {
defer pipeWriter.Close()
defer close(pipeErrCh)
bufWr := bufio.NewWriter(pipeWriter)
defer bufWr.Flush()
pipeErrCh <- provisionersdk.Tar(bufWr, pf.directory, provisionersdk.TemplateArchiveLimit)
}()
defer pipeReader.Close()
content = pipeReader
}

spin := spinner.New(spinner.CharSets[5], 100*time.Millisecond)
Expand All @@ -66,6 +76,9 @@ func (pf *templateUploadFlags) upload(cmd *cobra.Command, client *codersdk.Clien
if err != nil {
return nil, xerrors.Errorf("upload: %w", err)
}
if err = <-pipeErrCh; err != nil {
return nil, xerrors.Errorf("pipe: %w", err)
}
return &resp, nil
}

Expand Down
3 changes: 2 additions & 1 deletion coderd/coderdtest/authorize.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package coderdtest

import (
"bytes"
"context"
"fmt"
"io"
Expand Down Expand Up @@ -378,7 +379,7 @@ func NewAuthTester(ctx context.Context, t *testing.T, client *codersdk.Client, a
template := CreateTemplate(t, client, admin.OrganizationID, version.ID)
workspace := CreateWorkspace(t, client, admin.OrganizationID, template.ID)
AwaitWorkspaceBuildJob(t, client, workspace.LatestBuild.ID)
file, err := client.Upload(ctx, codersdk.ContentTypeTar, make([]byte, 1024))
file, err := client.Upload(ctx, codersdk.ContentTypeTar, bytes.NewReader(make([]byte, 1024)))
require.NoError(t, err, "upload file")
workspace, err = client.Workspace(ctx, workspace.ID)
require.NoError(t, err, "workspace resources")
Expand Down
4 changes: 2 additions & 2 deletions coderd/coderdtest/coderdtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -525,7 +525,7 @@ func CreateTemplateVersion(t *testing.T, client *codersdk.Client, organizationID
t.Helper()
data, err := echo.Tar(res)
require.NoError(t, err)
file, err := client.Upload(context.Background(), codersdk.ContentTypeTar, data)
file, err := client.Upload(context.Background(), codersdk.ContentTypeTar, bytes.NewReader(data))
require.NoError(t, err)
templateVersion, err := client.CreateTemplateVersion(context.Background(), organizationID, codersdk.CreateTemplateVersionRequest{
FileID: file.ID,
Expand Down Expand Up @@ -572,7 +572,7 @@ func CreateTemplate(t *testing.T, client *codersdk.Client, organization uuid.UUI
func UpdateTemplateVersion(t *testing.T, client *codersdk.Client, organizationID uuid.UUID, res *echo.Responses, templateID uuid.UUID) codersdk.TemplateVersion {
data, err := echo.Tar(res)
require.NoError(t, err)
file, err := client.Upload(context.Background(), codersdk.ContentTypeTar, data)
file, err := client.Upload(context.Background(), codersdk.ContentTypeTar, bytes.NewReader(data))
require.NoError(t, err)
templateVersion, err := client.CreateTemplateVersion(context.Background(), organizationID, codersdk.CreateTemplateVersionRequest{
TemplateID: templateID,
Expand Down
11 changes: 6 additions & 5 deletions coderd/files_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package coderd_test

import (
"bytes"
"context"
"net/http"
"testing"
Expand All @@ -23,7 +24,7 @@ func TestPostFiles(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()

_, err := client.Upload(ctx, "bad", []byte{'a'})
_, err := client.Upload(ctx, "bad", bytes.NewReader([]byte{'a'}))
require.Error(t, err)
})

Expand All @@ -35,7 +36,7 @@ func TestPostFiles(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()

_, err := client.Upload(ctx, codersdk.ContentTypeTar, make([]byte, 1024))
_, err := client.Upload(ctx, codersdk.ContentTypeTar, bytes.NewReader(make([]byte, 1024)))
require.NoError(t, err)
})

Expand All @@ -48,9 +49,9 @@ func TestPostFiles(t *testing.T) {
defer cancel()

data := make([]byte, 1024)
_, err := client.Upload(ctx, codersdk.ContentTypeTar, data)
_, err := client.Upload(ctx, codersdk.ContentTypeTar, bytes.NewReader(data))
require.NoError(t, err)
_, err = client.Upload(ctx, codersdk.ContentTypeTar, data)
_, err = client.Upload(ctx, codersdk.ContentTypeTar, bytes.NewReader(data))
require.NoError(t, err)
})
}
Expand Down Expand Up @@ -79,7 +80,7 @@ func TestDownload(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()

resp, err := client.Upload(ctx, codersdk.ContentTypeTar, make([]byte, 1024))
resp, err := client.Upload(ctx, codersdk.ContentTypeTar, bytes.NewReader(make([]byte, 1024)))
require.NoError(t, err)
data, contentType, err := client.Download(ctx, resp.ID)
require.NoError(t, err)
Expand Down
5 changes: 3 additions & 2 deletions coderd/templateversions_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package coderd_test

import (
"bytes"
"context"
"net/http"
"testing"
Expand Down Expand Up @@ -108,7 +109,7 @@ func TestPostTemplateVersionsByOrganization(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), testutil.WaitLong)
defer cancel()

file, err := client.Upload(ctx, codersdk.ContentTypeTar, data)
file, err := client.Upload(ctx, codersdk.ContentTypeTar, bytes.NewReader(data))
require.NoError(t, err)
version, err := client.CreateTemplateVersion(ctx, user.OrganizationID, codersdk.CreateTemplateVersionRequest{
Name: "bananas",
Expand Down Expand Up @@ -895,7 +896,7 @@ func TestPaginatedTemplateVersions(t *testing.T) {
templateVersionIDs := make([]uuid.UUID, total)
data, err := echo.Tar(nil)
require.NoError(t, err)
file, err := client.Upload(egCtx, codersdk.ContentTypeTar, data)
file, err := client.Upload(egCtx, codersdk.ContentTypeTar, bytes.NewReader(data))
require.NoError(t, err)
for i := 0; i < total; i++ {
i := i
Expand Down
10 changes: 6 additions & 4 deletions codersdk/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,18 +109,20 @@ func (c *Client) Request(ctx context.Context, method, path string, body interfac

var r io.Reader
if body != nil {
if data, ok := body.([]byte); ok {
switch data := body.(type) {
case io.Reader:
r = data
case []byte:
r = bytes.NewReader(data)
} else {
// Assume JSON if not bytes.
default:
// Assume JSON in all other cases.
buf := bytes.NewBuffer(nil)
enc := json.NewEncoder(buf)
enc.SetEscapeHTML(false)
err = enc.Encode(body)
if err != nil {
return nil, xerrors.Errorf("encode body: %w", err)
}

r = buf
}
}
Expand Down
4 changes: 2 additions & 2 deletions codersdk/files.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ type UploadResponse struct {

// Upload uploads an arbitrary file with the content type provided.
// This is used to upload a source-code archive.
func (c *Client) Upload(ctx context.Context, contentType string, content []byte) (UploadResponse, error) {
res, err := c.Request(ctx, http.MethodPost, "/api/v2/files", content, func(r *http.Request) {
func (c *Client) Upload(ctx context.Context, contentType string, rd io.Reader) (UploadResponse, error) {
res, err := c.Request(ctx, http.MethodPost, "/api/v2/files", rd, func(r *http.Request) {
r.Header.Set("Content-Type", contentType)
})
if err != nil {
Expand Down
3 changes: 2 additions & 1 deletion enterprise/coderd/provisionerdaemons_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package coderd_test

import (
"bytes"
"context"
"net/http"
"testing"
Expand Down Expand Up @@ -119,7 +120,7 @@ func TestProvisionerDaemonServe(t *testing.T) {
}},
})
require.NoError(t, err)
file, err := client.Upload(context.Background(), codersdk.ContentTypeTar, data)
file, err := client.Upload(context.Background(), codersdk.ContentTypeTar, bytes.NewReader(data))
require.NoError(t, err)

version, err := client.CreateTemplateVersion(context.Background(), user.OrganizationID, codersdk.CreateTemplateVersionRequest{
Expand Down
3 changes: 2 additions & 1 deletion enterprise/coderd/templates_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package coderd_test

import (
"bytes"
"context"
"net/http"
"testing"
Expand Down Expand Up @@ -300,7 +301,7 @@ func TestTemplateACL(t *testing.T) {

data, err := echo.Tar(nil)
require.NoError(t, err)
file, err := client1.Upload(context.Background(), codersdk.ContentTypeTar, data)
file, err := client1.Upload(context.Background(), codersdk.ContentTypeTar, bytes.NewReader(data))
require.NoError(t, err)

_, err = client1.CreateTemplateVersion(ctx, user.OrganizationID, codersdk.CreateTemplateVersionRequest{
Expand Down
26 changes: 12 additions & 14 deletions provisionersdk/archive.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package provisionersdk

import (
"archive/tar"
"bytes"
"io"
"os"
"path/filepath"
Expand Down Expand Up @@ -32,25 +31,24 @@ func dirHasExt(dir string, ext string) (bool, error) {
}

// Tar archives a Terraform directory.
func Tar(directory string, limit int64) ([]byte, error) {
var buffer bytes.Buffer
tarWriter := tar.NewWriter(&buffer)
func Tar(w io.Writer, directory string, limit int64) error {
tarWriter := tar.NewWriter(w)
totalSize := int64(0)

const tfExt = ".tf"
hasTf, err := dirHasExt(directory, tfExt)
if err != nil {
return nil, err
return err
}
if !hasTf {
absPath, err := filepath.Abs(directory)
if err != nil {
return nil, err
return err
}

// Show absolute path to aid in debugging. E.g. showing "." is
// useless.
return nil, xerrors.Errorf(
return xerrors.Errorf(
"%s is not a valid template since it has no %s files",
absPath, tfExt,
)
Expand Down Expand Up @@ -111,20 +109,20 @@ func Tar(directory string, limit int64) ([]byte, error) {
return data.Close()
})
if err != nil {
return nil, err
return err
}
err = tarWriter.Flush()
if err != nil {
return nil, err
return err
}
return buffer.Bytes(), nil
return nil
}

// Untar extracts the archive to a provided directory.
func Untar(directory string, archive []byte) error {
reader := tar.NewReader(bytes.NewReader(archive))
func Untar(directory string, r io.Reader) error {
tarReader := tar.NewReader(r)
for {
header, err := reader.Next()
header, err := tarReader.Next()
if xerrors.Is(err, io.EOF) {
return nil
}
Expand All @@ -149,7 +147,7 @@ func Untar(directory string, archive []byte) error {
return err
}
// Max file size of 10MB.
_, err = io.CopyN(file, reader, (1<<20)*10)
_, err = io.CopyN(file, tarReader, (1<<20)*10)
if xerrors.Is(err, io.EOF) {
err = nil
}
Expand Down
14 changes: 9 additions & 5 deletions provisionersdk/archive_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package provisionersdk_test

import (
"bytes"
"io"
"os"
"path/filepath"
"testing"
Expand All @@ -18,7 +20,7 @@ func TestTar(t *testing.T) {
file, err := os.CreateTemp(dir, "")
require.NoError(t, err)
_ = file.Close()
_, err = provisionersdk.Tar(dir, 1024)
err = provisionersdk.Tar(io.Discard, dir, 1024)
require.Error(t, err)
})
t.Run("Valid", func(t *testing.T) {
Expand All @@ -27,7 +29,7 @@ func TestTar(t *testing.T) {
file, err := os.CreateTemp(dir, "*.tf")
require.NoError(t, err)
_ = file.Close()
_, err = provisionersdk.Tar(dir, 1024)
err = provisionersdk.Tar(io.Discard, dir, 1024)
require.NoError(t, err)
})
t.Run("HiddenFiles", func(t *testing.T) {
Expand Down Expand Up @@ -71,10 +73,11 @@ func TestTar(t *testing.T) {
file.Name, err = filepath.Rel(dir, tmpFile.Name())
require.NoError(t, err)
}
content, err := provisionersdk.Tar(dir, 1024)
archive := new(bytes.Buffer)
err := provisionersdk.Tar(archive, dir, 1024)
require.NoError(t, err)
dir = t.TempDir()
err = provisionersdk.Untar(dir, content)
err = provisionersdk.Untar(dir, archive)
require.NoError(t, err)
for _, file := range files {
_, err = os.Stat(filepath.Join(dir, file.Name))
Expand All @@ -94,7 +97,8 @@ func TestUntar(t *testing.T) {
file, err := os.CreateTemp(dir, "*.tf")
require.NoError(t, err)
_ = file.Close()
archive, err := provisionersdk.Tar(dir, 1024)
archive := new(bytes.Buffer)
err = provisionersdk.Tar(archive, dir, 1024)
require.NoError(t, err)
dir = t.TempDir()
err = provisionersdk.Untar(dir, archive)
Expand Down