Skip to content

Commit

Permalink
zero init features: dedupe/new prompts/config file
Browse files Browse the repository at this point in the history
  • Loading branch information
davidcheung committed Jun 1, 2020
1 parent d4f95bf commit 7e655d1
Show file tree
Hide file tree
Showing 9 changed files with 325 additions and 12 deletions.
10 changes: 6 additions & 4 deletions configs/configs.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package configs

const (
TemplatesDir = "tmp/templates"
ZeroProjectYml = "zero-project.yml"
IgnoredPaths = "(?i)zero.module.yml|.git/"
TemplateExtn = ".tmpl"
TemplatesDir = "tmp/templates"
ZeroProjectYml = "zero-project.yml"
ZeroHomeDirectory = ".zero"
UserCredentials = "credentials.yml"
IgnoredPaths = "(?i)zero.module.yml|.git/"
TemplateExtn = ".tmpl"
)
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ require (
github.com/logrusorgru/aurora v0.0.0-20191017060258-dc85c304c434
github.com/manifoldco/promptui v0.3.0
github.com/spf13/cobra v0.0.6
github.com/stretchr/testify v1.5.1 // indirect
github.com/stretchr/testify v1.4.0
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b // indirect
gopkg.in/yaml.v2 v2.2.5
)
12 changes: 12 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZm
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
Expand Down Expand Up @@ -101,6 +102,7 @@ github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1 h1:0hERBMJE1eitiLkihrMvRVBYAkpHzc/J3QdDN+dAcgU=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
Expand Down Expand Up @@ -131,6 +133,7 @@ github.com/logrusorgru/aurora v0.0.0-20191017060258-dc85c304c434 h1:im9kkmH0WWwx
github.com/logrusorgru/aurora v0.0.0-20191017060258-dc85c304c434/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/manifoldco/promptui v0.3.0 h1:vJiVJREqDfn9ZhqTG1Dz5zP9RPWlAzWQkwRYLGyUHx4=
github.com/manifoldco/promptui v0.3.0/go.mod h1:zoCNXiJnyM03LlBgTsWv8mq28s7aTC71UgKasqRJHww=
Expand All @@ -147,9 +150,11 @@ github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0 h1:fzU/JVNcaqHQEcVFAKeR41fkiLdIPrefOvVG1VZ96U0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
Expand All @@ -170,19 +175,24 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2 h1:m8/z1t7/fwjysjQRYbP0RD+bUIF/8tJwPdEZsI83ACI=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU=
github.com/spf13/cobra v0.0.6 h1:breEStsVwemnKh2/s6gMvSdMEkwW0sK8vGStnlVBMCs=
github.com/spf13/cobra v0.0.6/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE=
github.com/spf13/jwalterweatherman v1.0.0 h1:XHEdyB+EcvlqZamSM4ZOMGlc93t6AcsBEu9Gc1vn7yk=
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
github.com/spf13/viper v1.4.0 h1:yXHLWeravcrgGyFSyCgdYpXQ9dR9c/WED3pg1RhxqEU=
github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
Expand Down Expand Up @@ -312,6 +322,8 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5 h1:ymVxjfMaHvXD8RqPRmzHHsB3VvucivSkIAvJFDI5O3c=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200506231410-2ff61e1afc86 h1:OfFoIUYv/me30yv7XlMy4F9RJw8DEm8WQ6QG1Ph4bH0=
gopkg.in/yaml.v3 v3.0.0-20200506231410-2ff61e1afc86/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
Expand Down
118 changes: 118 additions & 0 deletions internal/config/global_config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
package config

import (
"bytes"
"io/ioutil"
"log"
"os"
"os/user"
"path"

"github.com/commitdev/zero/configs"
yaml "gopkg.in/yaml.v2"
)

var GetCredentialsPath = getCredentialsPath

type Projects map[string]*Project

type Project struct {
ProjectName string `yaml:"-"`
AWSResourceConfig `yaml:"aws,omitempty"`
GithubResourceConfig `yaml:"github,omitempty"`
CircleCiResourceConfig `yaml:"circleci,omitempty"`
}

type AWSResourceConfig struct {
AccessKeyId string `yaml:"accessKeyId,omitempty"`
SecretAccessKey string `yaml:"secretAccessKey,omitempty"`
}
type GithubResourceConfig struct {
AccessToken string `yaml:"accessToken,omitempty"`
}
type CircleCiResourceConfig struct {
ApiKey string `yaml:"apiKey,omitempty"`
}

func (p *Projects) Unmarshal(data []byte) error {
err := yaml.NewDecoder(bytes.NewReader(data)).Decode(p)
if err != nil {
return err
}
for k, v := range *p {
v.ProjectName = k
}
return nil
}

func LoadUserCredentials() Projects {
data := ReadOrCreateUserCredentialsFile()

projects := Projects{}
err := projects.Unmarshal(data)

if err != nil {
log.Fatalf("Failed to parse configuration: %v", err)
}
return projects
}

func getCredentialsPath() string {
usr, err := user.Current()
if err != nil {
log.Fatalf("Failed to get user directory path: %v", err)
}

rootDir := path.Join(usr.HomeDir, configs.ZeroHomeDirectory)
os.MkdirAll(rootDir, os.ModePerm)
filePath := path.Join(rootDir, configs.UserCredentials)
return filePath
}

func ReadOrCreateUserCredentialsFile() []byte {
credPath := GetCredentialsPath()

_, fileStateErr := os.Stat(credPath)
if os.IsNotExist(fileStateErr) {
var file, fileStateErr = os.Create(credPath)
if fileStateErr != nil {
log.Fatalf("Failed to create config file: %v", fileStateErr)
}
defer file.Close()
}
data, err := ioutil.ReadFile(credPath)
if err != nil {
log.Fatalf("Failed to read credentials file: %v", err)
}
return data

}

func GetUserCredentials(targetProjectName string) *Project {
projects := LoadUserCredentials()

if val, ok := projects[targetProjectName]; ok {
return val
} else {
p := Project{
ProjectName: targetProjectName,
}
projects[targetProjectName] = &p
return &p
}
}

func (project *Project) Save() {
projects := LoadUserCredentials()
projects[project.ProjectName] = project
projects.Save()
}

func (projects *Projects) Save() {
credsPath := GetCredentialsPath()
content, _ := yaml.Marshal(&projects)
err := ioutil.WriteFile(credsPath, content, 0644)
if err != nil {
log.Panicf("failed to parse config: %v", err)
}
}
103 changes: 103 additions & 0 deletions internal/config/global_config_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package config_test

import (
"fmt"
"io/ioutil"
"log"
"os"
"path"
"testing"

"github.com/commitdev/zero/internal/config"
"github.com/stretchr/testify/assert"
)

const baseTestFixturesDir = "../../tests/test_data/configs/"

var testCredentialFile = func() (func() string, func()) {
tmpConfigPath := getTmpConfig()
mockFunc := func() string { return tmpConfigPath }
teardownFunc := func() { os.RemoveAll(tmpConfigPath) }
return mockFunc, teardownFunc
}

func getTmpConfig() string {
pathFrom := path.Join(baseTestFixturesDir, fmt.Sprintf("credentials%s.yml", ""))
pathTo := path.Join(baseTestFixturesDir, fmt.Sprintf("credentials%s.yml", "-tmp"))
copyFile(pathFrom, pathTo)
return pathTo
}

func copyFile(from string, to string) {
bytesRead, err := ioutil.ReadFile(from)
if err != nil {
log.Fatal(err)
}

err = ioutil.WriteFile(to, bytesRead, 0644)
if err != nil {
log.Fatal(err)
}
}
func TestReadOrCreateUserCredentialsFile(t *testing.T) {
config.GetCredentialsPath = func() string {
return path.Join("../../tests/test_data/", "configs/does-not-exist.yml")
}
credPath := config.GetCredentialsPath()
defer os.RemoveAll(credPath)

_, fileStateErr := os.Stat(credPath)
assert.True(t, os.IsNotExist(fileStateErr), "File should not exist")

config.ReadOrCreateUserCredentialsFile()
stats, err := os.Stat(credPath)
assert.False(t, os.IsNotExist(err), "File should be created")
assert.Equal(t, "does-not-exist.yml", stats.Name(), "Should create yml automatically")
}

func TestGetUserCredentials(t *testing.T) {
var teardownFn func()
config.GetCredentialsPath, teardownFn = testCredentialFile()
defer teardownFn()

t.Run("Fixture file should have existing project with creds", func(t *testing.T) {
projectName := "my-project"
project := config.GetUserCredentials(projectName)

// Reading from fixtures: tests/test_data/configs/credentials.yml
assert.Equal(t, "AKIAABCD", project.AWSResourceConfig.AccessKeyId)
assert.Equal(t, "ZXCV", project.AWSResourceConfig.SecretAccessKey)
assert.Equal(t, "0987", project.GithubResourceConfig.AccessToken)
assert.Equal(t, "SOME_API_KEY", project.CircleCiResourceConfig.ApiKey)
})

t.Run("Fixture file should support multiple projects", func(t *testing.T) {
projectName := "another-project"
project := config.GetUserCredentials(projectName)
assert.Equal(t, "654", project.GithubResourceConfig.AccessToken)
})

}

func TestEditUserCredentials(t *testing.T) {
var teardownFn func()
config.GetCredentialsPath, teardownFn = testCredentialFile()
defer teardownFn()

t.Run("Should create new project if not exist", func(t *testing.T) {
projectName := "test-project3"
project := config.GetUserCredentials(projectName)
project.AWSResourceConfig.AccessKeyId = "TEST_KEY_ID_1"
project.Save()
newKeyID := config.GetUserCredentials(projectName).AWSResourceConfig.AccessKeyId
assert.Equal(t, "TEST_KEY_ID_1", newKeyID)
})
t.Run("Should edit old project if already exist", func(t *testing.T) {
projectName := "my-project"
project := config.GetUserCredentials(projectName)
project.AWSResourceConfig.AccessKeyId = "EDITED_ACCESS_KEY_ID"
project.Save()
newKeyID := config.GetUserCredentials(projectName).AWSResourceConfig.AccessKeyId
assert.Equal(t, "EDITED_ACCESS_KEY_ID", newKeyID)
})
}
3 changes: 2 additions & 1 deletion internal/config/init_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@ func TestInit(t *testing.T) {
t.Fatal(err)
}

config.Init(config.RootDir, projectName, nil)
projectConfig := config.ZeroProjectConfig{}
config.Init(config.RootDir, projectName, &projectConfig)

if _, err := os.Stat(path.Join(testDirPath, configs.ZeroProjectYml)); err != nil {
t.Fatal(err)
Expand Down

0 comments on commit 7e655d1

Please sign in to comment.