github.com/webonyx/up@v0.7.4-0.20180808230834-91b94e551323/internal/setup/setup.go (about) 1 // Package setup provides up.json initialization. 2 package setup 3 4 import ( 5 "encoding/json" 6 "errors" 7 "fmt" 8 "io/ioutil" 9 "os" 10 "path/filepath" 11 "sort" 12 13 "github.com/mitchellh/go-homedir" 14 "github.com/tj/go/term" 15 "github.com/tj/survey" 16 17 "github.com/apex/up/internal/util" 18 "github.com/apex/up/internal/validate" 19 "github.com/apex/up/platform/aws/regions" 20 ) 21 22 // ErrNoCredentials is the error returned when no AWS credential profiles are available. 23 var ErrNoCredentials = errors.New("no credentials") 24 25 // config saved to up.json 26 type config struct { 27 Name string `json:"name"` 28 Profile string `json:"profile"` 29 Regions []string `json:"regions"` 30 } 31 32 // questions for the user. 33 var questions = []*survey.Question{ 34 { 35 Name: "name", 36 Prompt: &survey.Input{ 37 Message: "Project name:", 38 Default: defaultName(), 39 }, 40 Validate: validateName, 41 }, 42 { 43 Name: "profile", 44 Prompt: &survey.Select{ 45 Message: "AWS profile:", 46 Options: awsProfiles(), 47 Default: os.Getenv("AWS_PROFILE"), 48 PageSize: 10, 49 }, 50 Validate: survey.Required, 51 }, 52 { 53 Name: "region", 54 Prompt: &survey.Select{ 55 Message: "AWS region:", 56 Options: regions.Names, 57 Default: defaultRegion(), 58 PageSize: 15, 59 }, 60 Validate: survey.Required, 61 }, 62 } 63 64 // Create an up.json file for the user. 65 func Create() error { 66 var in struct { 67 Name string `json:"name"` 68 Profile string `json:"profile"` 69 Region string `json:"region"` 70 } 71 72 if len(awsProfiles()) == 0 { 73 return ErrNoCredentials 74 } 75 76 println() 77 78 // confirm 79 var ok bool 80 err := survey.AskOne(&survey.Confirm{ 81 Message: fmt.Sprintf("No up.json found, create a new project?"), 82 Default: true, 83 }, &ok, nil) 84 85 if err != nil { 86 return err 87 } 88 89 if !ok { 90 return errors.New("aborted") 91 } 92 93 // prompt 94 term.MoveUp(1) 95 term.ClearLine() 96 if err := survey.Ask(questions, &in); err != nil { 97 return err 98 } 99 100 c := config{ 101 Name: in.Name, 102 Profile: in.Profile, 103 Regions: []string{ 104 regions.GetIdByName(in.Region), 105 }, 106 } 107 108 b, _ := json.MarshalIndent(c, "", " ") 109 return ioutil.WriteFile("up.json", b, 0644) 110 } 111 112 // defaultName returns the default app name. 113 // The name is only inferred if it is valid. 114 func defaultName() string { 115 dir, _ := os.Getwd() 116 name := filepath.Base(dir) 117 if validate.Name(name) != nil { 118 return "" 119 } 120 return name 121 } 122 123 // defaultRegion returns the default aws region. 124 func defaultRegion() string { 125 if s := os.Getenv("AWS_DEFAULT_REGION"); s != "" { 126 return s 127 } 128 129 if s := os.Getenv("AWS_REGION"); s != "" { 130 return s 131 } 132 133 return "" 134 } 135 136 // validateName validates the name prompt. 137 func validateName(v interface{}) error { 138 if err := validate.Name(v.(string)); err != nil { 139 return err 140 } 141 142 return survey.Required(v) 143 } 144 145 // awsProfiles returns the AWS profiles found. 146 func awsProfiles() []string { 147 path, err := homedir.Expand("~/.aws/credentials") 148 if err != nil { 149 return nil 150 } 151 152 f, err := os.Open(path) 153 if err != nil { 154 return nil 155 } 156 defer f.Close() 157 158 s, err := util.ParseSections(f) 159 if err != nil { 160 return nil 161 } 162 163 sort.Strings(s) 164 return s 165 }