Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added dependsOn to module and project config, switched apply to apply… #180

Merged
merged 2 commits into from
Jun 24, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
12 changes: 5 additions & 7 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,12 @@ module github.com/commitdev/zero
go 1.13

require (
github.com/aws/aws-sdk-go v1.25.33
github.com/chzyer/logex v1.1.10 // indirect
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e // indirect
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1 // indirect
github.com/aws/aws-sdk-go v1.30.12
github.com/coreos/go-semver v0.2.0
github.com/google/go-cmp v0.3.0
github.com/google/go-cmp v0.3.1
github.com/google/uuid v1.1.1
github.com/hashicorp/go-getter v1.4.0
github.com/hashicorp/go-getter v1.4.2-0.20200106182914-9813cbd4eb02
github.com/hashicorp/terraform v0.12.26
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect
github.com/k0kubun/colorstring v0.0.0-20150214042306-9440f1994b88 // indirect
github.com/k0kubun/pp v3.0.1+incompatible
Expand All @@ -23,7 +21,7 @@ require (
github.com/mattn/go-colorable v0.1.2 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/spf13/cobra v0.0.6
github.com/stretchr/testify v1.4.0
github.com/stretchr/testify v1.5.1
github.com/termie/go-shutil v0.0.0-20140729215957-bcacb06fecae
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b // indirect
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 // indirect
Expand Down
229 changes: 220 additions & 9 deletions go.sum

Large diffs are not rendered by default.

18 changes: 15 additions & 3 deletions internal/apply/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

"github.com/commitdev/zero/internal/module"
"github.com/commitdev/zero/internal/util"
"github.com/hashicorp/terraform/dag"

"github.com/commitdev/zero/internal/config/globalconfig"
"github.com/commitdev/zero/internal/config/projectconfig"
Expand Down Expand Up @@ -50,8 +51,18 @@ Only a single environment may be suitable for an initial test, but for a real sy
func applyAll(dir string, projectConfig projectconfig.ZeroProjectConfig, applyEnvironments []string) {
environmentArg := fmt.Sprintf("ENVIRONMENT=%s", strings.Join(applyEnvironments, ","))

// Go through each of the modules and run `make`
for _, mod := range projectConfig.Modules {
graph := projectConfig.GetDAG()

// Walk the graph of modules and run `make`
root := []dag.Vertex{projectconfig.GraphRootName}
graph.DepthFirstWalk(root, func(v dag.Vertex, depth int) error {
// Don't process the root
if depth == 0 {
return nil
}

name := v.(string)
mod := projectConfig.Modules[name]
// Add env vars for the makefile
envList := []string{
environmentArg,
Expand All @@ -72,7 +83,8 @@ func applyAll(dir string, projectConfig projectconfig.ZeroProjectConfig, applyEn
envList = util.AppendProjectEnvToCmdEnv(mod.Parameters, envList)
envList = util.AppendProjectEnvToCmdEnv(credentials.AsEnvVars(), envList)
util.ExecuteCommand(exec.Command("make"), modulePath, envList)
}
return nil
})
}

// promptEnvironments Prompts the user for the environments to apply against and returns a slice of strings representing the environments
Expand Down
1 change: 1 addition & 0 deletions internal/config/moduleconfig/module_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type ModuleConfig struct {
Name string
Description string
Author string
DependsOn []string `yaml:"dependsOn,omitempty"`
TemplateConfig `yaml:"template"`
RequiredCredentials []string `yaml:"requiredCredentials"`
Parameters []Parameter
Expand Down
48 changes: 31 additions & 17 deletions internal/config/projectconfig/project_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,27 @@ import (
"io/ioutil"
"log"

"github.com/hashicorp/terraform/dag"
"github.com/k0kubun/pp"
yaml "gopkg.in/yaml.v2"
)

// GraphRootName represents the root of the graph of modules in a project
const GraphRootName = "graphRoot"

type ZeroProjectConfig struct {
Name string `yaml:"name"`
ShouldPushRepositories bool
Infrastructure Infrastructure // TODO simplify and flatten / rename?
Parameters map[string]string
Modules Modules `yaml:"modules"`
}

type Infrastructure struct {
AWS *AWS
}

type AWS struct {
AccountID string `yaml:"accountId"`
Region string
Terraform terraform // TODO simplify and flatten?
}

type terraform struct {
RemoteState bool
}

type Modules map[string]Module

type Module struct {
DependsOn []string `yaml:"dependsOn,omitempty"`
Parameters Parameters `yaml:"parameters,omitempty"`
Files Files `yaml:"files,omitempty"`
Files Files
}

type Parameters map[string]string
Expand Down Expand Up @@ -63,9 +53,33 @@ func (c *ZeroProjectConfig) Print() {
pp.Println(c)
}

func NewModule(parameters Parameters, directory string, repository string, source string) Module {
// GetDAG returns a graph of the module names used in this project config
func (c *ZeroProjectConfig) GetDAG() dag.AcyclicGraph {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using AcyclicGraph is slick 🕶️ 🕶️

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah it was nice to be able to handle dependencies in what is probably going to end up being the necessary way, but also be able to do it quite easily!

var g dag.AcyclicGraph

// Add vertices to graph
g.Add(GraphRootName)
for name := range c.Modules {
g.Add(name)
}

// Connect modules in graph
for name, m := range c.Modules {
if len(m.DependsOn) == 0 {
g.Connect(dag.BasicEdge(GraphRootName, name))
} else {
for _, dependencyName := range m.DependsOn {
g.Connect(dag.BasicEdge(dependencyName, name))
}
}
}
return g
}

func NewModule(parameters Parameters, directory string, repository string, source string, dependsOn []string) Module {
return Module{
Parameters: parameters,
DependsOn: dependsOn,
Files: Files{
Directory: directory,
Repository: repository,
Expand Down
43 changes: 40 additions & 3 deletions internal/config/projectconfig/project_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ import (
"io/ioutil"
"log"
"os"
"path/filepath"
"testing"

"github.com/commitdev/zero/internal/config/projectconfig"
"github.com/commitdev/zero/internal/constants"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/stretchr/testify/assert"
)

func TestLoadConfig(t *testing.T) {
Expand Down Expand Up @@ -37,9 +40,9 @@ func TestLoadConfig(t *testing.T) {
func eksGoReactSampleModules() projectconfig.Modules {
parameters := projectconfig.Parameters{"a": "b"}
return projectconfig.Modules{
"aws-eks-stack": projectconfig.NewModule(parameters, "zero-aws-eks-stack", "github.com/something/repo1", "github.com/commitdev/zero-aws-eks-stack"),
"deployable-backend": projectconfig.NewModule(parameters, "zero-deployable-backend", "github.com/something/repo2", "github.com/commitdev/zero-deployable-backend"),
"deployable-react-frontend": projectconfig.NewModule(parameters, "zero-deployable-react-frontend", "github.com/something/repo3", "github.com/commitdev/zero-deployable-react-frontend"),
"aws-eks-stack": projectconfig.NewModule(parameters, "zero-aws-eks-stack", "github.com/something/repo1", "github.com/commitdev/zero-aws-eks-stack", []string{}),
"deployable-backend": projectconfig.NewModule(parameters, "zero-deployable-backend", "github.com/something/repo2", "github.com/commitdev/zero-deployable-backend", []string{}),
"deployable-react-frontend": projectconfig.NewModule(parameters, "zero-deployable-react-frontend", "github.com/something/repo3", "github.com/commitdev/zero-deployable-react-frontend", []string{}),
}
}

Expand Down Expand Up @@ -74,3 +77,37 @@ modules:
source: github.com/commitdev/zero-deployable-react-frontend
`
}

func TestProjectConfigModuleGraph(t *testing.T) {
configPath := filepath.Join("../../../tests/test_data/projectconfig/", constants.ZeroProjectYml)

t.Run("Should generate a valid, correct graph based on the project config", func(t *testing.T) {
pc := projectconfig.LoadConfig(configPath)
graph := pc.GetDAG()

// Validate the graph
assert.NoError(t, graph.Validate())

// Check the structure of the graph
root, err := graph.Root()
assert.NoError(t, err)
assert.Equal(t, "graphRoot", root)

want := `graphRoot
project1
project1
project2
project3
project2
project4
project3
project4
project5
project4
project5
`
assert.Equal(t, want, graph.String())

})

}
2 changes: 1 addition & 1 deletion internal/generate/generate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ func TestGenerateModules(t *testing.T) {
projectConfig := projectconfig.ZeroProjectConfig{
Name: "foo",
Modules: projectconfig.Modules{
"mod1": projectconfig.NewModule(map[string]string{"test": "bar"}, tmpDir, "n/a", baseTestFixturesDir),
"mod1": projectconfig.NewModule(map[string]string{"test": "bar"}, tmpDir, "n/a", baseTestFixturesDir, []string{}),
},
}

Expand Down
8 changes: 2 additions & 6 deletions internal/init/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ func Init(outDir string) *projectconfig.ZeroProjectConfig {
}

}
projectConfig.Modules[moduleName] = projectconfig.NewModule(projectModuleParams, repoName, repoURL, mappedSources[moduleName])
projectConfig.Modules[moduleName] = projectconfig.NewModule(projectModuleParams, repoName, repoURL, mappedSources[moduleName], module.DependsOn)
}

// TODO: load ~/.zero/config.yml (or credentials)
Expand Down Expand Up @@ -308,11 +308,7 @@ func chooseStack(reg registry.Registry) []string {

func defaultProjConfig() projectconfig.ZeroProjectConfig {
return projectconfig.ZeroProjectConfig{
Name: "",
Infrastructure: projectconfig.Infrastructure{
AWS: nil,
},

Name: "",
Parameters: map[string]string{},
Modules: projectconfig.Modules{},
}
Expand Down
34 changes: 34 additions & 0 deletions tests/test_data/projectconfig/zero-project.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Graph shape:
# 2
# / \
# 1 4
# \ /
# 3 - 5

name: graph_test

modules:
project1:
parameters:
foo: bar
project2:
dependsOn:
- project1
parameters:
baz: qux
project3:
dependsOn:
- project1
parameters:
baz: qux
project4:
dependsOn:
- project2
- project3
parameters:
baz: qux
project5:
dependsOn:
- project3
parameters:
baz: qux