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