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
|
// Copyright 2013 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package environs
import (
"bytes"
"crypto/rand"
"fmt"
"io"
"text/template"
)
var configHeader = `## This is the Juju config file, which you can use to specify multiple environments in which to deploy.
## By default Juju ships AWS (default), HP Cloud, OpenStack.
## See https://juju.ubuntu.com/docs for more information
## An environment configuration must always specify at least the following information:
##
## - name (to identify the environment)
## - type (to specify the provider)
## - admin-secret (an arbitrary "password" identifying an client with administrative-level access to system state)
## Values in <brackets> below need to be filled in by the user.
## The default environment is chosen when one is not specified using either:
## -e, --environment command line parameter
## JUJU_ENV environment variable
## If both -e and JUJU_ENV are specified, the command line parameter has precedence.
default: amazon
environments:
`
func randomKey() string {
buf := make([]byte, 16)
_, err := io.ReadFull(rand.Reader, buf)
if err != nil {
panic(fmt.Errorf("error from crypto rand: %v", err))
}
return fmt.Sprintf("%x", buf)
}
// BoilerplateConfig returns a sample juju configuration.
func BoilerplateConfig() string {
var config bytes.Buffer
config.WriteString(configHeader)
for name, p := range providers {
t, err := parseTemplate(p.BoilerplateConfig())
if err != nil {
panic(fmt.Errorf("cannot parse boilerplate from %s: %v", name, err))
}
var ecfg bytes.Buffer
if err := t.Execute(&ecfg, nil); err != nil {
panic(fmt.Errorf("cannot generate boilerplate from %s: %v", name, err))
}
indent(&config, ecfg.Bytes(), " ")
}
// Sanity check to ensure the boilerplate parses.
_, err := ReadEnvironsBytes(config.Bytes())
if err != nil {
panic(fmt.Errorf("cannot parse %s:\n%v", config.String(), err))
}
return config.String()
}
func parseTemplate(s string) (*template.Template, error) {
t := template.New("")
t.Funcs(template.FuncMap{"rand": randomKey})
return t.Parse(s)
}
// indent appends the given text to the given buffer indented by the given indent string.
func indent(b *bytes.Buffer, text []byte, indentStr string) {
for {
if len(text) == 0 {
return
}
b.WriteString(indentStr)
i := bytes.IndexByte(text, '\n')
if i == -1 {
b.Write(text)
b.WriteRune('\n')
return
}
i++
b.Write(text[0:i])
text = text[i:]
}
}
|