Skip to content

Commit

Permalink
fix: write downloaded executable atomically
Browse files Browse the repository at this point in the history
This may address an issue where a user interrupted `terraform-demux`
and ran into an issue where running the executable would result in a
`Killed: 9` message.
  • Loading branch information
ericnorris committed Oct 20, 2021
1 parent 01a1cb3 commit 0566733
Show file tree
Hide file tree
Showing 3 changed files with 14 additions and 18 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ require (
github.com/google/btree v1.0.1 // indirect
github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79
github.com/hashicorp/terraform-config-inspect v0.0.0-20210318070130-9a80970d6b34
github.com/natefinch/atomic v1.0.1 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.9.1
)
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/go-wordwrap v1.0.0 h1:6GlHJ/LTGMrIJbwgdqdl2eEH8o+Exx/0m8ir9Gns0u4=
github.com/mitchellh/go-wordwrap v1.0.0/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A=
github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM=
github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
Expand Down
29 changes: 11 additions & 18 deletions internal/releaseapi/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/Masterminds/semver/v3"
"github.com/gregjones/httpcache"
"github.com/gregjones/httpcache/diskcache"
"github.com/natefinch/atomic"
"github.com/pkg/errors"
)

Expand Down Expand Up @@ -122,22 +123,14 @@ func (c *Client) downloadBuild(build Build) (string, error) {
return "", err
}

defer zipFile.Close()

zipReader, err := zip.NewReader(zipFile, zipLength)

if err != nil {
return "", errors.Wrap(err, "could not unzip release archive")
}

destination, err := os.OpenFile(path, os.O_RDWR|os.O_CREATE, 0755)

if err != nil {
return "", errors.Wrap(err, "could not create destination file for executable")
}

defer destination.Close()

var found bool

for _, f := range zipReader.File {
if filepath.Base(f.Name) != "terraform" {
continue
Expand All @@ -146,23 +139,23 @@ func (c *Client) downloadBuild(build Build) (string, error) {
source, err := f.Open()

if err != nil {
return "", errors.Wrap(err, "could not read executable in release archive")
return "", errors.Wrap(err, "could not read binary in release archive")
}

defer source.Close()

if _, err := io.Copy(destination, source); err != nil {
return "", errors.Wrap(err, "could not copy executable to destination")
if err := atomic.WriteFile(path, source); err != nil {
return "", errors.Wrap(err, "could not write binary to the cache directory")
}

found = true
}
if err := os.Chmod(path, 0700); err != nil {
return "", errors.Wrap(err, "could not make binary executable")
}

if !found {
return "", errors.New("could not find executable named 'terraform' in release archive")
return path, nil
}

return path, nil
return "", errors.New("could not find executable named 'terraform' in release archive")
}

func (c *Client) downloadReleaseArchive(build Build) (*os.File, int64, error) {
Expand Down

0 comments on commit 0566733

Please sign in to comment.