Skip to content

Commit

Permalink
Added prompts at project create, including lookups for aws credential… (
Browse files Browse the repository at this point in the history
#77)

* Added prompts at project create, including lookups for aws credentials and account id
* Removed create test for now
  • Loading branch information
bmonkman authored and zthomas committed Nov 13, 2019
1 parent 1b3258c commit 2dd20ea
Show file tree
Hide file tree
Showing 11 changed files with 195 additions and 104 deletions.
14 changes: 7 additions & 7 deletions README.md
Expand Up @@ -17,7 +17,7 @@ With Commit0:

As there alot of dependencies it will be easier to use this tool within the provided image, clone the repo and then run `make build-docker-local`.
The best way then to use this is to add an alias, then you can use the CLI as if it was installed as usual on your machine:
`alias commit0='docker run -v "$(pwd):/project" commit0:v0'`
`alias commit0='docker run -it -v "$(pwd):/project" -v "${HOME}/.aws:/root/.aws" commit0:v0'`

## Usage

Expand Down Expand Up @@ -53,22 +53,22 @@ Based on specified config it will generate:
It will also live with your project, when you add a new service to the config it will generate everything needed for that new service.


## Development
## Development
We are looking for contributors!

Building from the source
```
make build-deps
make deps-go
```
this will create a commit0 executable in your working direcory. To install install it into your go path use:
this will create a commit0 executable in your working direcory. To install install it into your go path use:
```
make install-go
```

Compile a new `commit0` binary in the working directory
```
make build
make build
```

Now you can either add your project directory to your path or just execute it directly
Expand All @@ -81,22 +81,22 @@ cd test-app
```

### Architecture
The project is built with GoLang and requires Docker
The project is built with GoLang and requires Docker
- /cmd - the CLI command entry points
- /internal/generate
- /internal/config
- /internal/templator - the templating service

Example Flow:
The application starts at `cmd/generate.go`
1. loads all the templates from packr
1. loads all the templates from packr
- TODO: eventually this should be loaded remotely throug a dependency management system
2. loads the config from the commit0.yml config file
3. based on the configs, run the appropriate generators
- templator is passed in to the Generate function for dependency injection
- `internal/generate/generate_helper.go` iterates through all the configs and runs each generator
4. each generator (`react/generate.go`, `ci/generate.go` etc) further delegates and actually executes the templating based on the configs passed in.
- `internal/templator/templator.go` is the base class and includes generic templating handling logic
- `internal/templator/templator.go` is the base class and includes generic templating handling logic
- it CI is required, it'll also call a CI generator and pass in the service specific CI configs
- TOOD: CI templates have to call separate templates based on the context
- TODO: templator should be generic and not have any knowledge of the specific templating implementation (go, ci etc), move that logic upstream
Expand Down
64 changes: 59 additions & 5 deletions cmd/create.go
Expand Up @@ -6,11 +6,18 @@ import (
"path"
"sync"

"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/sts"
"github.com/commitdev/commit0/internal/templator"
"github.com/commitdev/commit0/internal/util"
"github.com/commitdev/commit0/internal/util/secrets"
"github.com/gobuffalo/packr/v2"
"github.com/kyokomi/emoji"
"github.com/logrusorgru/aurora"
"github.com/manifoldco/promptui"
"github.com/spf13/cobra"
)

Expand All @@ -22,16 +29,63 @@ func Create(projectName string, outDir string, t *templator.Templator) string {
rootDir := path.Join(outDir, projectName)
log.Println(aurora.Cyan(emoji.Sprintf(":tada: Creating project %s.", projectName)))
err := os.MkdirAll(rootDir, os.ModePerm)

if os.IsExist(err) {
log.Fatalln(aurora.Red(emoji.Sprintf(":exclamation: Directory %v already exists! Error: %v", projectName, err)))
} else if err != nil {
log.Fatalln(aurora.Red(emoji.Sprintf(":exclamation: Error creating root: %v ", err)))
}
var wg sync.WaitGroup

// @TODO : Clean up the following aws stuff
providerPrompt := promptui.Select{
Label: "Select Cloud Provider",
Items: []string{"Amazon AWS", "Google GCP", "Microsoft Azure"},
}

_, _, err = providerPrompt.Run()

regionPrompt := promptui.Select{
Label: "Select AWS Region ",
Items: []string{"us-west-1", "us-west-2", "us-east-1", "us-east-2", "ca-central-1",
"eu-central-1", "eu-west-1", "ap-east-1", "ap-south-1"},
}

_, regionResult, err := regionPrompt.Run()

if err != nil {
log.Fatalf("Prompt failed %v\n", err)
panic(err)
}

s := secrets.GetSecrets(rootDir)

sess, err := session.NewSession(&aws.Config{
Region: aws.String(regionResult),
Credentials: credentials.NewStaticCredentials(s.AWS.AccessKeyID, s.AWS.SecretAccessKey, ""),
})

svc := sts.New(sess)
input := &sts.GetCallerIdentityInput{}

awsCaller, err := svc.GetCallerIdentity(input)
if err != nil {
if aerr, ok := err.(awserr.Error); ok {
switch aerr.Code() {
default:
log.Fatalf(aerr.Error())
}
} else {
log.Fatalf(err.Error())
}
}

defaultProjConfig := defaultProjConfig(projectName)

defaultProjConfig.Infrastructure.AWS.Region = regionResult
if awsCaller != nil && awsCaller.Account != nil {
defaultProjConfig.Infrastructure.AWS.AccountID = *awsCaller.Account
}

var wg sync.WaitGroup
util.TemplateFileIfDoesNotExist(rootDir, util.CommitYml, t.Commit0, &wg, defaultProjConfig)
util.TemplateFileIfDoesNotExist(rootDir, ".gitignore", t.GitIgnore, &wg, projectName)

Expand All @@ -50,10 +104,10 @@ func defaultProjConfig(projectName string) util.ProjectConfiguration {
Email: "bob@test.com",
}},
Services: []util.Service{{
Name: "User",
Name: "User",
Description: "User Service",
Language: "go",
GitRepo: "github.com/test/repo",
Language: "go",
GitRepo: "github.com/test/repo",
}},
}
}
Expand Down
41 changes: 17 additions & 24 deletions cmd/create_test.go
@@ -1,37 +1,30 @@
package cmd_test

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

"github.com/commitdev/commit0/cmd"
"github.com/commitdev/commit0/internal/templator"
"github.com/commitdev/commit0/internal/util"
"github.com/gobuffalo/packr/v2"
)

func TestCreateWorks(t *testing.T) {
tmpdir, err := ioutil.TempDir("", "commit0-")
if err != nil {
t.Fatal(err)
}
// @TODO : Figure out a way to test this
// tmpdir, err := ioutil.TempDir("", "commit0-")
// if err != nil {
// t.Fatal(err)
// }

projectName := "test-project"
// projectName := "test-project"

templates := packr.New("templates", "../templates")
templator := templator.NewTemplator(templates)
// templates := packr.New("templates", "../templates")
// templator := templator.NewTemplator(templates)

root := cmd.Create(projectName, tmpdir, templator)
defer os.RemoveAll(tmpdir)
// root := cmd.Create(projectName, tmpdir, templator)
// defer os.RemoveAll(tmpdir)

st, err := os.Stat(path.Join(root, util.CommitYml))
if err != nil {
t.Fatal(err)
}
// st, err := os.Stat(path.Join(root, util.CommitYml))
// if err != nil {
// t.Fatal(err)
// }

if st.Size() == 0 {
t.Fatalf("commit0.yml is empty")
}
// if st.Size() == 0 {
// t.Fatalf("commit0.yml is empty")
// }
}
2 changes: 2 additions & 0 deletions go.mod
Expand Up @@ -3,6 +3,8 @@ module github.com/commitdev/commit0
go 1.12

require (
github.com/aws/aws-sdk-go v1.25.33
github.com/aws/aws-sdk-go-v2 v0.16.0
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
Expand Down
12 changes: 12 additions & 0 deletions go.sum
@@ -1,6 +1,10 @@
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/aws/aws-sdk-go v1.25.33 h1:8muvpP+Bq5e0CDkM9PDZ6tN74fVUq5v3zSCRaZ93ykM=
github.com/aws/aws-sdk-go v1.25.33/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
github.com/aws/aws-sdk-go-v2 v0.16.0 h1:X5pkFnjRNdDEX18NwDGWMaWL5ocNQX0qIYEhEcsTy64=
github.com/aws/aws-sdk-go-v2 v0.16.0/go.mod h1:pFLIN9LDjOEwHfruGweAXEq0XaD6uRkY8FsRkxhuBIg=
github.com/chzyer/logex v1.1.10 h1:Swpa1K6QvQznwJRcfTfQJmTE72DqScAa40E+fbHEXEE=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
Expand All @@ -15,6 +19,7 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/gobuffalo/envy v1.7.0 h1:GlXgaiBkmrYMHco6t4j7SacKO4XUjvh5pwXh0f4uxXU=
github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI=
github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs=
Expand All @@ -24,11 +29,15 @@ github.com/gobuffalo/packd v0.3.0 h1:eMwymTkA1uXsqxS0Tpoop3Lc0u3kTfiMBE6nKtQU4g4
github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q=
github.com/gobuffalo/packr/v2 v2.5.2 h1:4EvjeIpQLZuRIljwnidYgbRXbr1yIzVRrESiLjqKj6s=
github.com/gobuffalo/packr/v2 v2.5.2/go.mod h1:sgEE1xNZ6G0FNN5xn9pevVu4nywaxHvgup67xisti08=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
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=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU=
Expand Down Expand Up @@ -93,6 +102,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550 h1:ObdrDkeb4kJdCP557AjRjq69pTHfNouLtWZG7j9rPN8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3 h1:0GoQqolDA55aaLxZyTzK/Y2ePZzZTUrRacwib7cNsYQ=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
Expand All @@ -113,6 +124,7 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0 h1:Dh6fw+p6FyRl5x/FvNswO1j
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0 h1:Dh6fw+p6FyRl5x/FvNswO1ji0lIGzm3KP8Y9VkS9PTE=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
Expand Down
3 changes: 2 additions & 1 deletion internal/generate/kubernetes/generate.go
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/commitdev/commit0/internal/config"
"github.com/commitdev/commit0/internal/templator"
"github.com/commitdev/commit0/internal/util"
"github.com/commitdev/commit0/internal/util/secrets"
"github.com/kyokomi/emoji"
"github.com/logrusorgru/aurora"
)
Expand All @@ -21,7 +22,7 @@ func Generate(t *templator.Templator, cfg *config.Commit0Config, wg *sync.WaitGr

// Execute terrafrom init & plan
func Execute(cfg *config.Commit0Config, pathPrefix string) {
envars := util.MakeAwsEnvars(util.GetSecrets())
envars := secrets.MakeAwsEnvars(cfg, secrets.GetSecrets(util.GetCwd()))

pathPrefix = filepath.Join(pathPrefix, "kubernetes/terraform")

Expand Down
13 changes: 7 additions & 6 deletions internal/generate/terraform/generate.go
Expand Up @@ -9,6 +9,7 @@ import (
"github.com/commitdev/commit0/internal/config"
"github.com/commitdev/commit0/internal/templator"
"github.com/commitdev/commit0/internal/util"
"github.com/commitdev/commit0/internal/util/secrets"

"github.com/kyokomi/emoji"
"github.com/logrusorgru/aurora"
Expand Down Expand Up @@ -38,12 +39,12 @@ func Generate(t *templator.Templator, cfg *config.Commit0Config, wg *sync.WaitGr
}

// GetOutputs captures the terraform output for the specific variables
func GetOutputs(config *config.Commit0Config, pathPrefix string, outputs []string) map[string]string {
func GetOutputs(cfg *config.Commit0Config, pathPrefix string, outputs []string) map[string]string {
outputsMap := make(map[string]string)

log.Println("Preparing aws environment...")

envars := util.MakeAwsEnvars(util.GetSecrets())
envars := secrets.MakeAwsEnvars(cfg, secrets.GetSecrets(util.GetCwd()))

pathPrefix = filepath.Join(pathPrefix, "environments/staging")

Expand All @@ -56,12 +57,12 @@ func GetOutputs(config *config.Commit0Config, pathPrefix string, outputs []strin
}

// Init sets up anything required by Execute
func Init(config *config.Commit0Config, pathPrefix string) {
func Init(cfg *config.Commit0Config, pathPrefix string) {
// @TODO : Change this check. Most likely we should discover the accountid
if config.Infrastructure.AWS.AccountId != "" {
if cfg.Infrastructure.AWS.AccountId != "" {
log.Println("Preparing aws environment...")

envars := util.MakeAwsEnvars(util.GetSecrets())
envars := secrets.MakeAwsEnvars(cfg, secrets.GetSecrets(util.GetCwd()))

pathPrefix = filepath.Join(pathPrefix, "terraform")

Expand All @@ -78,7 +79,7 @@ func Execute(cfg *config.Commit0Config, pathPrefix string) {
if cfg.Infrastructure.AWS.AccountId != "" {
log.Println("Preparing aws environment...")

envars := util.MakeAwsEnvars(util.GetSecrets())
envars := secrets.MakeAwsEnvars(cfg, secrets.GetSecrets(util.GetCwd()))

pathPrefix = filepath.Join(pathPrefix, "terraform")

Expand Down
31 changes: 20 additions & 11 deletions internal/util/projectAttributes.go
Expand Up @@ -21,22 +21,31 @@ func ValidateLanguage(language string) bool {
}

type Maintainer struct {
Name string `json:"name"`
Email string `json:"email"`
Name string
Email string
}

type Service struct {
Name string `json:"name"`
Description string `json:"description"`
Language string `json:"language"`
Name string
Description string
Language string
GitRepo string `json:"gitRepo"`
}

type ProjectConfiguration struct {
ProjectName string `json:"projectName"`
FrontendFramework string `json:"frontendFramework"`
Organization string `json:"organization"`
Description string `json:"description"`
Maintainers []Maintainer `json:"maintainers"`
Services []Service `json:"services"`
ProjectName string `json:"projectName"`
FrontendFramework string `json:"frontendFramework"`
Organization string
Description string
Maintainers []Maintainer
Services []Service
Infrastructure Infrastructure
}

type Infrastructure struct {
AWS AWS
}
type AWS struct {
AccountID string
Region string
}

0 comments on commit 2dd20ea

Please sign in to comment.