github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/cmd/juju/commands/bootstrap_interactive.go (about)

     1  // Copyright 2016 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package commands
     5  
     6  import (
     7  	"bufio"
     8  	"fmt"
     9  	"io"
    10  	"sort"
    11  	"strings"
    12  
    13  	"github.com/juju/errors"
    14  	jujucloud "github.com/juju/juju/cloud"
    15  	"github.com/juju/juju/cmd/juju/common"
    16  	"github.com/juju/juju/cmd/juju/interact"
    17  )
    18  
    19  // assembleClouds
    20  func assembleClouds() ([]string, error) {
    21  	public, _, err := jujucloud.PublicCloudMetadata(jujucloud.JujuPublicCloudsPath())
    22  	if err != nil {
    23  		return nil, errors.Trace(err)
    24  	}
    25  
    26  	personal, err := jujucloud.PersonalCloudMetadata()
    27  	if err != nil {
    28  		return nil, errors.Trace(err)
    29  	}
    30  
    31  	return sortClouds(public, common.BuiltInClouds(), personal), nil
    32  }
    33  
    34  // queryCloud asks the user to choose a cloud.
    35  func queryCloud(clouds []string, defCloud string, scanner *bufio.Scanner, w io.Writer) (string, error) {
    36  	list := strings.Join(clouds, "\n")
    37  	if _, err := fmt.Fprint(w, "Clouds\n", list, "\n\n"); err != nil {
    38  		return "", errors.Trace(err)
    39  	}
    40  
    41  	// add support for a default (empty) selection.
    42  	clouds = append(clouds, "")
    43  
    44  	verify := interact.MatchOptions(clouds, errors.Errorf("Invalid cloud."))
    45  
    46  	query := fmt.Sprintf("Select a cloud [%s]: ", defCloud)
    47  	cloud, err := interact.QueryVerify([]byte(query), scanner, w, verify)
    48  	if err != nil {
    49  		return "", errors.Trace(err)
    50  	}
    51  	if cloud == "" {
    52  		return defCloud, nil
    53  	}
    54  
    55  	cloudName, ok := interact.FindMatch(cloud, clouds)
    56  	if !ok {
    57  		// should be impossible
    58  		return "", errors.Errorf("invalid cloud name chosen: %s", cloud)
    59  	}
    60  
    61  	return cloudName, nil
    62  }
    63  
    64  // queryRegion asks the user to pick a region of the ones passed in. The first
    65  // region in the list will be the default.
    66  func queryRegion(cloud string, regions []jujucloud.Region, scanner *bufio.Scanner, w io.Writer) (string, error) {
    67  	fmt.Fprintf(w, "Regions in %s:\n", cloud)
    68  	names := jujucloud.RegionNames(regions)
    69  	// add an empty string to allow for a default value. Also gives us an extra
    70  	// line return after the list of names.
    71  	names = append(names, "")
    72  	if _, err := fmt.Fprintln(w, strings.Join(names, "\n")); err != nil {
    73  		return "", errors.Trace(err)
    74  	}
    75  	verify := interact.MatchOptions(names, errors.Errorf("Invalid region."))
    76  	defaultRegion := regions[0].Name
    77  	query := fmt.Sprintf("Select a region in %s [%s]: ", cloud, defaultRegion)
    78  	region, err := interact.QueryVerify([]byte(query), scanner, w, verify)
    79  	if err != nil {
    80  		return "", errors.Trace(err)
    81  	}
    82  	if region == "" {
    83  		return defaultRegion, nil
    84  	}
    85  	regionName, ok := interact.FindMatch(region, names)
    86  	if !ok {
    87  		// should be impossible
    88  		return "", errors.Errorf("invalid region name chosen: %s", region)
    89  	}
    90  
    91  	return regionName, nil
    92  }
    93  
    94  func defaultControllerName(username, cloudname, region string, cloud *jujucloud.Cloud) string {
    95  	name := cloudname
    96  	if len(cloud.Regions) > 1 {
    97  		name = region
    98  	}
    99  	if username == "" {
   100  		return name
   101  	}
   102  	return username + "-" + name
   103  }
   104  
   105  func queryName(defName string, scanner *bufio.Scanner, w io.Writer) (string, error) {
   106  	query := fmt.Sprintf("Enter a name for the Controller [%s]: ", defName)
   107  	name, err := interact.QueryVerify([]byte(query), scanner, w, nil)
   108  	if err != nil {
   109  		return "", errors.Trace(err)
   110  	}
   111  	if name == "" {
   112  		return defName, nil
   113  	}
   114  	return name, nil
   115  }
   116  
   117  func sortClouds(maps ...map[string]jujucloud.Cloud) []string {
   118  	var clouds []string
   119  	for _, m := range maps {
   120  		for name := range m {
   121  			clouds = append(clouds, name)
   122  		}
   123  	}
   124  	sort.Strings(clouds)
   125  	return clouds
   126  }