internal/setup/setup.go
// Package setup provides up.json initialization.
package setup
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"sort"
"github.com/mitchellh/go-homedir"
"github.com/tj/go/term"
"github.com/tj/survey"
"github.com/apex/up/internal/util"
"github.com/apex/up/internal/validate"
"github.com/apex/up/platform/aws/regions"
)
// ErrNoCredentials is the error returned when no AWS credential profiles are available.
var ErrNoCredentials = errors.New("no credentials")
// config saved to up.json
type config struct {
Name string `json:"name"`
Profile string `json:"profile"`
Regions []string `json:"regions"`
}
// questions for the user.
var questions = []*survey.Question{
{
Name: "name",
Prompt: &survey.Input{
Message: "Project name:",
Default: defaultName(),
},
Validate: validateName,
},
{
Name: "profile",
Prompt: &survey.Select{
Message: "AWS profile:",
Options: awsProfiles(),
Default: os.Getenv("AWS_PROFILE"),
PageSize: 10,
},
Validate: survey.Required,
},
{
Name: "region",
Prompt: &survey.Select{
Message: "AWS region:",
Options: regions.Names,
Default: defaultRegion(),
PageSize: 15,
},
Validate: survey.Required,
},
}
// Create an up.json file for the user.
func Create() error {
var in struct {
Name string `json:"name"`
Profile string `json:"profile"`
Region string `json:"region"`
}
if len(awsProfiles()) == 0 {
return ErrNoCredentials
}
println()
// confirm
var ok bool
err := survey.AskOne(&survey.Confirm{
Message: fmt.Sprintf("No up.json found, create a new project?"),
Default: true,
}, &ok, nil)
if err != nil {
return err
}
if !ok {
return errors.New("aborted")
}
// prompt
term.MoveUp(1)
term.ClearLine()
if err := survey.Ask(questions, &in); err != nil {
return err
}
c := config{
Name: in.Name,
Profile: in.Profile,
Regions: []string{
regions.GetIdByName(in.Region),
},
}
b, _ := json.MarshalIndent(c, "", " ")
return ioutil.WriteFile("up.json", b, 0644)
}
// defaultName returns the default app name.
// The name is only inferred if it is valid.
func defaultName() string {
dir, _ := os.Getwd()
name := filepath.Base(dir)
if validate.Name(name) != nil {
return ""
}
return name
}
// defaultRegion returns the default aws region.
func defaultRegion() string {
if s := os.Getenv("AWS_DEFAULT_REGION"); s != "" {
return s
}
if s := os.Getenv("AWS_REGION"); s != "" {
return s
}
return ""
}
// validateName validates the name prompt.
func validateName(v interface{}) error {
if err := validate.Name(v.(string)); err != nil {
return err
}
return survey.Required(v)
}
// awsProfiles returns the AWS profiles found.
func awsProfiles() []string {
path, err := homedir.Expand("~/.aws/credentials")
if err != nil {
return nil
}
f, err := os.Open(path)
if err != nil {
return nil
}
defer f.Close()
s, err := util.ParseSections(f)
if err != nil {
return nil
}
sort.Strings(s)
return s
}