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  }