github.com/altoros/juju-vmware@v0.0.0-20150312064031-f19ae857ccca/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 "github.com/juju/juju/environs/config" 14 ) 15 16 var configHeader = ` 17 # This is the Juju config file, which you can use to specify multiple 18 # environments in which to deploy. By default Juju ships with AWS 19 # (default), HP Cloud, OpenStack, Azure, MaaS, Local and Manual 20 # providers. See https://juju.ubuntu.com/docs for more information 21 22 # An environment configuration must always specify at least the 23 # following information: 24 # - name (to identify the environment) 25 # - type (to specify the provider) 26 # In the following example the name is "myenv" and type is "ec2". 27 # myenv: 28 # type: ec2 29 30 # Values in <brackets> below need to be filled in by the user. 31 # Optional attributes are shown commented out, with 32 # a sample value or a value in <brackets>. 33 34 # There are several settings supported by all environments, all of which 35 # are optional and have specified default values. For more info, see the 36 # Juju documentation. 37 38 # The default environment is chosen when an environment is not 39 # specified using any of the following, in descending order of precedence: 40 # 1. -e or --environment command line parameter, passed after the command, e.g. 41 # $ juju add-unit -e myenv myservice 42 # 2. By setting JUJU_ENV environment variable. 43 # 3. Using the juju switch command like this: 44 # $ juju switch myenv 45 # 46 47 # You can control how Juju harvests machines by using the 48 # {{.ProvisionerHarvestKey}} setting. Harvesting is a process wherein 49 # Juju attempts to reclaim unused machines. 50 # 51 # Options are: 52 # 53 # Don't harvest any machines. 54 # {{.ProvisionerHarvestKey}}: none 55 # 56 # Only harvest machines that Juju knows about and are dead. 57 # {{.ProvisionerHarvestKey}}: destroyed 58 # 59 # Only harvest machines that Juju doesn't know about. 60 # {{.ProvisionerHarvestKey}}: unknown 61 # 62 # Harvest both dead and unknown machines. 63 # {{.ProvisionerHarvestKey}}: all 64 65 default: amazon 66 67 environments: 68 `[1:] 69 70 func init() { 71 72 type headerVars struct { 73 ProvisionerHarvestKey string 74 } 75 76 configBuff := new(bytes.Buffer) 77 configHeaderTmpl := template.Must(template.New("config header").Parse(configHeader)) 78 if err := configHeaderTmpl.Execute(configBuff, headerVars{ 79 ProvisionerHarvestKey: config.ProvisionerHarvestModeKey, 80 }); err != nil { 81 panic(fmt.Sprintf("error building config header: %v", err)) 82 } 83 configHeader = configBuff.String() 84 } 85 86 func randomKey() string { 87 buf := make([]byte, 16) 88 _, err := io.ReadFull(rand.Reader, buf) 89 if err != nil { 90 panic(fmt.Errorf("error from crypto rand: %v", err)) 91 } 92 return fmt.Sprintf("%x", buf) 93 } 94 95 // BoilerplateConfig returns a sample juju configuration. 96 func BoilerplateConfig() string { 97 configBuff := new(bytes.Buffer) 98 99 configBuff.WriteString(configHeader) 100 for name, p := range providers { 101 t, err := parseTemplate(p.BoilerplateConfig()) 102 if err != nil { 103 panic(fmt.Errorf("cannot parse boilerplate from %s: %v", name, err)) 104 } 105 var ecfg bytes.Buffer 106 if err := t.Execute(&ecfg, nil); err != nil { 107 panic(fmt.Errorf("cannot generate boilerplate from %s: %v", name, err)) 108 } 109 indent(configBuff, ecfg.Bytes(), " ") 110 } 111 112 // Sanity check to ensure the boilerplate parses. 113 _, err := ReadEnvironsBytes(configBuff.Bytes()) 114 if err != nil { 115 panic(fmt.Errorf("cannot parse %s:\n%v", configBuff.String(), err)) 116 } 117 return configBuff.String() 118 } 119 120 func parseTemplate(s string) (*template.Template, error) { 121 t := template.New("") 122 t.Funcs(template.FuncMap{"rand": randomKey}) 123 return t.Parse(s) 124 } 125 126 // indent appends the given text to the given buffer indented by the given indent string. 127 func indent(b *bytes.Buffer, text []byte, indentStr string) { 128 for { 129 if len(text) == 0 { 130 return 131 } 132 b.WriteString(indentStr) 133 i := bytes.IndexByte(text, '\n') 134 if i == -1 { 135 b.Write(text) 136 b.WriteRune('\n') 137 return 138 } 139 i++ 140 b.Write(text[0:i]) 141 text = text[i:] 142 } 143 }