-
Notifications
You must be signed in to change notification settings - Fork 491
/
bootstrap_interactive.go
132 lines (113 loc) · 3.43 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
123
124
125
126
127
128
129
130
131
132
// 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"
"github.com/juju/names/v5"
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)
}
builtin, err := common.BuiltInClouds()
if err != nil {
return nil, errors.Trace(err)
}
return sortClouds(public, builtin, 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, "Invalid cloud.")
query := fmt.Sprintf("Select a cloud [%s]: ", defCloud)
cloud, err := interact.QueryVerify(query, scanner, w, w, verify)
if err != nil {
return "", errors.Trace(err)
}
if cloud == "" {
return defCloud, nil
}
if ok := names.IsValidCloud(cloud); !ok {
return "", errors.NotValidf("cloud name %q", cloud)
}
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, "Invalid region.")
defaultRegion := regions[0].Name
query := fmt.Sprintf("Select a region in %s [%s]: ", cloud, defaultRegion)
region, err := interact.QueryVerify(query, scanner, w, 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(query, scanner, w, 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
}