Files
coder/provisionersdk/archive.go
Kyle Carberry c451f4e685 feat: Add templates to create working release (#422)
* Add templates

* Move API structs to codersdk

* Back to green tests!

* It all works, but now with tea! 🧋

* It works!

* Add cancellation to provisionerd

* Tests pass!

* Add deletion of workspaces and projects

* Fix agent lock

* Add clog

* Fix linting errors

* Remove unused CLI tests

* Rename daemon to start

* Fix leaking command

* Fix promptui test

* Update agent connection frequency

* Skip login tests on Windows

* Increase tunnel connect timeout

* Fix templater

* Lower test requirements

* Fix embed

* Disable promptui tests for Windows

* Fix write newline

* Fix PTY write newline

* Fix CloseReader

* Fix compilation on Windows

* Fix linting error

* Remove bubbletea

* Cleanup readwriter

* Use embedded templates instead of serving over API

* Move templates to examples

* Improve workspace create flow

* Fix Windows build

* Fix tests

* Fix linting errors

* Fix untar with extracting max size

* Fix newline char
2022-03-22 13:17:50 -06:00

101 lines
2.0 KiB
Go

package provisionersdk
import (
"archive/tar"
"bytes"
"io"
"os"
"path/filepath"
"strings"
"golang.org/x/xerrors"
)
// Tar archives a directory.
func Tar(directory string) ([]byte, error) {
var buffer bytes.Buffer
tarWriter := tar.NewWriter(&buffer)
err := filepath.Walk(directory, func(file string, fileInfo os.FileInfo, err error) error {
if err != nil {
return err
}
header, err := tar.FileInfoHeader(fileInfo, file)
if err != nil {
return err
}
rel, err := filepath.Rel(directory, file)
if err != nil {
return err
}
if strings.HasPrefix(rel, ".") {
// Don't archive hidden files!
return err
}
if strings.Contains(rel, ".tfstate") {
// Don't store tfstate!
return err
}
header.Name = rel
if err := tarWriter.WriteHeader(header); err != nil {
return err
}
if fileInfo.IsDir() {
return nil
}
data, err := os.Open(file)
if err != nil {
return err
}
if _, err := io.Copy(tarWriter, data); err != nil {
return err
}
return data.Close()
})
if err != nil {
return nil, err
}
err = tarWriter.Flush()
if err != nil {
return nil, err
}
return buffer.Bytes(), nil
}
// Untar extracts the archive to a provided directory.
func Untar(directory string, archive []byte) error {
reader := tar.NewReader(bytes.NewReader(archive))
for {
header, err := reader.Next()
if xerrors.Is(err, io.EOF) {
return nil
}
if err != nil {
return err
}
// #nosec
target := filepath.Join(directory, header.Name)
switch header.Typeflag {
case tar.TypeDir:
if _, err := os.Stat(target); err != nil {
if err := os.MkdirAll(target, 0755); err != nil {
return err
}
}
case tar.TypeReg:
file, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode))
if err != nil {
return err
}
// Max file size of 10MB.
_, err = io.CopyN(file, reader, (1<<20)*10)
if xerrors.Is(err, io.EOF) {
err = nil
}
if err != nil {
return err
}
_ = file.Close()
}
}
}