github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/provider/ec2/config_test.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  // TODO: Clean this up so it matches environs/openstack/config_test.go.
     7  
     8  import (
     9  	"io/ioutil"
    10  	"os"
    11  	"path/filepath"
    12  	"strings"
    13  
    14  	jc "github.com/juju/testing/checkers"
    15  	"github.com/juju/utils"
    16  	"gopkg.in/amz.v3/aws"
    17  	gc "gopkg.in/check.v1"
    18  
    19  	"github.com/juju/juju/environs"
    20  	"github.com/juju/juju/environs/config"
    21  	envtesting "github.com/juju/juju/environs/testing"
    22  	"github.com/juju/juju/testing"
    23  )
    24  
    25  // Use local suite since this file lives in the ec2 package
    26  // for testing internals.
    27  type ConfigSuite struct {
    28  	testing.BaseSuite
    29  	savedHome, savedAccessKey, savedSecretKey string
    30  }
    31  
    32  var _ = gc.Suite(&ConfigSuite{})
    33  
    34  var configTestRegion = aws.Region{
    35  	Name:        "configtest",
    36  	EC2Endpoint: "testregion.nowhere:1234",
    37  }
    38  
    39  var testAuth = aws.Auth{"gopher", "long teeth"}
    40  
    41  // configTest specifies a config parsing test, checking that env when
    42  // parsed as the ec2 section of a config file matches baseConfigResult
    43  // when mutated by the mutate function, or that the parse matches the
    44  // given error.
    45  type configTest struct {
    46  	config             map[string]interface{}
    47  	change             map[string]interface{}
    48  	expect             map[string]interface{}
    49  	region             string
    50  	cbucket            string
    51  	pbucket            string
    52  	pbucketRegion      string
    53  	accessKey          string
    54  	secretKey          string
    55  	firewallMode       string
    56  	blockStorageSource string
    57  	err                string
    58  }
    59  
    60  type attrs map[string]interface{}
    61  
    62  func (t configTest) check(c *gc.C) {
    63  	attrs := testing.FakeConfig().Merge(testing.Attrs{
    64  		"type":           "ec2",
    65  		"control-bucket": "x",
    66  	}).Merge(t.config)
    67  	cfg, err := config.New(config.NoDefaults, attrs)
    68  	c.Assert(err, jc.ErrorIsNil)
    69  	e, err := environs.New(cfg)
    70  	if t.change != nil {
    71  		c.Assert(err, jc.ErrorIsNil)
    72  
    73  		// Testing a change in configuration.
    74  		var old, changed, valid *config.Config
    75  		ec2env := e.(*environ)
    76  		old = ec2env.ecfg().Config
    77  		changed, err = old.Apply(t.change)
    78  		c.Assert(err, jc.ErrorIsNil)
    79  
    80  		// Keep err for validation below.
    81  		valid, err = providerInstance.Validate(changed, old)
    82  		if err == nil {
    83  			err = ec2env.SetConfig(valid)
    84  		}
    85  	}
    86  	if t.err != "" {
    87  		c.Check(err, gc.ErrorMatches, t.err)
    88  		return
    89  	}
    90  	c.Assert(err, jc.ErrorIsNil)
    91  
    92  	ecfg := e.(*environ).ecfg()
    93  	c.Assert(ecfg.Name(), gc.Equals, "testenv")
    94  	c.Assert(ecfg.controlBucket(), gc.Equals, "x")
    95  	if t.region != "" {
    96  		c.Assert(ecfg.region(), gc.Equals, t.region)
    97  	}
    98  	if t.accessKey != "" {
    99  		c.Assert(ecfg.accessKey(), gc.Equals, t.accessKey)
   100  		c.Assert(ecfg.secretKey(), gc.Equals, t.secretKey)
   101  		expected := map[string]string{
   102  			"access-key": t.accessKey,
   103  			"secret-key": t.secretKey,
   104  		}
   105  		c.Assert(err, jc.ErrorIsNil)
   106  		actual, err := e.Provider().SecretAttrs(ecfg.Config)
   107  		c.Assert(err, jc.ErrorIsNil)
   108  		c.Assert(expected, gc.DeepEquals, actual)
   109  	} else {
   110  		c.Assert(ecfg.accessKey(), gc.DeepEquals, testAuth.AccessKey)
   111  		c.Assert(ecfg.secretKey(), gc.DeepEquals, testAuth.SecretKey)
   112  	}
   113  	if t.firewallMode != "" {
   114  		c.Assert(ecfg.FirewallMode(), gc.Equals, t.firewallMode)
   115  	}
   116  	for name, expect := range t.expect {
   117  		actual, found := ecfg.UnknownAttrs()[name]
   118  		c.Check(found, jc.IsTrue)
   119  		c.Check(actual, gc.Equals, expect)
   120  	}
   121  
   122  	// check storage bucket is configured correctly
   123  	env := e.(*environ)
   124  	c.Assert(env.Storage().(*ec2storage).bucket.Region.Name, gc.Equals, ecfg.region())
   125  
   126  	expectedStorage := "ebs"
   127  	if t.blockStorageSource != "" {
   128  		expectedStorage = t.blockStorageSource
   129  	}
   130  	storage, ok := ecfg.StorageDefaultBlockSource()
   131  	c.Assert(ok, jc.IsTrue)
   132  	c.Assert(storage, gc.Equals, expectedStorage)
   133  }
   134  
   135  var configTests = []configTest{
   136  	{
   137  		config: attrs{},
   138  	}, {
   139  		// check that region defaults to us-east-1
   140  		config: attrs{},
   141  		region: "us-east-1",
   142  	}, {
   143  		config: attrs{
   144  			"region": "eu-west-1",
   145  		},
   146  		region: "eu-west-1",
   147  	}, {
   148  		config: attrs{
   149  			"region": "unknown",
   150  		},
   151  		err: ".*invalid region name.*",
   152  	}, {
   153  		config: attrs{
   154  			"region": "configtest",
   155  		},
   156  		region: "configtest",
   157  	}, {
   158  		config: attrs{
   159  			"region": "configtest",
   160  		},
   161  		change: attrs{
   162  			"region": "us-east-1",
   163  		},
   164  		err: `.*cannot change region from "configtest" to "us-east-1"`,
   165  	}, {
   166  		config: attrs{
   167  			"region": 666,
   168  		},
   169  		err: `.*expected string, got int\(666\)`,
   170  	}, {
   171  		config: attrs{
   172  			"access-key": 666,
   173  		},
   174  		err: `.*expected string, got int\(666\)`,
   175  	}, {
   176  		config: attrs{
   177  			"secret-key": 666,
   178  		},
   179  		err: `.*expected string, got int\(666\)`,
   180  	}, {
   181  		config: attrs{
   182  			"control-bucket": 666,
   183  		},
   184  		err: `.*expected string, got int\(666\)`,
   185  	}, {
   186  		change: attrs{
   187  			"control-bucket": "new-x",
   188  		},
   189  		err: `.*cannot change control-bucket from "x" to "new-x"`,
   190  	}, {
   191  		config: attrs{
   192  			"access-key": "jujuer",
   193  			"secret-key": "open sesame",
   194  		},
   195  		accessKey: "jujuer",
   196  		secretKey: "open sesame",
   197  	}, {
   198  		config: attrs{
   199  			"access-key": "jujuer",
   200  		},
   201  		err: ".*environment has no access-key or secret-key",
   202  	}, {
   203  		config: attrs{
   204  			"secret-key": "badness",
   205  		},
   206  		err: ".*environment has no access-key or secret-key",
   207  	}, {
   208  		config: attrs{
   209  			"admin-secret": "Futumpsh",
   210  		},
   211  	}, {
   212  		config:       attrs{},
   213  		firewallMode: config.FwInstance,
   214  	}, {
   215  		config:             attrs{},
   216  		blockStorageSource: "ebs",
   217  	}, {
   218  		config: attrs{
   219  			"storage-default-block-source": "ebs-fast",
   220  		},
   221  		blockStorageSource: "ebs-fast",
   222  	}, {
   223  		config: attrs{
   224  			"firewall-mode": "instance",
   225  		},
   226  		firewallMode: config.FwInstance,
   227  	}, {
   228  		config: attrs{
   229  			"firewall-mode": "global",
   230  		},
   231  		firewallMode: config.FwGlobal,
   232  	}, {
   233  		config: attrs{
   234  			"firewall-mode": "none",
   235  		},
   236  		firewallMode: config.FwNone,
   237  	}, {
   238  		config: attrs{
   239  			"ssl-hostname-verification": false,
   240  		},
   241  		err: ".*disabling ssh-hostname-verification is not supported",
   242  	}, {
   243  		config: attrs{
   244  			"future": "hammerstein",
   245  		},
   246  		expect: attrs{
   247  			"future": "hammerstein",
   248  		},
   249  	}, {
   250  		change: attrs{
   251  			"future": "hammerstein",
   252  		},
   253  		expect: attrs{
   254  			"future": "hammerstein",
   255  		},
   256  	},
   257  }
   258  
   259  func indent(s string, with string) string {
   260  	var r string
   261  	lines := strings.Split(s, "\n")
   262  	for _, l := range lines {
   263  		r += with + l + "\n"
   264  	}
   265  	return r
   266  }
   267  
   268  func (s *ConfigSuite) SetUpTest(c *gc.C) {
   269  	s.BaseSuite.SetUpTest(c)
   270  	s.savedHome = utils.Home()
   271  	s.savedAccessKey = os.Getenv("AWS_ACCESS_KEY_ID")
   272  	s.savedSecretKey = os.Getenv("AWS_SECRET_ACCESS_KEY")
   273  
   274  	home := c.MkDir()
   275  	sshDir := filepath.Join(home, ".ssh")
   276  	err := os.Mkdir(sshDir, 0777)
   277  	c.Assert(err, jc.ErrorIsNil)
   278  	err = ioutil.WriteFile(filepath.Join(sshDir, "id_rsa.pub"), []byte("sshkey\n"), 0666)
   279  	c.Assert(err, jc.ErrorIsNil)
   280  
   281  	utils.SetHome(home)
   282  	os.Setenv("AWS_ACCESS_KEY_ID", testAuth.AccessKey)
   283  	os.Setenv("AWS_SECRET_ACCESS_KEY", testAuth.SecretKey)
   284  	aws.Regions["configtest"] = configTestRegion
   285  }
   286  
   287  func (s *ConfigSuite) TearDownTest(c *gc.C) {
   288  	utils.SetHome(s.savedHome)
   289  	os.Setenv("AWS_ACCESS_KEY_ID", s.savedAccessKey)
   290  	os.Setenv("AWS_SECRET_ACCESS_KEY", s.savedSecretKey)
   291  	delete(aws.Regions, "configtest")
   292  	s.BaseSuite.TearDownTest(c)
   293  }
   294  
   295  func (s *ConfigSuite) TestConfig(c *gc.C) {
   296  	for i, t := range configTests {
   297  		c.Logf("test %d: %v", i, t.config)
   298  		t.check(c)
   299  	}
   300  }
   301  
   302  func (s *ConfigSuite) TestMissingAuth(c *gc.C) {
   303  	os.Setenv("AWS_ACCESS_KEY_ID", "")
   304  	os.Setenv("AWS_SECRET_ACCESS_KEY", "")
   305  
   306  	// Since PR #52 amz.v3 uses these AWS_ vars as fallbacks, if set.
   307  	os.Setenv("AWS_ACCESS_KEY", "")
   308  	os.Setenv("AWS_SECRET_KEY", "")
   309  
   310  	// Since LP r37 goamz uses also these EC2_ as fallbacks, so unset them too.
   311  	os.Setenv("EC2_ACCESS_KEY", "")
   312  	os.Setenv("EC2_SECRET_KEY", "")
   313  	test := configTests[0]
   314  	test.err = ".*environment has no access-key or secret-key"
   315  	test.check(c)
   316  }
   317  
   318  func (s *ConfigSuite) TestPrepareForCreateInsertsUniqueControlBucket(c *gc.C) {
   319  	s.PatchValue(&verifyCredentials, func(*environ) error { return nil })
   320  	attrs := testing.FakeConfig().Merge(testing.Attrs{
   321  		"type": "ec2",
   322  	})
   323  	cfg, err := config.New(config.NoDefaults, attrs)
   324  	c.Assert(err, jc.ErrorIsNil)
   325  
   326  	cfg1, err := providerInstance.PrepareForCreateEnvironment(cfg)
   327  	c.Assert(err, jc.ErrorIsNil)
   328  
   329  	bucket1 := cfg1.UnknownAttrs()["control-bucket"]
   330  	c.Assert(bucket1, gc.Matches, "[a-f0-9]{32}")
   331  
   332  	cfg2, err := providerInstance.PrepareForCreateEnvironment(cfg)
   333  	c.Assert(err, jc.ErrorIsNil)
   334  	bucket2 := cfg2.UnknownAttrs()["control-bucket"]
   335  	c.Assert(bucket2, gc.Matches, "[a-f0-9]{32}")
   336  
   337  	c.Assert(bucket1, gc.Not(gc.Equals), bucket2)
   338  }
   339  
   340  func (s *ConfigSuite) TestPrepareInsertsUniqueControlBucket(c *gc.C) {
   341  	s.PatchValue(&verifyCredentials, func(*environ) error { return nil })
   342  	attrs := testing.FakeConfig().Merge(testing.Attrs{
   343  		"type": "ec2",
   344  	})
   345  	cfg, err := config.New(config.NoDefaults, attrs)
   346  	c.Assert(err, jc.ErrorIsNil)
   347  
   348  	ctx := envtesting.BootstrapContext(c)
   349  	env0, err := providerInstance.PrepareForBootstrap(ctx, cfg)
   350  	c.Assert(err, jc.ErrorIsNil)
   351  	bucket0 := env0.(*environ).ecfg().controlBucket()
   352  	c.Assert(bucket0, gc.Matches, "[a-f0-9]{32}")
   353  
   354  	env1, err := providerInstance.PrepareForBootstrap(ctx, cfg)
   355  	c.Assert(err, jc.ErrorIsNil)
   356  	bucket1 := env1.(*environ).ecfg().controlBucket()
   357  	c.Assert(bucket1, gc.Matches, "[a-f0-9]{32}")
   358  
   359  	c.Assert(bucket1, gc.Not(gc.Equals), bucket0)
   360  }
   361  
   362  func (s *ConfigSuite) TestPrepareDoesNotTouchExistingControlBucket(c *gc.C) {
   363  	s.PatchValue(&verifyCredentials, func(*environ) error { return nil })
   364  	attrs := testing.FakeConfig().Merge(testing.Attrs{
   365  		"type":           "ec2",
   366  		"control-bucket": "burblefoo",
   367  	})
   368  	cfg, err := config.New(config.NoDefaults, attrs)
   369  	c.Assert(err, jc.ErrorIsNil)
   370  
   371  	env, err := providerInstance.PrepareForBootstrap(envtesting.BootstrapContext(c), cfg)
   372  	c.Assert(err, jc.ErrorIsNil)
   373  	bucket := env.(*environ).ecfg().controlBucket()
   374  	c.Assert(bucket, gc.Equals, "burblefoo")
   375  }
   376  
   377  func (s *ConfigSuite) TestPrepareSetsDefaultBlockSource(c *gc.C) {
   378  	s.PatchValue(&verifyCredentials, func(*environ) error { return nil })
   379  	attrs := testing.FakeConfig().Merge(testing.Attrs{
   380  		"type": "ec2",
   381  	})
   382  	cfg, err := config.New(config.NoDefaults, attrs)
   383  	c.Assert(err, jc.ErrorIsNil)
   384  
   385  	env, err := providerInstance.PrepareForBootstrap(envtesting.BootstrapContext(c), cfg)
   386  	c.Assert(err, jc.ErrorIsNil)
   387  	source, ok := env.(*environ).ecfg().StorageDefaultBlockSource()
   388  	c.Assert(ok, jc.IsTrue)
   389  	c.Assert(source, gc.Equals, "ebs")
   390  }
   391  
   392  func (*ConfigSuite) TestSchema(c *gc.C) {
   393  	fields := providerInstance.Schema()
   394  	// Check that all the fields defined in environs/config
   395  	// are in the returned schema.
   396  	globalFields, err := config.Schema(nil)
   397  	c.Assert(err, gc.IsNil)
   398  	for name, field := range globalFields {
   399  		c.Check(fields[name], jc.DeepEquals, field)
   400  	}
   401  }