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  }