Skip to content

Commit

Permalink
feat: add version command (#1691)
Browse files Browse the repository at this point in the history
  • Loading branch information
pjsier authored Jul 12, 2021
1 parent 23015f3 commit d358857
Show file tree
Hide file tree
Showing 17 changed files with 663 additions and 76 deletions.
9 changes: 9 additions & 0 deletions server/controllers/events/events_controller_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -858,11 +858,20 @@ func setupE2E(t *testing.T, repoDir string) (events_controllers.VCSEventsControl
silenceNoProjects,
)

versionCommandRunner := events.NewVersionCommandRunner(
pullUpdater,
projectCommandBuilder,
projectCommandRunner,
parallelPoolSize,
silenceNoProjects,
)

commentCommandRunnerByCmd := map[models.CommandName]events.CommentCommandRunner{
models.PlanCommand: planCommandRunner,
models.ApplyCommand: applyCommandRunner,
models.ApprovePoliciesCommand: approvePoliciesCommandRunner,
models.UnlockCommand: unlockCommandRunner,
models.VersionCommand: versionCommandRunner,
}

commandRunner := &events.DefaultCommandRunner{
Expand Down
25 changes: 25 additions & 0 deletions server/core/runtime/version_step_runner.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package runtime

import (
"path/filepath"

"github.com/hashicorp/go-version"
"github.com/runatlantis/atlantis/server/events/models"
)

// VersionStepRunner runs a version command given a ctx
type VersionStepRunner struct {
TerraformExecutor TerraformExec
DefaultTFVersion *version.Version
}

// Run ensures a given version for the executable, builds the args from the project context and then runs executable returning the result
func (v *VersionStepRunner) Run(ctx models.ProjectCommandContext, extraArgs []string, path string, envs map[string]string) (string, error) {
tfVersion := v.DefaultTFVersion
if ctx.TerraformVersion != nil {
tfVersion = ctx.TerraformVersion
}

versionCmd := []string{"version"}
return v.TerraformExecutor.RunCommandWithVersion(ctx.Log, filepath.Clean(path), versionCmd, envs, tfVersion, ctx.Workspace)
}
50 changes: 50 additions & 0 deletions server/core/runtime/version_step_runner_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package runtime

import (
"testing"

"github.com/hashicorp/go-version"
. "github.com/petergtz/pegomock"
"github.com/runatlantis/atlantis/server/core/terraform/mocks"
"github.com/runatlantis/atlantis/server/events/models"
"github.com/runatlantis/atlantis/server/logging"
. "github.com/runatlantis/atlantis/testing"
)

func TestRunVersionStep(t *testing.T) {
RegisterMockTestingT(t)
logger := logging.NewNoopLogger(t)
workspace := "default"

context := models.ProjectCommandContext{
Log: logger,
EscapedCommentArgs: []string{"comment", "args"},
Workspace: workspace,
RepoRelDir: ".",
User: models.User{Username: "username"},
Pull: models.PullRequest{
Num: 2,
},
BaseRepo: models.Repo{
FullName: "owner/repo",
Owner: "owner",
Name: "repo",
},
}

terraform := mocks.NewMockClient()
tfVersion, _ := version.NewVersion("0.15.0")
tmpDir, cleanup := TempDir(t)
defer cleanup()

s := &VersionStepRunner{
TerraformExecutor: terraform,
DefaultTFVersion: tfVersion,
}

t.Run("ensure runs", func(t *testing.T) {
_, err := s.Run(context, []string{}, tmpDir, map[string]string(nil))
terraform.VerifyWasCalledOnce().RunCommandWithVersion(logger, tmpDir, []string{"version"}, map[string]string(nil), tfVersion, "default")
Ok(t, err)
})
}
9 changes: 9 additions & 0 deletions server/events/command_runner_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,20 @@ func setup(t *testing.T) *vcsmocks.MockClient {
SilenceNoProjects,
)

versionCommandRunner := events.NewVersionCommandRunner(
pullUpdater,
projectCommandBuilder,
projectCommandRunner,
parallelPoolSize,
SilenceNoProjects,
)

commentCommandRunnerByCmd := map[models.CommandName]events.CommentCommandRunner{
models.PlanCommand: planCommandRunner,
models.ApplyCommand: applyCommandRunner,
models.ApprovePoliciesCommand: approvePoliciesCommandRunner,
models.UnlockCommand: unlockCommandRunner,
models.VersionCommand: versionCommandRunner,
}

preWorkflowHooksCommandRunner = mocks.NewMockPreWorkflowHooksCommandRunner()
Expand Down
18 changes: 17 additions & 1 deletion server/events/comment_parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ type CommentBuilder interface {
BuildPlanComment(repoRelDir string, workspace string, project string, commentArgs []string) string
// BuildApplyComment builds an apply comment for the specified args.
BuildApplyComment(repoRelDir string, workspace string, project string, autoMergeDisabled bool) string
// BuildVersionComment builds a version comment for the specified args.
BuildVersionComment(repoRelDir string, workspace string, project string) string
}

// CommentParser implements CommentParsing
Expand Down Expand Up @@ -165,7 +167,7 @@ func (e *CommentParser) Parse(comment string, vcsHost models.VCSHostType) Commen
}

// Need to have a plan, apply, approve_policy or unlock at this point.
if !e.stringInSlice(command, []string{models.PlanCommand.String(), models.ApplyCommand.String(), models.UnlockCommand.String(), models.ApprovePoliciesCommand.String()}) {
if !e.stringInSlice(command, []string{models.PlanCommand.String(), models.ApplyCommand.String(), models.UnlockCommand.String(), models.ApprovePoliciesCommand.String(), models.VersionCommand.String()}) {
return CommentParseResult{CommentResponse: fmt.Sprintf("```\nError: unknown command %q.\nRun 'atlantis --help' for usage.\n```", command)}
}

Expand Down Expand Up @@ -204,6 +206,13 @@ func (e *CommentParser) Parse(comment string, vcsHost models.VCSHostType) Commen
name = models.UnlockCommand
flagSet = pflag.NewFlagSet(models.UnlockCommand.String(), pflag.ContinueOnError)
flagSet.SetOutput(ioutil.Discard)
case models.VersionCommand.String():
name = models.VersionCommand
flagSet = pflag.NewFlagSet(models.VersionCommand.String(), pflag.ContinueOnError)
flagSet.StringVarP(&workspace, workspaceFlagLong, workspaceFlagShort, "", "Switch to this Terraform workspace before running version.")
flagSet.StringVarP(&dir, dirFlagLong, dirFlagShort, "", "Which directory to run version in relative to root of repo, ex. 'child/dir'.")
flagSet.StringVarP(&project, projectFlagLong, projectFlagShort, "", fmt.Sprintf("Print the version for this project. Refers to the name of the project configured in %s.", yaml.AtlantisYAMLFilename))
flagSet.BoolVarP(&verbose, verboseFlagLong, verboseFlagShort, false, "Append Atlantis log to comment.")
default:
return CommentParseResult{CommentResponse: fmt.Sprintf("Error: unknown command %q – this is a bug", command)}
}
Expand Down Expand Up @@ -285,6 +294,12 @@ func (e *CommentParser) BuildApplyComment(repoRelDir string, workspace string, p
return fmt.Sprintf("%s %s%s", atlantisExecutable, models.ApplyCommand.String(), flags)
}

// BuildVersionComment builds a version comment for the specified args.
func (e *CommentParser) BuildVersionComment(repoRelDir string, workspace string, project string) string {
flags := e.buildFlags(repoRelDir, workspace, project, false)
return fmt.Sprintf("%s %s%s", atlantisExecutable, models.VersionCommand.String(), flags)
}

func (e *CommentParser) buildFlags(repoRelDir string, workspace string, project string, autoMergeDisabled bool) string {
// Add quotes if dir has spaces.
if strings.Contains(repoRelDir, " ") {
Expand Down Expand Up @@ -389,6 +404,7 @@ Commands:
{{- end }}
unlock Removes all atlantis locks and discards all plans for this PR.
To unlock a specific plan you can use the Atlantis UI.
version Print the output of 'terraform version'
help View help.
Flags:
Expand Down
158 changes: 87 additions & 71 deletions server/events/comment_parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ func TestParse_Parsing(t *testing.T) {
}
}

func TestBuildPlanApplyComment(t *testing.T) {
func TestBuildPlanApplyVersionComment(t *testing.T) {
cases := []struct {
repoRelDir string
workspace string
Expand All @@ -585,77 +585,87 @@ func TestBuildPlanApplyComment(t *testing.T) {
commentArgs []string
expPlanFlags string
expApplyFlags string
expVersionFlags string
}{
{
repoRelDir: ".",
workspace: "default",
project: "",
commentArgs: nil,
expPlanFlags: "-d .",
expApplyFlags: "-d .",
},
{
repoRelDir: "dir",
workspace: "default",
project: "",
commentArgs: nil,
expPlanFlags: "-d dir",
expApplyFlags: "-d dir",
},
{
repoRelDir: ".",
workspace: "workspace",
project: "",
commentArgs: nil,
expPlanFlags: "-w workspace",
expApplyFlags: "-w workspace",
},
{
repoRelDir: "dir",
workspace: "workspace",
project: "",
commentArgs: nil,
expPlanFlags: "-d dir -w workspace",
expApplyFlags: "-d dir -w workspace",
},
{
repoRelDir: ".",
workspace: "default",
project: "project",
commentArgs: nil,
expPlanFlags: "-p project",
expApplyFlags: "-p project",
},
{
repoRelDir: "dir",
workspace: "workspace",
project: "project",
commentArgs: nil,
expPlanFlags: "-p project",
expApplyFlags: "-p project",
},
{
repoRelDir: ".",
workspace: "default",
project: "",
commentArgs: []string{`"arg1"`, `"arg2"`},
expPlanFlags: "-d . -- arg1 arg2",
expApplyFlags: "-d .",
},
{
repoRelDir: "dir",
workspace: "workspace",
project: "",
commentArgs: []string{`"arg1"`, `"arg2"`, `arg3`},
expPlanFlags: "-d dir -w workspace -- arg1 arg2 arg3",
expApplyFlags: "-d dir -w workspace",
},
{
repoRelDir: "dir with spaces",
workspace: "default",
project: "",
expPlanFlags: "-d \"dir with spaces\"",
expApplyFlags: "-d \"dir with spaces\"",
repoRelDir: ".",
workspace: "default",
project: "",
commentArgs: nil,
expPlanFlags: "-d .",
expApplyFlags: "-d .",
expVersionFlags: "-d .",
},
{
repoRelDir: "dir",
workspace: "default",
project: "",
commentArgs: nil,
expPlanFlags: "-d dir",
expApplyFlags: "-d dir",
expVersionFlags: "-d dir",
},
{
repoRelDir: ".",
workspace: "workspace",
project: "",
commentArgs: nil,
expPlanFlags: "-w workspace",
expApplyFlags: "-w workspace",
expVersionFlags: "-w workspace",
},
{
repoRelDir: "dir",
workspace: "workspace",
project: "",
commentArgs: nil,
expPlanFlags: "-d dir -w workspace",
expApplyFlags: "-d dir -w workspace",
expVersionFlags: "-d dir -w workspace",
},
{
repoRelDir: ".",
workspace: "default",
project: "project",
commentArgs: nil,
expPlanFlags: "-p project",
expApplyFlags: "-p project",
expVersionFlags: "-p project",
},
{
repoRelDir: "dir",
workspace: "workspace",
project: "project",
commentArgs: nil,
expPlanFlags: "-p project",
expApplyFlags: "-p project",
expVersionFlags: "-p project",
},
{
repoRelDir: ".",
workspace: "default",
project: "",
commentArgs: []string{`"arg1"`, `"arg2"`},
expPlanFlags: "-d . -- arg1 arg2",
expApplyFlags: "-d .",
expVersionFlags: "-d .",
},
{
repoRelDir: "dir",
workspace: "workspace",
project: "",
commentArgs: []string{`"arg1"`, `"arg2"`, `arg3`},
expPlanFlags: "-d dir -w workspace -- arg1 arg2 arg3",
expApplyFlags: "-d dir -w workspace",
expVersionFlags: "-d dir -w workspace",
},
{
repoRelDir: "dir with spaces",
workspace: "default",
project: "",
expPlanFlags: "-d \"dir with spaces\"",
expApplyFlags: "-d \"dir with spaces\"",
expVersionFlags: "-d \"dir with spaces\"",
},
{
repoRelDir: "dir",
Expand All @@ -665,19 +675,23 @@ func TestBuildPlanApplyComment(t *testing.T) {
commentArgs: []string{`"arg1"`, `"arg2"`, `arg3`},
expPlanFlags: "-d dir -w workspace -- arg1 arg2 arg3",
expApplyFlags: "-d dir -w workspace --auto-merge-disabled",
expVersionFlags: "-d dir -w workspace",
},
}

for _, c := range cases {
t.Run(c.expPlanFlags, func(t *testing.T) {
for _, cmd := range []models.CommandName{models.PlanCommand, models.ApplyCommand} {
for _, cmd := range []models.CommandName{models.PlanCommand, models.ApplyCommand, models.VersionCommand} {
switch cmd {
case models.PlanCommand:
actComment := commentParser.BuildPlanComment(c.repoRelDir, c.workspace, c.project, c.commentArgs)
Equals(t, fmt.Sprintf("atlantis plan %s", c.expPlanFlags), actComment)
case models.ApplyCommand:
actComment := commentParser.BuildApplyComment(c.repoRelDir, c.workspace, c.project, c.autoMergeDisabled)
Equals(t, fmt.Sprintf("atlantis apply %s", c.expApplyFlags), actComment)
case models.VersionCommand:
actComment := commentParser.BuildVersionComment(c.repoRelDir, c.workspace, c.project)
Equals(t, fmt.Sprintf("atlantis version %s", c.expVersionFlags), actComment)
}
}
})
Expand Down Expand Up @@ -715,6 +729,7 @@ Commands:
To only apply a specific plan, use the -d, -w and -p flags.
unlock Removes all atlantis locks and discards all plans for this PR.
To unlock a specific plan you can use the Atlantis UI.
version Print the output of 'terraform version'
help View help.
Flags:
Expand All @@ -741,6 +756,7 @@ Commands:
To plan a specific project, use the -d, -w and -p flags.
unlock Removes all atlantis locks and discards all plans for this PR.
To unlock a specific plan you can use the Atlantis UI.
version Print the output of 'terraform version'
help View help.
Flags:
Expand Down
Loading

0 comments on commit d358857

Please sign in to comment.