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  }