Skip to content
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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion cmd/init.go
Original file line number Diff line number Diff line change
@@ -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"
)

Expand All @@ -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.Init(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()))
}
},
}
81 changes: 48 additions & 33 deletions internal/config/projectconfig/init.go
Original file line number Diff line number Diff line change
@@ -1,43 +1,25 @@
package projectconfig

import (
"bytes"
"fmt"
"io/ioutil"
"path"
"text/template"

"github.com/commitdev/zero/internal/constants"
"github.com/commitdev/zero/pkg/util/exit"
"github.com/commitdev/zero/internal/util"
"gopkg.in/yaml.v2"
)

const exampleConfig = `name: %s
const zeroProjectConfigTemplate = `
# 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 = "./"
Expand All @@ -46,16 +28,49 @@ func SetRootDir(dir string) {
RootDir = dir
}

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)
// 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 to serialize configuration file %s", constants.ZeroProjectYml))
return err
}

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))
return err
}

return nil
}

func getProjectFileContent(projectConfig ZeroProjectConfig) (string, error) {
var tplBuffer bytes.Buffer
tmpl, err := template.New("projectConfig").Parse(zeroProjectConfigTemplate)
if err != nil {
return "", err
}

if len(projectConfig.Modules) == 0 {
return "", fmt.Errorf("Invalid project config, expected config modules to be non-empty")
}

pConfigModules, err := yaml.Marshal(projectConfig.Modules)
if err != nil {
return "", err
}

t := struct {
Name string
ShouldPushRepositories bool
Modules string
}{
Name: projectConfig.Name,
ShouldPushRepositories: projectConfig.ShouldPushRepositories,
Modules: util.IndentString(string(pConfigModules), 2),
}

if err := tmpl.Execute(&tplBuffer, t); err != nil {
return "", err
}
return tplBuffer.String(), nil
}
29 changes: 26 additions & 3 deletions internal/config/projectconfig/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,49 @@ 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"
"github.com/stretchr/testify/assert"
)

func TestInit(t *testing.T) {
func TestCreateProjectConfigFile(t *testing.T) {
const testDir = "../../test-sandbox"
projectName := "test-project"

projectconfig.SetRootDir(testDir)
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(),
}
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 {
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))
}
})

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))
})

}
2 changes: 1 addition & 1 deletion internal/config/projectconfig/project_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ type Modules map[string]Module

type Module struct {
Parameters Parameters `yaml:"parameters,omitempty"`
Files Files
Files Files `yaml:"files,omitempty"`
}

type Parameters map[string]string
Expand Down
45 changes: 24 additions & 21 deletions internal/config/projectconfig/project_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,29 +45,32 @@ func eksGoReactSampleModules() projectconfig.Modules {

func validConfigContent() string {
return `
# Templated zero-project.yml file
name: abc

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
`
}
11 changes: 11 additions & 0 deletions internal/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"os"
"os/exec"
"path"
"strconv"
"strings"
"text/template"

Expand Down Expand Up @@ -113,3 +114,13 @@ 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, spaces int) string {
var result string
subStr := strings.Split(content, "\n")
for _, s := range subStr {
result += fmt.Sprintf("%"+strconv.Itoa(spaces)+"s%s\n", "", s)
}
return result
}