go-mod: update go-tfe dependency

This commit is contained in:
Sander van Harmelen 2018-11-30 19:36:32 +01:00
parent 92e83e3bcf
commit 0e5587d091
10 changed files with 194 additions and 69 deletions

2
go.mod
View File

@ -68,7 +68,7 @@ require (
github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90
github.com/hashicorp/go-safetemp v0.0.0-20180326211150-b1a1dbde6fdc // indirect
github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86 // indirect
github.com/hashicorp/go-tfe v0.3.1
github.com/hashicorp/go-tfe v0.3.3
github.com/hashicorp/go-uuid v1.0.0
github.com/hashicorp/go-version v0.0.0-20180322230233-23480c066577
github.com/hashicorp/golang-lru v0.5.0 // indirect

8
go.sum
View File

@ -148,12 +148,12 @@ github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90 h1:9HVkPxOp
github.com/hashicorp/go-rootcerts v0.0.0-20160503143440-6bb64b370b90/go.mod h1:o4zcYY1e0GEZI6eSEr+43QDYmuGglw1qSO6qdHUHCgg=
github.com/hashicorp/go-safetemp v0.0.0-20180326211150-b1a1dbde6fdc h1:wAa9fGALVHfjYxZuXRnmuJG2CnwRpJYOTvY6YdErAh0=
github.com/hashicorp/go-safetemp v0.0.0-20180326211150-b1a1dbde6fdc/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
github.com/hashicorp/go-slug v0.1.0 h1:MJGEiOwRGrQCBmMMZABHqIESySFJ4ajrsjgDI4/aFI0=
github.com/hashicorp/go-slug v0.1.0/go.mod h1:+zDycQOzGqOqMW7Kn2fp9vz/NtqpMLQlgb9JUF+0km4=
github.com/hashicorp/go-slug v0.2.0 h1:gekvezBc+9LwN3qC+lesrz0Qg36hhgge9z/an1FCHx4=
github.com/hashicorp/go-slug v0.2.0/go.mod h1:+zDycQOzGqOqMW7Kn2fp9vz/NtqpMLQlgb9JUF+0km4=
github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86 h1:7YOlAIO2YWnJZkQp7B5eFykaIY7C9JndqAFQyVV5BhM=
github.com/hashicorp/go-sockaddr v0.0.0-20180320115054-6d291a969b86/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-tfe v0.3.1 h1:178hBlqjBsXohfcJ2/t2RM8c29IviQrEkj+mqdbkQzM=
github.com/hashicorp/go-tfe v0.3.1/go.mod h1:SRMjgjY06SfEKstIPRUVMtQfhSYR2H3GHVop0lfedkY=
github.com/hashicorp/go-tfe v0.3.3 h1:v17u0VdSy54n6Xn575cTzLrNJ0gn+Y7mq5J+A/p1fkw=
github.com/hashicorp/go-tfe v0.3.3/go.mod h1:Vssg8/lwVz+PyJ/nAK97zYmXxxLe28MCIMhKo+rva1o=
github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCSnM=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-version v0.0.0-20180322230233-23480c066577 h1:at4+18LrM8myamuV7/vT6x2s1JNXp2k4PsSbt4I02X4=

1
vendor/github.com/hashicorp/go-slug/go.mod generated vendored Normal file
View File

@ -0,0 +1 @@
module github.com/hashicorp/go-slug

View File

@ -7,6 +7,7 @@ import (
"io"
"os"
"path/filepath"
"strings"
)
// Meta provides detailed information about a slug.
@ -18,31 +19,54 @@ type Meta struct {
Size int64
}
// Pack creates a slug from a directory src, and writes the new
// slug to w. Returns metadata about the slug and any error.
func Pack(src string, w io.Writer) (*Meta, error) {
// Gzip compress all the output data
// Pack creates a slug from a src directory, and writes the new slug
// to w. Returns metadata about the slug and any errors.
//
// When dereference is set to true, symlinks with a target outside of
// the src directory will be dereferenced. When dereference is set to
// false symlinks with a target outside the src directory are omitted
// from the slug.
func Pack(src string, w io.Writer, dereference bool) (*Meta, error) {
// Gzip compress all the output data.
gzipW := gzip.NewWriter(w)
// Tar the file contents
// Tar the file contents.
tarW := tar.NewWriter(gzipW)
// Track the metadata details as we go.
meta := &Meta{}
// Walk the tree of files
err := filepath.Walk(src, func(path string, info os.FileInfo, err error) error {
// Walk the tree of files.
err := filepath.Walk(src, packWalkFn(src, src, src, tarW, meta, dereference))
if err != nil {
return nil, err
}
// Flush the tar writer.
if err := tarW.Close(); err != nil {
return nil, fmt.Errorf("Failed to close the tar archive: %v", err)
}
// Flush the gzip writer.
if err := gzipW.Close(); err != nil {
return nil, fmt.Errorf("Failed to close the gzip writer: %v", err)
}
return meta, nil
}
func packWalkFn(root, src, dst string, tarW *tar.Writer, meta *Meta, dereference bool) filepath.WalkFunc {
return func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
}
// Check the file type and if we need to write the body
keepFile, writeBody := checkFileMode(info.Mode())
if !keepFile {
return nil
// Skip the .git directory.
if info.IsDir() && info.Name() == ".git" {
return filepath.SkipDir
}
// Get the relative path from the unpack directory
// Get the relative path from the current src directory.
subpath, err := filepath.Rel(src, path)
if err != nil {
return fmt.Errorf("Failed to get relative path for file %q: %v", path, err)
@ -51,20 +75,94 @@ func Pack(src string, w io.Writer) (*Meta, error) {
return nil
}
// Read the symlink target. We don't track the error because
// it doesn't matter if there is an error.
target, _ := os.Readlink(path)
// Build the file header for the tar entry
header, err := tar.FileInfoHeader(info, target)
if err != nil {
return fmt.Errorf("Failed creating archive header for file %q: %v", path, err)
// Skip the .terraform directory, except for the modules subdirectory.
if strings.Contains(subpath, ".terraform") && info.Name() != ".terraform" {
if !strings.Contains(subpath, filepath.Clean(".terraform/modules")) {
return filepath.SkipDir
}
}
// Modify the header to properly be the full subpath
header.Name = subpath
if info.IsDir() {
// Get the relative path from the initial root directory.
subpath, err = filepath.Rel(root, strings.Replace(path, src, dst, 1))
if err != nil {
return fmt.Errorf("Failed to get relative path for file %q: %v", path, err)
}
if subpath == "." {
return nil
}
// Check the file type and if we need to write the body.
keepFile, writeBody := checkFileMode(info.Mode())
if !keepFile {
return nil
}
fm := info.Mode()
header := &tar.Header{
Name: filepath.ToSlash(subpath),
ModTime: info.ModTime(),
Mode: int64(fm.Perm()),
}
switch {
case info.IsDir():
header.Typeflag = tar.TypeDir
header.Name += "/"
case fm.IsRegular():
header.Typeflag = tar.TypeReg
header.Size = info.Size()
case fm&os.ModeSymlink != 0:
target, err := filepath.EvalSymlinks(path)
if err != nil {
return fmt.Errorf("Failed to get symbolic link destination for %q: %v", path, err)
}
// If the target is within the current source, we
// create the symlink using a relative path.
if strings.Contains(target, src) {
link, err := filepath.Rel(filepath.Dir(path), target)
if err != nil {
return fmt.Errorf("Failed to get relative path for symlink destination %q: %v", target, err)
}
header.Typeflag = tar.TypeSymlink
header.Linkname = filepath.ToSlash(link)
// Break out of the case as a symlink
// doesn't need any additional config.
break
}
if !dereference {
// Return early as the symlink has a target outside of the
// src directory and we don't want to dereference symlinks.
return nil
}
// Get the file info for the target.
info, err = os.Lstat(target)
if err != nil {
return fmt.Errorf("Failed to get file info from file %q: %v", target, err)
}
// If the target is a directory we can recurse into the target
// directory by calling the packWalkFn with updated arguments.
if info.IsDir() {
return filepath.Walk(target, packWalkFn(root, target, path, tarW, meta, dereference))
}
// Dereference this symlink by updating the header with the target file
// details and set writeBody to true so the body will be written.
header.Typeflag = tar.TypeReg
header.ModTime = info.ModTime()
header.Mode = int64(info.Mode().Perm())
header.Size = info.Size()
writeBody = true
default:
return fmt.Errorf("Unexpected file mode %v", fm)
}
// Write the header first to the archive.
@ -72,7 +170,7 @@ func Pack(src string, w io.Writer) (*Meta, error) {
return fmt.Errorf("Failed writing archive header for file %q: %v", path, err)
}
// Account for the file in the list
// Account for the file in the list.
meta.Files = append(meta.Files, header.Name)
// Skip writing file data for certain file types (above).
@ -80,51 +178,37 @@ func Pack(src string, w io.Writer) (*Meta, error) {
return nil
}
// Add the size since we are going to write the body.
meta.Size += info.Size()
f, err := os.Open(path)
if err != nil {
return fmt.Errorf("Failed opening file %q for archiving: %v", path, err)
}
defer f.Close()
if _, err = io.Copy(tarW, f); err != nil {
size, err := io.Copy(tarW, f)
if err != nil {
return fmt.Errorf("Failed copying file %q to archive: %v", path, err)
}
// Add the size we copied to the body.
meta.Size += size
return nil
})
if err != nil {
return nil, err
}
// Flush the tar writer
if err := tarW.Close(); err != nil {
return nil, fmt.Errorf("Failed to close the tar archive: %v", err)
}
// Flush the gzip writer
if err := gzipW.Close(); err != nil {
return nil, fmt.Errorf("Failed to close the gzip writer: %v", err)
}
return meta, nil
}
// Unpack is used to read and extract the contents of a slug to
// directory dst. Returns any error.
// the dst directory. Returns any errors.
func Unpack(r io.Reader, dst string) error {
// Decompress as we read
// Decompress as we read.
uncompressed, err := gzip.NewReader(r)
if err != nil {
return fmt.Errorf("Failed to uncompress slug: %v", err)
}
// Untar as we read
// Untar as we read.
untar := tar.NewReader(uncompressed)
// Unpackage all the contents into the directory
// Unpackage all the contents into the directory.
for {
header, err := untar.Next()
if err == io.EOF {
@ -134,14 +218,14 @@ func Unpack(r io.Reader, dst string) error {
return fmt.Errorf("Failed to untar slug: %v", err)
}
// Get rid of absolute paths
// Get rid of absolute paths.
path := header.Name
if path[0] == '/' {
path = path[1:]
}
path = filepath.Join(dst, path)
// Make the directories to the path
// Make the directories to the path.
dir := filepath.Dir(path)
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("Failed to create directory %q: %v", dir, err)
@ -156,7 +240,7 @@ func Unpack(r io.Reader, dst string) error {
continue
}
// Only unpack regular files from this point on
// Only unpack regular files from this point on.
if header.Typeflag == tar.TypeDir {
continue
} else if header.Typeflag != tar.TypeReg && header.Typeflag != tar.TypeRegA {
@ -164,12 +248,12 @@ func Unpack(r io.Reader, dst string) error {
header.Typeflag)
}
// Open a handle to the destination
// Open a handle to the destination.
fh, err := os.Create(path)
if err != nil {
// This mimics tar's behavior wrt the tar file containing duplicate files
// and it allowing later ones to clobber earlier ones even if the file
// has perms that don't allow overwriting
// has perms that don't allow overwriting.
if os.IsPermission(err) {
os.Chmod(path, 0600)
fh, err = os.Create(path)
@ -180,7 +264,7 @@ func Unpack(r io.Reader, dst string) error {
}
}
// Copy the contents
// Copy the contents.
_, err = io.Copy(fh, untar)
fh.Close()
if err != nil {
@ -201,12 +285,12 @@ func Unpack(r io.Reader, dst string) error {
// be included in the archive, and if it has a data body which needs writing.
func checkFileMode(m os.FileMode) (keep, body bool) {
switch {
case m.IsRegular():
return true, true
case m.IsDir():
return true, false
case m.IsRegular():
return true, true
case m&os.ModeSymlink != 0:
return true, false
}

View File

@ -185,7 +185,7 @@ func (s *configurationVersions) Read(ctx context.Context, cvID string) (*Configu
func (s *configurationVersions) Upload(ctx context.Context, url, path string) error {
body := bytes.NewBuffer(nil)
_, err := slug.Pack(path, body)
_, err := slug.Pack(path, body, true)
if err != nil {
return err
}

View File

@ -5,7 +5,7 @@ require (
github.com/google/go-querystring v1.0.0
github.com/hashicorp/go-cleanhttp v0.5.0
github.com/hashicorp/go-retryablehttp v0.5.0
github.com/hashicorp/go-slug v0.1.0
github.com/hashicorp/go-slug v0.2.0
github.com/hashicorp/go-uuid v1.0.0
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/stretchr/testify v1.2.2

View File

@ -6,8 +6,8 @@ github.com/hashicorp/go-cleanhttp v0.5.0 h1:wvCrVc9TjDls6+YGAF2hAifE1E5U1+b4tH6K
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-retryablehttp v0.5.0 h1:aVN0FYnPwAgZI/hVzqwfMiM86ttcHTlQKbBVeVmXPIs=
github.com/hashicorp/go-retryablehttp v0.5.0/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-slug v0.1.0 h1:MJGEiOwRGrQCBmMMZABHqIESySFJ4ajrsjgDI4/aFI0=
github.com/hashicorp/go-slug v0.1.0/go.mod h1:+zDycQOzGqOqMW7Kn2fp9vz/NtqpMLQlgb9JUF+0km4=
github.com/hashicorp/go-slug v0.2.0 h1:gekvezBc+9LwN3qC+lesrz0Qg36hhgge9z/an1FCHx4=
github.com/hashicorp/go-slug v0.2.0/go.mod h1:+zDycQOzGqOqMW7Kn2fp9vz/NtqpMLQlgb9JUF+0km4=
github.com/hashicorp/go-uuid v1.0.0 h1:RS8zrF7PhGwyNPOtxSClXXj9HA8feRnJzgnI1RJCSnM=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=

View File

@ -38,6 +38,13 @@ var (
// random is used to generate pseudo-random numbers.
random = rand.New(rand.NewSource(time.Now().UnixNano()))
// ErrWorkspaceLocked is returned when trying to lock a
// locked workspace.
ErrWorkspaceLocked = errors.New("workspace already locked")
// ErrWorkspaceNotLocked is returned when trying to unlock
// a unlocked workspace.
ErrWorkspaceNotLocked = errors.New("workspace already unlocked")
// ErrUnauthorized is returned when a receiving a 401.
ErrUnauthorized = errors.New("unauthorized")
// ErrResourceNotFound is returned when a receiving a 404.
@ -164,8 +171,8 @@ func NewClient(cfg *Config) (*Client, error) {
ErrorHandler: retryablehttp.PassthroughErrorHandler,
HTTPClient: config.HTTPClient,
RetryWaitMin: 100 * time.Millisecond,
RetryWaitMax: 300 * time.Millisecond,
RetryMax: 5,
RetryWaitMax: 400 * time.Millisecond,
RetryMax: 30,
},
}
@ -505,6 +512,15 @@ func checkResponseCode(r *http.Response) error {
return ErrUnauthorized
case 404:
return ErrResourceNotFound
case 409:
switch {
case strings.HasSuffix(r.Request.URL.Path, "actions/lock"):
return ErrWorkspaceLocked
case strings.HasSuffix(r.Request.URL.Path, "actions/unlock"):
return ErrWorkspaceNotLocked
case strings.HasSuffix(r.Request.URL.Path, "actions/force-unlock"):
return ErrWorkspaceNotLocked
}
}
// Decode the error payload.

View File

@ -37,6 +37,9 @@ type Workspaces interface {
// Unlock a workspace by its ID.
Unlock(ctx context.Context, workspaceID string) (*Workspace, error)
// ForceUnlock a workspace by its ID.
ForceUnlock(ctx context.Context, workspaceID string) (*Workspace, error)
// AssignSSHKey to a workspace.
AssignSSHKey(ctx context.Context, workspaceID string, options WorkspaceAssignSSHKeyOptions) (*Workspace, error)
@ -369,6 +372,27 @@ func (s *workspaces) Unlock(ctx context.Context, workspaceID string) (*Workspace
return w, nil
}
// ForceUnlock a workspace by its ID.
func (s *workspaces) ForceUnlock(ctx context.Context, workspaceID string) (*Workspace, error) {
if !validStringID(&workspaceID) {
return nil, errors.New("invalid value for workspace ID")
}
u := fmt.Sprintf("workspaces/%s/actions/force-unlock", url.QueryEscape(workspaceID))
req, err := s.client.newRequest("POST", u, nil)
if err != nil {
return nil, err
}
w := &Workspace{}
err = s.client.do(ctx, req, w)
if err != nil {
return nil, err
}
return w, nil
}
// WorkspaceAssignSSHKeyOptions represents the options to assign an SSH key to
// a workspace.
type WorkspaceAssignSSHKeyOptions struct {

4
vendor/modules.txt vendored
View File

@ -324,9 +324,9 @@ github.com/hashicorp/go-retryablehttp
github.com/hashicorp/go-rootcerts
# github.com/hashicorp/go-safetemp v0.0.0-20180326211150-b1a1dbde6fdc
github.com/hashicorp/go-safetemp
# github.com/hashicorp/go-slug v0.1.0
# github.com/hashicorp/go-slug v0.2.0
github.com/hashicorp/go-slug
# github.com/hashicorp/go-tfe v0.3.1
# github.com/hashicorp/go-tfe v0.3.3
github.com/hashicorp/go-tfe
# github.com/hashicorp/go-uuid v1.0.0
github.com/hashicorp/go-uuid