launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/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 environments in which to deploy. 16 # By default Juju ships AWS (default), HP Cloud, OpenStack. 17 # See https://juju.ubuntu.com/docs for more information 18 19 # An environment configuration must always specify at least the following information: 20 # 21 # - name (to identify the environment) 22 # - type (to specify the provider) 23 24 # Values in <brackets> below need to be filled in by the user. 25 # Optional attributes are shown commented out, with 26 # a sample value or a value in <brackets>. 27 28 # The default environment is chosen when an environment is not 29 # specified using any of the following, in descending order of precedence: 30 # -e or --environment command line parameter. 31 # JUJU_ENV environment variable. 32 # the juju switch command. 33 default: amazon 34 35 environments: 36 `[1:] 37 38 func randomKey() string { 39 buf := make([]byte, 16) 40 _, err := io.ReadFull(rand.Reader, buf) 41 if err != nil { 42 panic(fmt.Errorf("error from crypto rand: %v", err)) 43 } 44 return fmt.Sprintf("%x", buf) 45 } 46 47 // BoilerplateConfig returns a sample juju configuration. 48 func BoilerplateConfig() string { 49 var config bytes.Buffer 50 51 config.WriteString(configHeader) 52 for name, p := range providers { 53 t, err := parseTemplate(p.BoilerplateConfig()) 54 if err != nil { 55 panic(fmt.Errorf("cannot parse boilerplate from %s: %v", name, err)) 56 } 57 var ecfg bytes.Buffer 58 if err := t.Execute(&ecfg, nil); err != nil { 59 panic(fmt.Errorf("cannot generate boilerplate from %s: %v", name, err)) 60 } 61 indent(&config, ecfg.Bytes(), " ") 62 } 63 64 // Sanity check to ensure the boilerplate parses. 65 _, err := ReadEnvironsBytes(config.Bytes()) 66 if err != nil { 67 panic(fmt.Errorf("cannot parse %s:\n%v", config.String(), err)) 68 } 69 return config.String() 70 } 71 72 func parseTemplate(s string) (*template.Template, error) { 73 t := template.New("") 74 t.Funcs(template.FuncMap{"rand": randomKey}) 75 return t.Parse(s) 76 } 77 78 // indent appends the given text to the given buffer indented by the given indent string. 79 func indent(b *bytes.Buffer, text []byte, indentStr string) { 80 for { 81 if len(text) == 0 { 82 return 83 } 84 b.WriteString(indentStr) 85 i := bytes.IndexByte(text, '\n') 86 if i == -1 { 87 b.Write(text) 88 b.WriteRune('\n') 89 return 90 } 91 i++ 92 b.Write(text[0:i]) 93 text = text[i:] 94 } 95 }