github.com/Pankov404/juju@v0.0.0-20150703034450-be266991dceb/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  }