Skip to content

Commit

Permalink
Merge pull request #82 from runatlantis/speedup
Browse files Browse the repository at this point in the history
Add plugin cache. Don't run workspace if unneeded.
  • Loading branch information
lkysow authored Mar 20, 2018
2 parents 2dbb894 + b507bd0 commit 6bf86df
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 5 deletions.
39 changes: 35 additions & 4 deletions server/events/terraform/terraform_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"fmt"
"os"
"os/exec"
"path/filepath"
"regexp"
"strings"

Expand All @@ -35,14 +36,17 @@ type Client interface {
}

type DefaultClient struct {
defaultVersion *version.Version
defaultVersion *version.Version
terraformPluginCacheDir string
}

const terraformPluginCacheDirName = "plugin-cache"

// zeroPointNine constrains the version to be 0.9.*
var zeroPointNine = MustConstraint(">=0.9,<0.10")
var versionRegex = regexp.MustCompile("Terraform v(.*)\n")

func NewClient() (*DefaultClient, error) {
func NewClient(dataDir string) (*DefaultClient, error) {
// todo: use exec.LookPath to find out if we even have terraform rather than
// parsing the error looking for a not found error.
versionCmdOutput, err := exec.Command("terraform", "version").CombinedOutput() // #nosec
Expand All @@ -64,8 +68,16 @@ func NewClient() (*DefaultClient, error) {
return nil, errors.Wrap(err, "parsing terraform version")
}

// We will run terraform with the TF_PLUGIN_CACHE_DIR env var set to this
// directory inside our data dir.
cacheDir := filepath.Join(dataDir, terraformPluginCacheDirName)
if err := os.MkdirAll(cacheDir, 0700); err != nil {
return nil, errors.Wrapf(err, "unable to create terraform plugin cache directory at %q", terraformPluginCacheDirName)
}

return &DefaultClient{
defaultVersion: v,
defaultVersion: v,
terraformPluginCacheDir: cacheDir,
}, nil
}

Expand All @@ -91,6 +103,10 @@ func (c *DefaultClient) RunCommandWithVersion(log *logging.SimpleLogger, path st
// append current process's environment variables
// this is to prevent the $PATH variable being removed from the environment
envVars := []string{
// Will de-emphasize specific commands to run in output.
"TF_IN_AUTOMATION=true",
// Cache plugins so terraform init runs faster.
fmt.Sprintf("TF_PLUGIN_CACHE_DIR=%s", c.terraformPluginCacheDir),
fmt.Sprintf("WORKSPACE=%s", workspace),
fmt.Sprintf("ATLANTIS_TERRAFORM_VERSION=%s", v.String()),
fmt.Sprintf("DIR=%s", path),
Expand Down Expand Up @@ -132,11 +148,26 @@ func (c *DefaultClient) Init(log *logging.SimpleLogger, path string, workspace s
}

workspaceCommand := "workspace"
if zeroPointNine.Check(version) {
runningZeroPointNine := zeroPointNine.Check(version)
if runningZeroPointNine {
// In 0.9.* `env` was used instead of `workspace`
workspaceCommand = "env"
}

// Use `workspace show` to find out what workspace we're in now. If we're
// already in the right workspace then no need to switch. This will save us
// about ten seconds. This command is only available in > 0.10.
if !runningZeroPointNine {
workspaceShowOutput, err := c.RunCommandWithVersion(log, path, []string{workspaceCommand, "show"}, version, workspace) // nolint:vetshadow
outputs = append(outputs, workspaceShowOutput)
if err != nil {
return outputs, err
}
if strings.TrimSpace(workspaceShowOutput) == workspace {
return outputs, nil
}
}

output, err = c.RunCommandWithVersion(log, path, []string{workspaceCommand, "select", "-no-color", workspace}, version, workspace)
outputs = append(outputs, output)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion server/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ func NewServer(userConfig UserConfig, config Config) (*Server, error) {
}
vcsClient := vcs.NewDefaultClientProxy(githubClient, gitlabClient)
commitStatusUpdater := &events.DefaultCommitStatusUpdater{Client: vcsClient}
terraformClient, err := terraform.NewClient()
terraformClient, err := terraform.NewClient(userConfig.DataDir)
// The flag.Lookup call is to detect if we're running in a unit test. If we
// are, then we don't error out because we don't have/want terraform
// installed on our CI system where the unit tests run.
Expand Down

0 comments on commit 6bf86df

Please sign in to comment.