github.com/rogpeppe/juju@v0.0.0-20140613142852-6337964b789e/environs/boilerplate_config.go (about) 1 // Copyright 2013 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package environs 5 6 import ( 7 "bytes" 8 "crypto/rand" 9 "fmt" 10 "io" 11 "text/template" 12 ) 13 14 var configHeader = ` 15 # This is the Juju config file, which you can use to specify multiple 16 # environments in which to deploy. By default Juju ships with AWS 17 # (default), HP Cloud, OpenStack, Azure, MaaS, Local and Manual 18 # providers. See https://juju.ubuntu.com/docs for more information 19 20 # An environment configuration must always specify at least the 21 # following information: 22 # - name (to identify the environment) 23 # - type (to specify the provider) 24 # In the following example the name is "myenv" and type is "ec2". 25 # myenv: 26 # type: ec2 27 28 # Values in <brackets> below need to be filled in by the user. 29 # Optional attributes are shown commented out, with 30 # a sample value or a value in <brackets>. 31 32 # There are several settings supported by all environments, all of which 33 # are optional and have specified default values. For more info, see the 34 # Juju documentation. 35 36 # The default environment is chosen when an environment is not 37 # specified using any of the following, in descending order of precedence: 38 # 1. -e or --environment command line parameter, passed after the command, e.g. 39 # $ juju add-unit -e myenv myservice 40 # 2. By setting JUJU_ENV environment variable. 41 # 3. Using the juju switch command like this: 42 # $ juju switch myenv 43 # 44 45 default: amazon 46 47 environments: 48 `[1:] 49 50 func randomKey() string { 51 buf := make([]byte, 16) 52 _, err := io.ReadFull(rand.Reader, buf) 53 if err != nil { 54 panic(fmt.Errorf("error from crypto rand: %v", err)) 55 } 56 return fmt.Sprintf("%x", buf) 57 } 58 59 // BoilerplateConfig returns a sample juju configuration. 60 func BoilerplateConfig() string { 61 var config bytes.Buffer 62 63 config.WriteString(configHeader) 64 for name, p := range providers { 65 t, err := parseTemplate(p.BoilerplateConfig()) 66 if err != nil { 67 panic(fmt.Errorf("cannot parse boilerplate from %s: %v", name, err)) 68 } 69 var ecfg bytes.Buffer 70 if err := t.Execute(&ecfg, nil); err != nil { 71 panic(fmt.Errorf("cannot generate boilerplate from %s: %v", name, err)) 72 } 73 indent(&config, ecfg.Bytes(), " ") 74 } 75 76 // Sanity check to ensure the boilerplate parses. 77 _, err := ReadEnvironsBytes(config.Bytes()) 78 if err != nil { 79 panic(fmt.Errorf("cannot parse %s:\n%v", config.String(), err)) 80 } 81 return config.String() 82 } 83 84 func parseTemplate(s string) (*template.Template, error) { 85 t := template.New("") 86 t.Funcs(template.FuncMap{"rand": randomKey}) 87 return t.Parse(s) 88 } 89 90 // indent appends the given text to the given buffer indented by the given indent string. 91 func indent(b *bytes.Buffer, text []byte, indentStr string) { 92 for { 93 if len(text) == 0 { 94 return 95 } 96 b.WriteString(indentStr) 97 i := bytes.IndexByte(text, '\n') 98 if i == -1 { 99 b.Write(text) 100 b.WriteRune('\n') 101 return 102 } 103 i++ 104 b.Write(text[0:i]) 105 text = text[i:] 106 } 107 }