Skip to content

Commit

Permalink
merge?
Browse files Browse the repository at this point in the history
  • Loading branch information
smonero committed Apr 10, 2024
2 parents 6c60758 + 723f4d6 commit f595e57
Show file tree
Hide file tree
Showing 8 changed files with 350 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@ import (

"github.com/pkg/errors"
"github.com/runatlantis/atlantis/server/neptune/adhoc/adhocgithubhelpers"
"github.com/runatlantis/atlantis/server/neptune/gateway/config"
root_config "github.com/runatlantis/atlantis/server/neptune/gateway/config"
"github.com/runatlantis/atlantis/server/neptune/workflows/activities/github"
"github.com/runatlantis/atlantis/server/neptune/workflows/activities/terraform"
internal_gh "github.com/runatlantis/atlantis/server/vcs/provider/github"
)

type AdhocTerraformWorkflowExecutionParams struct {
Expand All @@ -16,15 +19,30 @@ type AdhocTerraformWorkflowExecutionParams struct {
// Note that deploymentID is used in NewWorkflowStore(), but we don't care about that in adhoc mode so can leave it blank
}

func ConstructAdhocExecParamsWithRootCfgBuilderAndRepoRetriever(ctx context.Context, repoName string, revision string, githubRetriever *adhocgithubhelpers.AdhocGithubRetriever) (AdhocTerraformWorkflowExecutionParams, error) {
func ConstructAdhocExecParamsWithRootCfgBuilderAndRepoRetriever(ctx context.Context, repoName string, revision string, githubRetriever *adhocgithubhelpers.AdhocGithubRetriever, rootCfgBuilder *root_config.Builder) (AdhocTerraformWorkflowExecutionParams, error) {
// TODO: in the future, could potentially pass in the owner instead of hardcoding lyft
repo, err := githubRetriever.GetRepository(ctx, "lyft", repoName)
if err != nil {
return AdhocTerraformWorkflowExecutionParams{}, errors.Wrap(err, "getting repo")
}

opts := config.BuilderOptions{
RepoFetcherOptions: &internal_gh.RepoFetcherOptions{
CloneDepth: 1,
SimplePath: true,
},
}

rootCfgs, err := rootCfgBuilder.Build(ctx, &root_config.RepoCommit{}, repo.Credentials.InstallationToken, opts)
if err != nil {
return AdhocTerraformWorkflowExecutionParams{}, errors.Wrap(err, "building root cfgs")
}

roots := getRootsFromMergedProjectCfgs(rootCfgs)

return AdhocTerraformWorkflowExecutionParams{
Revision: revision,
GithubRepo: repo,
Revision: revision,
GithubRepo: repo,
TerraformRoots: roots,
}, nil
}
99 changes: 99 additions & 0 deletions server/neptune/adhoc/adhocexecutionhelpers/root_helpers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package adhoc

import (
"github.com/runatlantis/atlantis/server/config/valid"
"github.com/runatlantis/atlantis/server/neptune/gateway/deploy"
"github.com/runatlantis/atlantis/server/neptune/workflows"
"github.com/runatlantis/atlantis/server/neptune/workflows/activities/execute"
"github.com/runatlantis/atlantis/server/neptune/workflows/activities/terraform"
)

func getRootsFromMergedProjectCfgs(rootCfgs []*valid.MergedProjectCfg) []terraform.Root {
roots := make([]terraform.Root, 0, len(rootCfgs))
for _, rootCfg := range rootCfgs {
root := convertMergedProjectCfgToRoot(rootCfg)
terraformRoot := convertToTerraformRoot(root)
roots = append(roots, terraformRoot)
}
return roots
}

func convertMergedProjectCfgToRoot(rootCfg *valid.MergedProjectCfg) workflows.Root {
var tfVersion string
if rootCfg.TerraformVersion != nil {
tfVersion = rootCfg.TerraformVersion.String()
}

return workflows.Root{
Name: rootCfg.Name,
Plan: workflows.Job{
Steps: prependPlanEnvSteps(rootCfg),
},
Apply: workflows.Job{
Steps: generateSteps(rootCfg.DeploymentWorkflow.Apply.Steps),
},
RepoRelPath: rootCfg.RepoRelDir,
TrackedFiles: rootCfg.WhenModified,
TfVersion: tfVersion,
// note we don't set TriggerInfo or PlanMode
}
}

func convertToTerraformRoot(root workflows.Root) terraform.Root {
return terraform.Root{
Name: root.Name,
Apply: execute.Job{
Steps: steps(root.Apply.Steps),
},
Plan: terraform.PlanJob{
Job: execute.Job{
Steps: steps(root.Plan.Steps)},
},
// Note we don't have mode, nor PlanApproval
Path: root.RepoRelPath,
TfVersion: root.TfVersion,
}
}

// These are copied here so that we don't have to use a workflowsignaler
func prependPlanEnvSteps(cfg *valid.MergedProjectCfg) []workflows.Step {
var steps []workflows.Step
if t, ok := cfg.Tags[deploy.Manifest]; ok {
//this is a Lyft specific env var
steps = append(steps, workflows.Step{
StepName: deploy.EnvStep,
EnvVarName: "MANIFEST_FILEPATH",
EnvVarValue: t,
})
}
steps = append(steps, generateSteps(cfg.DeploymentWorkflow.Plan.Steps)...)
return steps
}

func generateSteps(steps []valid.Step) []workflows.Step {
var workflowSteps []workflows.Step
for _, step := range steps {
workflowSteps = append(workflowSteps, workflows.Step{
StepName: step.StepName,
ExtraArgs: step.ExtraArgs,
RunCommand: step.RunCommand,
EnvVarName: step.EnvVarName,
EnvVarValue: step.EnvVarValue,
})
}
return workflowSteps
}

func steps(requestSteps []workflows.Step) []execute.Step {
var terraformSteps []execute.Step
for _, step := range requestSteps {
terraformSteps = append(terraformSteps, execute.Step{
StepName: step.StepName,
ExtraArgs: step.ExtraArgs,
RunCommand: step.RunCommand,
EnvVarName: step.EnvVarName,
EnvVarValue: step.EnvVarValue,
})
}
return terraformSteps
}
162 changes: 162 additions & 0 deletions server/neptune/adhoc/adhocexecutionhelpers/root_helpers_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
package adhoc

import (
"testing"

"github.com/runatlantis/atlantis/server/config/valid"
v "github.com/runatlantis/atlantis/server/config/valid"
"github.com/runatlantis/atlantis/server/neptune/workflows"
"github.com/runatlantis/atlantis/server/neptune/workflows/activities/execute"
"github.com/stretchr/testify/assert"
)

func TestPrependPlanEnvSteps(t *testing.T) {
tests := []struct {
cfg *valid.MergedProjectCfg
expectedSteps []workflows.Step
}{
{
cfg: &valid.MergedProjectCfg{
Tags: map[string]string{"manifest_path": "manifest_path"},
DeploymentWorkflow: v.Workflow{
Plan: v.Stage{
Steps: []v.Step{
{
StepName: "step1",
ExtraArgs: []string{"arg1", "arg2"},
RunCommand: "run",
EnvVarName: "env1",
EnvVarValue: "value1",
},
},
},
},
},
expectedSteps: []workflows.Step{
{
StepName: "env",
EnvVarName: "MANIFEST_FILEPATH",
EnvVarValue: "manifest_path",
},
{
StepName: "step1",
ExtraArgs: []string{"arg1", "arg2"},
RunCommand: "run",
EnvVarName: "env1",
EnvVarValue: "value1",
},
},
},
{
cfg: &valid.MergedProjectCfg{
Tags: map[string]string{"foo": "foo"},
DeploymentWorkflow: v.Workflow{
Plan: v.Stage{
Steps: []v.Step{
{
StepName: "step1",
ExtraArgs: []string{"arg1", "arg2"},
RunCommand: "run",
EnvVarName: "env1",
EnvVarValue: "value1",
},
},
},
},
},
expectedSteps: []workflows.Step{
{
StepName: "step1",
ExtraArgs: []string{"arg1", "arg2"},
RunCommand: "run",
EnvVarName: "env1",
EnvVarValue: "value1",
},
},
},
}

for _, tt := range tests {
res := prependPlanEnvSteps(tt.cfg)
assert.True(t, compareSteps(res, tt.expectedSteps))
}
}

func compareSteps(a []workflows.Step, b []workflows.Step) bool {
if len(a) != len(b) {
return false
}

for i, step := range a {
if step.StepName != b[i].StepName {
return false
}
if step.RunCommand != b[i].RunCommand {
return false
}
if step.EnvVarName != b[i].EnvVarName {
return false
}
if step.EnvVarValue != b[i].EnvVarValue {
return false
}
}

return true
}

func compareExecuteSteps(a []execute.Step, b []execute.Step) bool {
if len(a) != len(b) {
return false
}

for i, step := range a {
if step.StepName != b[i].StepName {
return false
}
if step.RunCommand != b[i].RunCommand {
return false
}
if step.EnvVarName != b[i].EnvVarName {
return false
}
if step.EnvVarValue != b[i].EnvVarValue {
return false
}
}

return true
}

func TestSteps(t *testing.T) {
tests := []struct {
requestSteps []workflows.Step
expectedSteps []execute.Step
}{
{
requestSteps: []workflows.Step{
{
StepName: "step1",
ExtraArgs: []string{"arg1", "arg2"},
RunCommand: "run",
EnvVarName: "env1",
EnvVarValue: "value1",
},
},
expectedSteps: []execute.Step{
{
StepName: "step1",
ExtraArgs: []string{"arg1", "arg2"},
RunCommand: "run",
EnvVarName: "env1",
EnvVarValue: "value1",
},
},
},
}

for _, tt := range tests {
res := steps(tt.requestSteps)
assert.True(t, compareExecuteSteps(res, tt.expectedSteps))
}
}
5 changes: 5 additions & 0 deletions server/neptune/workflows/activities/github.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ type FetchRootRequest struct {
Root terraform.Root
DeploymentID string
Revision string
WorkflowMode terraform.WorkflowMode
}

type FetchRootResponse struct {
Expand All @@ -265,6 +266,10 @@ func (a *githubActivities) GithubFetchRoot(ctx context.Context, request FetchRoo
defer cancel()

deployBasePath := filepath.Join(a.DataDir, deploymentsDirName, request.DeploymentID)
// if we are in Adhoc mode, we can use a simple file path without a UUID since there will only be one repository
if request.WorkflowMode == terraform.Adhoc {
deployBasePath = filepath.Join(a.DataDir)
}
repositoryPath := filepath.Join(deployBasePath, "repo")
opts := &github.RepositoryContentGetOptions{
Ref: request.Revision,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ func (r *RootFetcher) Fetch(ctx workflow.Context) (*terraform.LocalRoot, func(wo
Root: r.Request.Root,
DeploymentID: r.Request.DeploymentID,
Revision: r.Request.Revision,
WorkflowMode: r.Request.WorkflowMode,
}).Get(ctx, &fetchRootResponse)

if err != nil {
Expand Down
8 changes: 8 additions & 0 deletions server/neptune/workflows/internal/terraform/workflow_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ const (
testDeploymentID = "123"
testPath = "rel/path"
DeployDir = "deployments/123"
testWorkflowMode = terraformModel.Deploy
)

var testGithubRepo = github.Repo{
Expand Down Expand Up @@ -287,6 +288,7 @@ func TestSuccess_DeployMode(t *testing.T) {
Repo: testGithubRepo,
Root: testLocalRoot.Root,
DeploymentID: testDeploymentID,
WorkflowMode: testWorkflowMode,
}).Return(activities.FetchRootResponse{
LocalRoot: testLocalRoot,
DeployDirectory: DeployDir,
Expand Down Expand Up @@ -495,6 +497,7 @@ func TestSuccess_PRMode(t *testing.T) {
Repo: testGithubRepo,
Root: testLocalRoot.Root,
DeploymentID: testDeploymentID,
WorkflowMode: terraformModel.PR,
}).Return(activities.FetchRootResponse{
LocalRoot: testLocalRoot,
DeployDirectory: DeployDir,
Expand Down Expand Up @@ -643,6 +646,7 @@ func TestSuccess_AdminMode(t *testing.T) {
Repo: testGithubRepo,
Root: testLocalRoot.Root,
DeploymentID: testDeploymentID,
WorkflowMode: terraformModel.Adhoc,
}).Return(activities.FetchRootResponse{
LocalRoot: testLocalRoot,
DeployDirectory: DeployDir,
Expand Down Expand Up @@ -725,6 +729,7 @@ func TestSuccess_PRMode_FailedPolicy(t *testing.T) {
Repo: testGithubRepo,
Root: testLocalRoot.Root,
DeploymentID: testDeploymentID,
WorkflowMode: terraformModel.PR,
}).Return(activities.FetchRootResponse{
LocalRoot: testLocalRoot,
DeployDirectory: DeployDir,
Expand Down Expand Up @@ -867,6 +872,7 @@ func TestUpdateJobError(t *testing.T) {
Repo: testGithubRepo,
Root: testLocalRoot.Root,
DeploymentID: testDeploymentID,
WorkflowMode: testWorkflowMode,
}).Return(activities.FetchRootResponse{
DeployDirectory: DeployDir,
LocalRoot: testLocalRoot,
Expand Down Expand Up @@ -913,6 +919,7 @@ func TestPlanRejection(t *testing.T) {
Repo: testGithubRepo,
Root: testLocalRoot.Root,
DeploymentID: testDeploymentID,
WorkflowMode: testWorkflowMode,
}).Return(activities.FetchRootResponse{
DeployDirectory: DeployDir,
LocalRoot: testLocalRoot,
Expand Down Expand Up @@ -1081,6 +1088,7 @@ func TestFetchRootError(t *testing.T) {
Repo: testGithubRepo,
Root: testLocalRoot.Root,
DeploymentID: testDeploymentID,
WorkflowMode: testWorkflowMode,
}).Return(activities.FetchRootResponse{
DeployDirectory: DeployDir,
LocalRoot: testLocalRoot,
Expand Down
Loading

0 comments on commit f595e57

Please sign in to comment.