github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/provider/ec2/config.go (about)

     1  // Copyright 2011, 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package ec2
     5  
     6  import (
     7  	"fmt"
     8  
     9  	"github.com/juju/schema"
    10  	"gopkg.in/amz.v3/aws"
    11  	"gopkg.in/juju/environschema.v1"
    12  
    13  	"github.com/juju/juju/environs/config"
    14  )
    15  
    16  const boilerplateConfig = `
    17  # https://juju.ubuntu.com/docs/config-aws.html
    18  amazon:
    19      type: ec2
    20  
    21      # region specifies the EC2 region. It defaults to us-east-1.
    22      #
    23      # region: us-east-1
    24  
    25      # access-key holds the EC2 access key. It defaults to the
    26      # environment variable AWS_ACCESS_KEY_ID.
    27      #
    28      # access-key: <secret>
    29  
    30      # secret-key holds the EC2 secret key. It defaults to the
    31      # environment variable AWS_SECRET_ACCESS_KEY.
    32      #
    33      # secret-key: <secret>
    34  
    35      # image-stream chooses a simplestreams stream from which to select
    36      # OS images, for example daily or released images (or any other stream
    37      # available on simplestreams).
    38      #
    39      # image-stream: "released"
    40  
    41      # agent-stream chooses a simplestreams stream from which to select tools,
    42      # for example released or proposed tools (or any other stream available
    43      # on simplestreams).
    44      #
    45      # agent-stream: "released"
    46  
    47      # Whether or not to refresh the list of available updates for an
    48      # OS. The default option of true is recommended for use in
    49      # production systems, but disabling this can speed up local
    50      # deployments for development or testing.
    51      #
    52      # enable-os-refresh-update: true
    53  
    54      # Whether or not to perform OS upgrades when machines are
    55      # provisioned. The default option of true is recommended for use
    56      # in production systems, but disabling this can speed up local
    57      # deployments for development or testing.
    58      #
    59      # enable-os-upgrade: true
    60  
    61  `
    62  
    63  var configSchema = environschema.Fields{
    64  	"access-key": {
    65  		Description: "The EC2 access key",
    66  		EnvVar:      "AWS_ACCESS_KEY_ID",
    67  		Type:        environschema.Tstring,
    68  		Mandatory:   true,
    69  		Group:       environschema.AccountGroup,
    70  	},
    71  	"secret-key": {
    72  		Description: "The EC2 secret key",
    73  		EnvVar:      "AWS_SECRET_ACCESS_KEY",
    74  		Type:        environschema.Tstring,
    75  		Mandatory:   true,
    76  		Secret:      true,
    77  		Group:       environschema.AccountGroup,
    78  	},
    79  	"region": {
    80  		Description: "The EC2 region to use",
    81  		Type:        environschema.Tstring,
    82  	},
    83  	"control-bucket": {
    84  		Description: "The S3 bucket used to store environment metadata",
    85  		Type:        environschema.Tstring,
    86  	},
    87  }
    88  
    89  var configFields = func() schema.Fields {
    90  	fs, _, err := configSchema.ValidationSchema()
    91  	if err != nil {
    92  		panic(err)
    93  	}
    94  	return fs
    95  }()
    96  
    97  var configDefaults = schema.Defaults{
    98  	"access-key":     "",
    99  	"secret-key":     "",
   100  	"region":         "us-east-1",
   101  	"control-bucket": "",
   102  }
   103  
   104  type environConfig struct {
   105  	*config.Config
   106  	attrs map[string]interface{}
   107  }
   108  
   109  func (c *environConfig) region() string {
   110  	return c.attrs["region"].(string)
   111  }
   112  
   113  func (c *environConfig) controlBucket() string {
   114  	return c.attrs["control-bucket"].(string)
   115  }
   116  
   117  func (c *environConfig) accessKey() string {
   118  	return c.attrs["access-key"].(string)
   119  }
   120  
   121  func (c *environConfig) secretKey() string {
   122  	return c.attrs["secret-key"].(string)
   123  }
   124  
   125  func (p environProvider) newConfig(cfg *config.Config) (*environConfig, error) {
   126  	valid, err := p.Validate(cfg, nil)
   127  	if err != nil {
   128  		return nil, err
   129  	}
   130  	return &environConfig{valid, valid.UnknownAttrs()}, nil
   131  }
   132  
   133  // Schema returns the configuration schema for an environment.
   134  func (environProvider) Schema() environschema.Fields {
   135  	fields, err := config.Schema(configSchema)
   136  	if err != nil {
   137  		panic(err)
   138  	}
   139  	return fields
   140  }
   141  
   142  func validateConfig(cfg, old *config.Config) (*environConfig, error) {
   143  	// Check for valid changes for the base config values.
   144  	if err := config.Validate(cfg, old); err != nil {
   145  		return nil, err
   146  	}
   147  	validated, err := cfg.ValidateUnknownAttrs(configFields, configDefaults)
   148  	if err != nil {
   149  		return nil, err
   150  	}
   151  
   152  	// Add EC2 specific defaults.
   153  	providerDefaults := make(map[string]interface{})
   154  
   155  	// Storage.
   156  	if _, ok := cfg.StorageDefaultBlockSource(); !ok {
   157  		providerDefaults[config.StorageDefaultBlockSourceKey] = EBS_ProviderType
   158  	}
   159  	if len(providerDefaults) > 0 {
   160  		if cfg, err = cfg.Apply(providerDefaults); err != nil {
   161  			return nil, err
   162  		}
   163  	}
   164  	ecfg := &environConfig{cfg, validated}
   165  
   166  	if ecfg.accessKey() == "" || ecfg.secretKey() == "" {
   167  		auth, err := aws.EnvAuth()
   168  		if err != nil || ecfg.accessKey() != "" || ecfg.secretKey() != "" {
   169  			return nil, fmt.Errorf("environment has no access-key or secret-key")
   170  		}
   171  		ecfg.attrs["access-key"] = auth.AccessKey
   172  		ecfg.attrs["secret-key"] = auth.SecretKey
   173  	}
   174  	if _, ok := aws.Regions[ecfg.region()]; !ok {
   175  		return nil, fmt.Errorf("invalid region name %q", ecfg.region())
   176  	}
   177  
   178  	if old != nil {
   179  		attrs := old.UnknownAttrs()
   180  		if region, _ := attrs["region"].(string); ecfg.region() != region {
   181  			return nil, fmt.Errorf("cannot change region from %q to %q", region, ecfg.region())
   182  		}
   183  		if bucket, _ := attrs["control-bucket"].(string); ecfg.controlBucket() != bucket {
   184  			return nil, fmt.Errorf("cannot change control-bucket from %q to %q", bucket, ecfg.controlBucket())
   185  		}
   186  	}
   187  
   188  	// ssl-hostname-verification cannot be disabled
   189  	if !ecfg.SSLHostnameVerification() {
   190  		return nil, fmt.Errorf("disabling ssh-hostname-verification is not supported")
   191  	}
   192  	return ecfg, nil
   193  }