-
Notifications
You must be signed in to change notification settings - Fork 52
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
dedupe #143
dedupe #143
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
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" | ||
) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
package config | ||
|
||
import ( | ||
"bytes" | ||
"io/ioutil" | ||
"log" | ||
"os" | ||
"os/user" | ||
"path" | ||
|
||
"github.com/commitdev/zero/configs" | ||
"github.com/commitdev/zero/pkg/util/exit" | ||
yaml "gopkg.in/yaml.v2" | ||
) | ||
|
||
var GetCredentialsPath = getCredentialsPath | ||
|
||
type ProjectCredentials map[string]ProjectCredential | ||
|
||
type ProjectCredential 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 ProjectCredentials) Unmarshal(data []byte) error { | ||
if len(data) == 0 { | ||
return nil | ||
} | ||
err := yaml.NewDecoder(bytes.NewReader(data)).Decode(p) | ||
if err != nil { | ||
return err | ||
} | ||
for k, v := range p { | ||
v.ProjectName = k | ||
p[k] = v | ||
} | ||
return nil | ||
} | ||
|
||
func LoadUserCredentials() ProjectCredentials { | ||
data := readOrCreateUserCredentialsFile() | ||
|
||
projects := ProjectCredentials{} | ||
|
||
err := projects.Unmarshal(data) | ||
|
||
if err != nil { | ||
exit.Fatal("Failed to parse configuration: %v", err) | ||
} | ||
return projects | ||
} | ||
|
||
func getCredentialsPath() string { | ||
usr, err := user.Current() | ||
if err != nil { | ||
exit.Fatal("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 { | ||
exit.Fatal("Failed to create config file: %v", fileStateErr) | ||
} | ||
defer file.Close() | ||
} | ||
data, err := ioutil.ReadFile(credPath) | ||
if err != nil { | ||
exit.Fatal("Failed to read credentials file: %v", err) | ||
} | ||
return data | ||
} | ||
|
||
func GetUserCredentials(targetProjectName string) ProjectCredential { | ||
projects := LoadUserCredentials() | ||
|
||
if val, ok := projects[targetProjectName]; ok { | ||
return val | ||
} else { | ||
p := ProjectCredential{ | ||
ProjectName: targetProjectName, | ||
} | ||
projects[targetProjectName] = p | ||
return p | ||
} | ||
} | ||
|
||
func Save(project ProjectCredential) { | ||
projects := LoadUserCredentials() | ||
projects[project.ProjectName] = project | ||
writeCredentialsFile(projects) | ||
} | ||
|
||
func writeCredentialsFile(projects ProjectCredentials) { | ||
credsPath := GetCredentialsPath() | ||
content, _ := yaml.Marshal(projects) | ||
err := ioutil.WriteFile(credsPath, content, 0644) | ||
if err != nil { | ||
log.Panicf("failed to write config: %v", err) | ||
} | ||
} |
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) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. These should really be testing the API of the package rather than the internals. By calling a function like There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Make sense, should I create another file for tests like this under the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe, though the general practice is try to make your tests in the _test package, then test the exported stuff and not the internals so that your test is coupled to the "API" which should be stable and not the internals which could change. And if you get to the point where the "API" is masking a massive amount of code, try to split it up into smaller packages which can be easily tested in isolation. |
||
config.GetCredentialsPath = func() string { | ||
return path.Join(baseTestFixturesDir, "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") | ||
// attempting to read the file should create the file | ||
config.GetUserCredentials("any-project") | ||
|
||
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" | ||
config.Save(project) | ||
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" | ||
config.Save(project) | ||
newKeyID := config.GetUserCredentials(projectName).AWSResourceConfig.AccessKeyId | ||
assert.Equal(t, "EDITED_ACCESS_KEY_ID", newKeyID) | ||
}) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice tests!