From 1110bda4f467165444ab07ecda7c445ba68fc50d Mon Sep 17 00:00:00 2001 From: Dolapo Toki Date: Wed, 17 Jun 2020 14:03:12 -0700 Subject: [PATCH 1/8] wip: marshal zero-project.yaml file --- internal/config/projectconfig/init.go | 65 ++++++++++++------- .../config/projectconfig/project_config.go | 4 +- .../projectconfig/project_config_test.go | 59 +++++++++++++++++ internal/util/util.go | 6 ++ 4 files changed, 107 insertions(+), 27 deletions(-) diff --git a/internal/config/projectconfig/init.go b/internal/config/projectconfig/init.go index 783c897c7..5970e4166 100644 --- a/internal/config/projectconfig/init.go +++ b/internal/config/projectconfig/init.go @@ -1,43 +1,28 @@ package projectconfig import ( + "bytes" "fmt" "io/ioutil" + "os" "path" + "text/template" "github.com/commitdev/zero/internal/constants" + "github.com/commitdev/zero/internal/util" "github.com/commitdev/zero/pkg/util/exit" "gopkg.in/yaml.v2" ) -const exampleConfig = `name: %s +// {{ .ShouldPushRepositories | printf "%q"}} +const exampleConfig = ` +# Templated zero-project.yml file +name: {{.Name}} -# Context is normally populated automatically but could be used to inject global params -context: +shouldPushRepositories: {{.ShouldPushRepositories | printf "%v"}} -# module can be in any format the go-getter supports (path, github, url, etc.) -# supports https://github.com/hashicorp/go-getter#url-format -# Example: -# - repo: "../development/modules/ci" -# - dir: "github-actions" modules: - aws-eks-stack: - parameters: - repoName: infrastructure - region: us-east-1 - accountId: 12345 - productionHost: something.com - files: - dir: infrastructure - repo: https://github.com/myorg/infrastructure - some-other-module: - parameters: - repoName: api - files: - dir: api - repo: https://github.com/myorg/api - - +{{.Modules}} ` var RootDir = "./" @@ -59,3 +44,33 @@ func Init(dir string, projectName string, projectContext *ZeroProjectConfig) { exit.Fatal(fmt.Sprintf("Failed to create config file %s", constants.ZeroProjectYml)) } } + +func GetProjectFileContent(projectConfig ZeroProjectConfig) string { + var tpl bytes.Buffer + tmpl := template.New("sa") + tmpl, err := tmpl.Parse(exampleConfig) + if err != nil { + exit.Fatal(fmt.Sprintf("Failed to parse the sample Zero module config file %s", constants.ZeroProjectYml)) + } + + type tempProjectConfig struct { + Name string + ShouldPushRepositories bool + Modules string + } + + foo, err := yaml.Marshal(projectConfig.Modules) + if err != nil { + fmt.Println(err) + } + + t := tempProjectConfig{ + Name: projectConfig.Name, + ShouldPushRepositories: projectConfig.ShouldPushRepositories, + Modules: util.IndentString(string(foo), 2), + } + + tmpl.Execute(os.Stdout, t) + result := tpl.String() + return result +} diff --git a/internal/config/projectconfig/project_config.go b/internal/config/projectconfig/project_config.go index b416a5da5..4ba9ef7b5 100644 --- a/internal/config/projectconfig/project_config.go +++ b/internal/config/projectconfig/project_config.go @@ -33,8 +33,8 @@ type terraform struct { type Modules map[string]Module type Module struct { - Parameters Parameters `yaml:"parameters,omitempty"` - Files Files + Parameters Parameters `yaml:"parameters,omitempty"` // map which parameter belongs to each module back from context/init.go + Files Files `yaml:"files,omitempty"` } type Parameters map[string]string diff --git a/internal/config/projectconfig/project_config_test.go b/internal/config/projectconfig/project_config_test.go index 3c94d0242..429c0dccc 100644 --- a/internal/config/projectconfig/project_config_test.go +++ b/internal/config/projectconfig/project_config_test.go @@ -1,14 +1,18 @@ package projectconfig_test import ( + "fmt" "io/ioutil" "log" "os" + "strings" "testing" "github.com/commitdev/zero/internal/config/projectconfig" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" + "github.com/stretchr/testify/assert" + "gopkg.in/yaml.v2" ) func TestLoadConfig(t *testing.T) { @@ -43,10 +47,65 @@ func eksGoReactSampleModules() projectconfig.Modules { } } +// TODO: Combinde TestMoudle and TestGetProjectFIleContent sample:global_config_test.go ln:42 +// TODO: remove test when you complete TestGetProjectFIleContent +func TestProject(t *testing.T) { + + module := projectconfig.NewModule(projectconfig.Parameters{ + "repoName": "infrastructure", + "region": "us-east-1", + }, "/infrastructure", "https://github.com/myorg/infrastructure") + + modules := projectconfig.Modules{ + "awk-eks-stack": module, + } + + modulesContent, _ := yaml.Marshal(&modules) + expectedContents := `awk-eks-stack: + parameters: + region: us-east-1 + repoName: infrastructure + accountId: 12345 + files: + dir: /infrastructure + repo: https://github.com/myorg/infrastructure +` + assert.Equal(t, strings.Trim(expectedContents, " "), strings.Trim(string(modulesContent), " ")) +} + +func TestGetProjectFileContent(t *testing.T) { + + module := projectconfig.NewModule(projectconfig.Parameters{ + "repoName": "infrastructure", + "region": "us-east-1", + }, "/infrastructure", "https://github.com/myorg/infrastructure") + + modules := projectconfig.Modules{ + "awk-eks-stack": module, + } + + config := projectconfig.ZeroProjectConfig{ + Name: "abc", + ShouldPushRepositories: true, + Infrastructure: projectconfig.Infrastructure{ + AWS: nil, + }, + + Parameters: map[string]string{}, + Modules: modules, + } + content := projectconfig.GetProjectFileContent(config) + + // TODO: assert file output to make sure this works. + fmt.Println(content) +} + func validConfigContent() string { return ` name: abc +shouldPushRepositories: true + modules: aws-eks-stack: parameters: diff --git a/internal/util/util.go b/internal/util/util.go index cb754bdff..270d23a19 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -113,3 +113,9 @@ func AppendProjectEnvToCmdEnv(envMap map[string]string, envList []string) []stri } return envList } + +// TODO: indent each line for the modules. +func IndentString(content string, spaces int) string { + // TODO: implement me + return "Testing indent string retrun" +} From eb70856055ca3d76dec326d7c49b9cd4a927015c Mon Sep 17 00:00:00 2001 From: Dolapo Toki Date: Wed, 17 Jun 2020 16:07:43 -0700 Subject: [PATCH 2/8] properly indent module configs init.go clean-up --- internal/config/projectconfig/init.go | 35 ++++++++++++--------------- internal/util/util.go | 14 ++++++++--- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/internal/config/projectconfig/init.go b/internal/config/projectconfig/init.go index 5970e4166..8ad70f57c 100644 --- a/internal/config/projectconfig/init.go +++ b/internal/config/projectconfig/init.go @@ -4,7 +4,6 @@ import ( "bytes" "fmt" "io/ioutil" - "os" "path" "text/template" @@ -14,8 +13,7 @@ import ( "gopkg.in/yaml.v2" ) -// {{ .ShouldPushRepositories | printf "%q"}} -const exampleConfig = ` +const zeroProjectConfigTemplate = ` # Templated zero-project.yml file name: {{.Name}} @@ -46,31 +44,30 @@ func Init(dir string, projectName string, projectContext *ZeroProjectConfig) { } func GetProjectFileContent(projectConfig ZeroProjectConfig) string { - var tpl bytes.Buffer - tmpl := template.New("sa") - tmpl, err := tmpl.Parse(exampleConfig) + var tplBuffer bytes.Buffer + tmpl, err := template.New("projectConfig").Parse(zeroProjectConfigTemplate) if err != nil { - exit.Fatal(fmt.Sprintf("Failed to parse the sample Zero module config file %s", constants.ZeroProjectYml)) + exit.Fatal(fmt.Sprintf("Failed to parse the config template %s", constants.ZeroProjectYml)) } - type tempProjectConfig struct { - Name string - ShouldPushRepositories bool - Modules string - } - - foo, err := yaml.Marshal(projectConfig.Modules) + pConfig, err := yaml.Marshal(projectConfig.Modules) if err != nil { - fmt.Println(err) + exit.Fatal(fmt.Sprintf("Failed while serializing the modules %s", constants.ZeroProjectYml)) } - t := tempProjectConfig{ + t := struct { + Name string + ShouldPushRepositories bool + Modules string + }{ Name: projectConfig.Name, ShouldPushRepositories: projectConfig.ShouldPushRepositories, - Modules: util.IndentString(string(foo), 2), + Modules: util.IndentString(string(pConfig), 2), } - tmpl.Execute(os.Stdout, t) - result := tpl.String() + if err := tmpl.Execute(&tplBuffer, t); err != nil { + exit.Fatal(fmt.Sprintf("Failed while executing the template %s", constants.ZeroProjectYml)) + } + result := tplBuffer.String() return result } diff --git a/internal/util/util.go b/internal/util/util.go index 270d23a19..e8eb05bc1 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -3,12 +3,14 @@ package util // @TODO split up and move into /pkg directory import ( + "bytes" "fmt" "io" "log" "os" "os/exec" "path" + "strconv" "strings" "text/template" @@ -114,8 +116,12 @@ func AppendProjectEnvToCmdEnv(envMap map[string]string, envList []string) []stri return envList } -// TODO: indent each line for the modules. -func IndentString(content string, spaces int) string { - // TODO: implement me - return "Testing indent string retrun" +// IndentString will Add x space char padding at the beginging of each line. +func IndentString(content string, space int) string { + var result bytes.Buffer + subStr := strings.Split(content, "\n") + for _, s := range subStr { + result.WriteString(fmt.Sprintf("%"+strconv.Itoa(space)+"s%s \n", "", s)) + } + return result.String() } From 1d8e55114f8b4d7ab5522b526627dca0758b7b70 Mon Sep 17 00:00:00 2001 From: Dolapo Toki Date: Wed, 17 Jun 2020 21:55:23 -0700 Subject: [PATCH 3/8] use string instead of byte buffer --- internal/util/util.go | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/internal/util/util.go b/internal/util/util.go index e8eb05bc1..1a89867ce 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -3,7 +3,6 @@ package util // @TODO split up and move into /pkg directory import ( - "bytes" "fmt" "io" "log" @@ -118,10 +117,10 @@ func AppendProjectEnvToCmdEnv(envMap map[string]string, envList []string) []stri // IndentString will Add x space char padding at the beginging of each line. func IndentString(content string, space int) string { - var result bytes.Buffer + var result string subStr := strings.Split(content, "\n") for _, s := range subStr { - result.WriteString(fmt.Sprintf("%"+strconv.Itoa(space)+"s%s \n", "", s)) + result += fmt.Sprintf("%"+strconv.Itoa(space)+"s%s \n", "", s) } - return result.String() + return result } From f91fa2ca1c5709c5e1f912ac650f318309f50ee9 Mon Sep 17 00:00:00 2001 From: Dolapo Toki Date: Fri, 19 Jun 2020 15:16:46 -0700 Subject: [PATCH 4/8] clean up tests and error handling --- internal/config/projectconfig/init.go | 27 ++++---- .../projectconfig/project_config_test.go | 67 ++++++------------- 2 files changed, 33 insertions(+), 61 deletions(-) diff --git a/internal/config/projectconfig/init.go b/internal/config/projectconfig/init.go index 8ad70f57c..75584fb56 100644 --- a/internal/config/projectconfig/init.go +++ b/internal/config/projectconfig/init.go @@ -30,29 +30,31 @@ func SetRootDir(dir string) { } func Init(dir string, projectName string, projectContext *ZeroProjectConfig) { - // TODO: template the zero-project.yml with projectContext - // content := []byte(fmt.Sprintf(exampleConfig, projectName)) - content, err := yaml.Marshal(projectContext) + content, err := GetProjectFileContent(*projectContext) if err != nil { - exit.Fatal(fmt.Sprintf("Failed to serialize configuration file %s", constants.ZeroProjectYml)) + exit.Fatal(fmt.Sprintf("Failed extracting the file config content %s", constants.ZeroProjectYml)) } - writeErr := ioutil.WriteFile(path.Join(dir, projectName, constants.ZeroProjectYml), content, 0644) + writeErr := ioutil.WriteFile(path.Join(dir, projectName, constants.ZeroProjectYml), []byte(content), 0644) if writeErr != nil { exit.Fatal(fmt.Sprintf("Failed to create config file %s", constants.ZeroProjectYml)) } } -func GetProjectFileContent(projectConfig ZeroProjectConfig) string { +func GetProjectFileContent(projectConfig ZeroProjectConfig) (string, error) { var tplBuffer bytes.Buffer tmpl, err := template.New("projectConfig").Parse(zeroProjectConfigTemplate) if err != nil { - exit.Fatal(fmt.Sprintf("Failed to parse the config template %s", constants.ZeroProjectYml)) + return "", err } - pConfig, err := yaml.Marshal(projectConfig.Modules) + if len(projectConfig.Modules) == 0 { + return "", fmt.Errorf("Invalid project config, expected config modules to be non-empty") + } + + pConfigModule, err := yaml.Marshal(projectConfig.Modules) if err != nil { - exit.Fatal(fmt.Sprintf("Failed while serializing the modules %s", constants.ZeroProjectYml)) + return "", err } t := struct { @@ -62,12 +64,11 @@ func GetProjectFileContent(projectConfig ZeroProjectConfig) string { }{ Name: projectConfig.Name, ShouldPushRepositories: projectConfig.ShouldPushRepositories, - Modules: util.IndentString(string(pConfig), 2), + Modules: util.IndentString(string(pConfigModule), 2), } if err := tmpl.Execute(&tplBuffer, t); err != nil { - exit.Fatal(fmt.Sprintf("Failed while executing the template %s", constants.ZeroProjectYml)) + return "", err } - result := tplBuffer.String() - return result + return tplBuffer.String(), nil } diff --git a/internal/config/projectconfig/project_config_test.go b/internal/config/projectconfig/project_config_test.go index 429c0dccc..f2dd2b916 100644 --- a/internal/config/projectconfig/project_config_test.go +++ b/internal/config/projectconfig/project_config_test.go @@ -1,18 +1,15 @@ package projectconfig_test import ( - "fmt" "io/ioutil" "log" "os" - "strings" "testing" "github.com/commitdev/zero/internal/config/projectconfig" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/stretchr/testify/assert" - "gopkg.in/yaml.v2" ) func TestLoadConfig(t *testing.T) { @@ -47,59 +44,33 @@ func eksGoReactSampleModules() projectconfig.Modules { } } -// TODO: Combinde TestMoudle and TestGetProjectFIleContent sample:global_config_test.go ln:42 -// TODO: remove test when you complete TestGetProjectFIleContent -func TestProject(t *testing.T) { - - module := projectconfig.NewModule(projectconfig.Parameters{ - "repoName": "infrastructure", - "region": "us-east-1", - }, "/infrastructure", "https://github.com/myorg/infrastructure") - - modules := projectconfig.Modules{ - "awk-eks-stack": module, - } - - modulesContent, _ := yaml.Marshal(&modules) - expectedContents := `awk-eks-stack: - parameters: - region: us-east-1 - repoName: infrastructure - accountId: 12345 - files: - dir: /infrastructure - repo: https://github.com/myorg/infrastructure -` - assert.Equal(t, strings.Trim(expectedContents, " "), strings.Trim(string(modulesContent), " ")) -} - func TestGetProjectFileContent(t *testing.T) { + projectConfig := projectconfig.ZeroProjectConfig{ + Name: "abc", + ShouldPushRepositories: false, + } - module := projectconfig.NewModule(projectconfig.Parameters{ - "repoName": "infrastructure", - "region": "us-east-1", - }, "/infrastructure", "https://github.com/myorg/infrastructure") + t.Run("Should fail if modules are missing from project config", func(t *testing.T) { + // Remove the modules + projectConfig.Modules = nil - modules := projectconfig.Modules{ - "awk-eks-stack": module, - } + result, err := projectconfig.GetProjectFileContent(projectConfig) - config := projectconfig.ZeroProjectConfig{ - Name: "abc", - ShouldPushRepositories: true, - Infrastructure: projectconfig.Infrastructure{ - AWS: nil, - }, + assert.Error(t, err) + assert.Equal(t, result, "") + }) - Parameters: map[string]string{}, - Modules: modules, - } - content := projectconfig.GetProjectFileContent(config) + t.Run("Should return a valid project config", func(t *testing.T) { + projectConfig.Modules = eksGoReactSampleModules() + result, err := projectconfig.GetProjectFileContent(projectConfig) - // TODO: assert file output to make sure this works. - fmt.Println(content) + assert.NoError(t, err) + assert.NotEmpty(t, result) + }) } +// TODO: Write test init function to check file written to disk, use test_data/ + func validConfigContent() string { return ` name: abc From a153e2625a1033cdc43b782fcf86fa96c8e9bb96 Mon Sep 17 00:00:00 2001 From: Dolapo Toki Date: Fri, 19 Jun 2020 18:07:16 -0700 Subject: [PATCH 5/8] refactor --- internal/config/projectconfig/init.go | 4 +- .../config/projectconfig/project_config.go | 2 +- .../projectconfig/project_config_test.go | 47 ++++++++++--------- internal/util/util.go | 2 +- 4 files changed, 29 insertions(+), 26 deletions(-) diff --git a/internal/config/projectconfig/init.go b/internal/config/projectconfig/init.go index 75584fb56..97a604685 100644 --- a/internal/config/projectconfig/init.go +++ b/internal/config/projectconfig/init.go @@ -52,7 +52,7 @@ func GetProjectFileContent(projectConfig ZeroProjectConfig) (string, error) { return "", fmt.Errorf("Invalid project config, expected config modules to be non-empty") } - pConfigModule, err := yaml.Marshal(projectConfig.Modules) + pConfigModules, err := yaml.Marshal(projectConfig.Modules) if err != nil { return "", err } @@ -64,7 +64,7 @@ func GetProjectFileContent(projectConfig ZeroProjectConfig) (string, error) { }{ Name: projectConfig.Name, ShouldPushRepositories: projectConfig.ShouldPushRepositories, - Modules: util.IndentString(string(pConfigModule), 2), + Modules: util.IndentString(string(pConfigModules), 2), } if err := tmpl.Execute(&tplBuffer, t); err != nil { diff --git a/internal/config/projectconfig/project_config.go b/internal/config/projectconfig/project_config.go index 4ba9ef7b5..7bc716b67 100644 --- a/internal/config/projectconfig/project_config.go +++ b/internal/config/projectconfig/project_config.go @@ -33,7 +33,7 @@ type terraform struct { type Modules map[string]Module type Module struct { - Parameters Parameters `yaml:"parameters,omitempty"` // map which parameter belongs to each module back from context/init.go + Parameters Parameters `yaml:"parameters,omitempty"` Files Files `yaml:"files,omitempty"` } diff --git a/internal/config/projectconfig/project_config_test.go b/internal/config/projectconfig/project_config_test.go index f2dd2b916..551085d0a 100644 --- a/internal/config/projectconfig/project_config_test.go +++ b/internal/config/projectconfig/project_config_test.go @@ -66,6 +66,8 @@ func TestGetProjectFileContent(t *testing.T) { assert.NoError(t, err) assert.NotEmpty(t, result) + // TODO: need to remove trailing new-line in util function for this to work + // assert.Equal(t, validConfigContent(), result) }) } @@ -73,31 +75,32 @@ func TestGetProjectFileContent(t *testing.T) { func validConfigContent() string { return ` +# Templated zero-project.yml file name: abc -shouldPushRepositories: true +shouldPushRepositories: false modules: - aws-eks-stack: - parameters: - a: b - files: - dir: zero-aws-eks-stack - repo: github.com/something/repo1 - source: github.com/commitdev/zero-aws-eks-stack - deployable-backend: - parameters: - a: b - files: - dir: zero-deployable-backend - repo: github.com/something/repo2 - source: github.com/commitdev/zero-deployable-backend - deployable-react-frontend: - parameters: - a: b - files: - dir: zero-deployable-react-frontend - repo: github.com/something/repo3 - source: github.com/commitdev/zero-deployable-react-frontend + aws-eks-stack: + parameters: + a: b + files: + dir: zero-aws-eks-stack + repo: github.com/something/repo1 + source: github.com/commitdev/zero-aws-eks-stack + deployable-backend: + parameters: + a: b + files: + dir: zero-deployable-backend + repo: github.com/something/repo2 + source: github.com/commitdev/zero-deployable-backend + deployable-react-frontend: + parameters: + a: b + files: + dir: zero-deployable-react-frontend + repo: github.com/something/repo3 + source: github.com/commitdev/zero-deployable-react-frontend ` } diff --git a/internal/util/util.go b/internal/util/util.go index 1a89867ce..70ebe2868 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -120,7 +120,7 @@ func IndentString(content string, space int) string { var result string subStr := strings.Split(content, "\n") for _, s := range subStr { - result += fmt.Sprintf("%"+strconv.Itoa(space)+"s%s \n", "", s) + result += fmt.Sprintf("%"+strconv.Itoa(space)+"s%s\n", "", s) } return result } From d362573b7fc20416909e557759e46dc3f9ddfba7 Mon Sep 17 00:00:00 2001 From: Dolapo Toki Date: Fri, 19 Jun 2020 18:43:02 -0700 Subject: [PATCH 6/8] unmarshal for testing --- .../projectconfig/project_config_test.go | 37 ++++++++++++------- 1 file changed, 23 insertions(+), 14 deletions(-) diff --git a/internal/config/projectconfig/project_config_test.go b/internal/config/projectconfig/project_config_test.go index 551085d0a..86a083b1d 100644 --- a/internal/config/projectconfig/project_config_test.go +++ b/internal/config/projectconfig/project_config_test.go @@ -10,6 +10,7 @@ import ( "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" "github.com/stretchr/testify/assert" + "gopkg.in/yaml.v2" ) func TestLoadConfig(t *testing.T) { @@ -45,34 +46,42 @@ func eksGoReactSampleModules() projectconfig.Modules { } func TestGetProjectFileContent(t *testing.T) { - projectConfig := projectconfig.ZeroProjectConfig{ + defaultConfig := projectconfig.ZeroProjectConfig{ Name: "abc", ShouldPushRepositories: false, + // Modules not set defaults to nil } t.Run("Should fail if modules are missing from project config", func(t *testing.T) { - // Remove the modules - projectConfig.Modules = nil + result, getProjectContentErr := projectconfig.GetProjectFileContent(defaultConfig) - result, err := projectconfig.GetProjectFileContent(projectConfig) - - assert.Error(t, err) + // Expect error to throw error for missing modules + assert.Error(t, getProjectContentErr) assert.Equal(t, result, "") }) t.Run("Should return a valid project config", func(t *testing.T) { - projectConfig.Modules = eksGoReactSampleModules() - result, err := projectconfig.GetProjectFileContent(projectConfig) + resultConfig := &projectconfig.ZeroProjectConfig{} + expectedConfig := &projectconfig.ZeroProjectConfig{ + Name: "abc", + ShouldPushRepositories: false, + Modules: eksGoReactSampleModules(), + } + + defaultConfig.Modules = eksGoReactSampleModules() // re-insert project config modules + projectContentString, getProjectContentErr := projectconfig.GetProjectFileContent(defaultConfig) + + assert.NoError(t, getProjectContentErr) - assert.NoError(t, err) - assert.NotEmpty(t, result) - // TODO: need to remove trailing new-line in util function for this to work - // assert.Equal(t, validConfigContent(), result) + unmarshalErr := yaml.Unmarshal([]byte(projectContentString), &resultConfig) + assert.NoError(t, unmarshalErr) + + if !cmp.Equal(expectedConfig, resultConfig, cmpopts.EquateEmpty()) { + t.Errorf("projectconfig.ZeroProjectConfig.Unmarshal mismatch (-expected +result):\n%s", cmp.Diff(expectedConfig, resultConfig)) + } }) } -// TODO: Write test init function to check file written to disk, use test_data/ - func validConfigContent() string { return ` # Templated zero-project.yml file From 90610865eae533d6bd27879f0fc3a1865625f394 Mon Sep 17 00:00:00 2001 From: Dolapo Toki Date: Mon, 22 Jun 2020 18:43:28 -0700 Subject: [PATCH 7/8] * refactor project_config/init.go * change test location --- cmd/init.go | 2 +- internal/config/projectconfig/init.go | 6 +-- internal/config/projectconfig/init_test.go | 29 ++++++++++++-- .../projectconfig/project_config_test.go | 39 ------------------- internal/util/util.go | 6 +-- 5 files changed, 33 insertions(+), 49 deletions(-) diff --git a/cmd/init.go b/cmd/init.go index 9773cfa7f..bf6d07406 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -15,6 +15,6 @@ var initCmd = &cobra.Command{ Short: "Create new project with provided name and initialize configuration based on user input.", Run: func(cmd *cobra.Command, args []string) { projectContext := initPrompts.Init(projectconfig.RootDir) - projectconfig.Init(projectconfig.RootDir, projectContext.Name, projectContext) + projectconfig.CreateProjectConfigFile(projectconfig.RootDir, projectContext.Name, projectContext) }, } diff --git a/internal/config/projectconfig/init.go b/internal/config/projectconfig/init.go index 97a604685..73b4a9547 100644 --- a/internal/config/projectconfig/init.go +++ b/internal/config/projectconfig/init.go @@ -29,8 +29,8 @@ func SetRootDir(dir string) { RootDir = dir } -func Init(dir string, projectName string, projectContext *ZeroProjectConfig) { - content, err := GetProjectFileContent(*projectContext) +func CreateProjectConfigFile(dir string, projectName string, projectContext *ZeroProjectConfig) { + content, err := getProjectFileContent(*projectContext) if err != nil { exit.Fatal(fmt.Sprintf("Failed extracting the file config content %s", constants.ZeroProjectYml)) } @@ -41,7 +41,7 @@ func Init(dir string, projectName string, projectContext *ZeroProjectConfig) { } } -func GetProjectFileContent(projectConfig ZeroProjectConfig) (string, error) { +func getProjectFileContent(projectConfig ZeroProjectConfig) (string, error) { var tplBuffer bytes.Buffer tmpl, err := template.New("projectConfig").Parse(zeroProjectConfigTemplate) if err != nil { diff --git a/internal/config/projectconfig/init_test.go b/internal/config/projectconfig/init_test.go index a34c8d464..5403f14c2 100644 --- a/internal/config/projectconfig/init_test.go +++ b/internal/config/projectconfig/init_test.go @@ -7,9 +7,11 @@ import ( "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" ) -func TestInit(t *testing.T) { +func TestCreateProjectConfigFile(t *testing.T) { const testDir = "../../test-sandbox" projectName := "test-project" @@ -17,16 +19,37 @@ func TestInit(t *testing.T) { defer os.RemoveAll(testDir) testDirPath := path.Join(projectconfig.RootDir, projectName) + // create sandbox dir err := os.MkdirAll(testDirPath, os.ModePerm) if err != nil { t.Fatal(err) } - config := projectconfig.ZeroProjectConfig{} - projectconfig.Init(projectconfig.RootDir, projectName, &config) + expectedConfig := &projectconfig.ZeroProjectConfig{ + Name: projectName, + ShouldPushRepositories: false, + Modules: eksGoReactSampleModules(), + } + projectconfig.CreateProjectConfigFile(projectconfig.RootDir, projectName, expectedConfig) + // make sure the file exists if _, err := os.Stat(path.Join(testDirPath, constants.ZeroProjectYml)); err != nil { t.Fatal(err) } + + t.Run("Should return a valid project config", func(t *testing.T) { + + resultConfig := projectconfig.LoadConfig(path.Join(testDirPath, constants.ZeroProjectYml)) + + if !cmp.Equal(expectedConfig, resultConfig, cmpopts.EquateEmpty()) { + t.Errorf("projectconfig.ZeroProjectConfig.Unmarshal mismatch (-expected +result):\n%s", cmp.Diff(expectedConfig, resultConfig)) + } + }) + + /* TODO: Test err is thrown when there is a failure? + t.Run("Should fail if modules are missing from project config", func(t *testing.T) { + + }) + */ } diff --git a/internal/config/projectconfig/project_config_test.go b/internal/config/projectconfig/project_config_test.go index 86a083b1d..22e76908c 100644 --- a/internal/config/projectconfig/project_config_test.go +++ b/internal/config/projectconfig/project_config_test.go @@ -9,8 +9,6 @@ import ( "github.com/commitdev/zero/internal/config/projectconfig" "github.com/google/go-cmp/cmp" "github.com/google/go-cmp/cmp/cmpopts" - "github.com/stretchr/testify/assert" - "gopkg.in/yaml.v2" ) func TestLoadConfig(t *testing.T) { @@ -45,43 +43,6 @@ func eksGoReactSampleModules() projectconfig.Modules { } } -func TestGetProjectFileContent(t *testing.T) { - defaultConfig := projectconfig.ZeroProjectConfig{ - Name: "abc", - ShouldPushRepositories: false, - // Modules not set defaults to nil - } - - t.Run("Should fail if modules are missing from project config", func(t *testing.T) { - result, getProjectContentErr := projectconfig.GetProjectFileContent(defaultConfig) - - // Expect error to throw error for missing modules - assert.Error(t, getProjectContentErr) - assert.Equal(t, result, "") - }) - - t.Run("Should return a valid project config", func(t *testing.T) { - resultConfig := &projectconfig.ZeroProjectConfig{} - expectedConfig := &projectconfig.ZeroProjectConfig{ - Name: "abc", - ShouldPushRepositories: false, - Modules: eksGoReactSampleModules(), - } - - defaultConfig.Modules = eksGoReactSampleModules() // re-insert project config modules - projectContentString, getProjectContentErr := projectconfig.GetProjectFileContent(defaultConfig) - - assert.NoError(t, getProjectContentErr) - - unmarshalErr := yaml.Unmarshal([]byte(projectContentString), &resultConfig) - assert.NoError(t, unmarshalErr) - - if !cmp.Equal(expectedConfig, resultConfig, cmpopts.EquateEmpty()) { - t.Errorf("projectconfig.ZeroProjectConfig.Unmarshal mismatch (-expected +result):\n%s", cmp.Diff(expectedConfig, resultConfig)) - } - }) -} - func validConfigContent() string { return ` # Templated zero-project.yml file diff --git a/internal/util/util.go b/internal/util/util.go index 70ebe2868..bc24f5edc 100644 --- a/internal/util/util.go +++ b/internal/util/util.go @@ -115,12 +115,12 @@ func AppendProjectEnvToCmdEnv(envMap map[string]string, envList []string) []stri return envList } -// IndentString will Add x space char padding at the beginging of each line. -func IndentString(content string, space int) string { +// IndentString will Add x space char padding at the beginging of each line. +func IndentString(content string, spaces int) string { var result string subStr := strings.Split(content, "\n") for _, s := range subStr { - result += fmt.Sprintf("%"+strconv.Itoa(space)+"s%s\n", "", s) + result += fmt.Sprintf("%"+strconv.Itoa(spaces)+"s%s\n", "", s) } return result } From 22fa36a6fb527266bb367d1831626897442b6321 Mon Sep 17 00:00:00 2001 From: Dolapo Toki Date: Tue, 23 Jun 2020 12:14:42 -0700 Subject: [PATCH 8/8] test when moudules is empty. rebase from master. --- cmd/init.go | 9 ++++++++- internal/config/projectconfig/init.go | 10 ++++++---- internal/config/projectconfig/init_test.go | 10 +++++----- 3 files changed, 19 insertions(+), 10 deletions(-) diff --git a/cmd/init.go b/cmd/init.go index bf6d07406..49471bd37 100644 --- a/cmd/init.go +++ b/cmd/init.go @@ -1,8 +1,11 @@ package cmd import ( + "fmt" + "github.com/commitdev/zero/internal/config/projectconfig" initPrompts "github.com/commitdev/zero/internal/init" + "github.com/commitdev/zero/pkg/util/exit" "github.com/spf13/cobra" ) @@ -15,6 +18,10 @@ var initCmd = &cobra.Command{ Short: "Create new project with provided name and initialize configuration based on user input.", Run: func(cmd *cobra.Command, args []string) { projectContext := initPrompts.Init(projectconfig.RootDir) - projectconfig.CreateProjectConfigFile(projectconfig.RootDir, projectContext.Name, projectContext) + projectConfigErr := projectconfig.CreateProjectConfigFile(projectconfig.RootDir, projectContext.Name, projectContext) + + if projectConfigErr != nil { + exit.Fatal(fmt.Sprintf(" Init failed while creating the zero project config file %s", projectConfigErr.Error())) + } }, } diff --git a/internal/config/projectconfig/init.go b/internal/config/projectconfig/init.go index 73b4a9547..76dcdc7ac 100644 --- a/internal/config/projectconfig/init.go +++ b/internal/config/projectconfig/init.go @@ -9,7 +9,6 @@ import ( "github.com/commitdev/zero/internal/constants" "github.com/commitdev/zero/internal/util" - "github.com/commitdev/zero/pkg/util/exit" "gopkg.in/yaml.v2" ) @@ -29,16 +28,19 @@ func SetRootDir(dir string) { RootDir = dir } -func CreateProjectConfigFile(dir string, projectName string, projectContext *ZeroProjectConfig) { +// CreateProjectConfigFile extracts the required content for zero project config file then write to disk. +func CreateProjectConfigFile(dir string, projectName string, projectContext *ZeroProjectConfig) error { content, err := getProjectFileContent(*projectContext) if err != nil { - exit.Fatal(fmt.Sprintf("Failed extracting the file config content %s", constants.ZeroProjectYml)) + return err } writeErr := ioutil.WriteFile(path.Join(dir, projectName, constants.ZeroProjectYml), []byte(content), 0644) if writeErr != nil { - exit.Fatal(fmt.Sprintf("Failed to create config file %s", constants.ZeroProjectYml)) + return err } + + return nil } func getProjectFileContent(projectConfig ZeroProjectConfig) (string, error) { diff --git a/internal/config/projectconfig/init_test.go b/internal/config/projectconfig/init_test.go index 5403f14c2..a5cd484df 100644 --- a/internal/config/projectconfig/init_test.go +++ b/internal/config/projectconfig/init_test.go @@ -9,6 +9,7 @@ import ( "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 TestCreateProjectConfigFile(t *testing.T) { @@ -31,7 +32,7 @@ func TestCreateProjectConfigFile(t *testing.T) { ShouldPushRepositories: false, Modules: eksGoReactSampleModules(), } - projectconfig.CreateProjectConfigFile(projectconfig.RootDir, projectName, expectedConfig) + assert.NoError(t, projectconfig.CreateProjectConfigFile(projectconfig.RootDir, projectName, expectedConfig)) // make sure the file exists if _, err := os.Stat(path.Join(testDirPath, constants.ZeroProjectYml)); err != nil { @@ -39,7 +40,6 @@ func TestCreateProjectConfigFile(t *testing.T) { } t.Run("Should return a valid project config", func(t *testing.T) { - resultConfig := projectconfig.LoadConfig(path.Join(testDirPath, constants.ZeroProjectYml)) if !cmp.Equal(expectedConfig, resultConfig, cmpopts.EquateEmpty()) { @@ -47,9 +47,9 @@ func TestCreateProjectConfigFile(t *testing.T) { } }) - /* TODO: Test err is thrown when there is a failure? t.Run("Should fail if modules are missing from project config", func(t *testing.T) { - + expectedConfig.Modules = nil + assert.Error(t, projectconfig.CreateProjectConfigFile(projectconfig.RootDir, projectName, expectedConfig)) }) - */ + }