launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/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  	"launchpad.net/goamz/aws"
    15  	gc "launchpad.net/gocheck"
    16  
    17  	"launchpad.net/juju-core/environs"
    18  	"launchpad.net/juju-core/environs/config"
    19  	"launchpad.net/juju-core/juju/osenv"
    20  	"launchpad.net/juju-core/testing"
    21  	"launchpad.net/juju-core/testing/testbase"
    22  )
    23  
    24  // Use local suite since this file lives in the ec2 package
    25  // for testing internals.
    26  type ConfigSuite struct {
    27  	testbase.LoggingSuite
    28  	savedHome, savedAccessKey, savedSecretKey string
    29  }
    30  
    31  var _ = gc.Suite(&ConfigSuite{})
    32  
    33  var configTestRegion = aws.Region{
    34  	Name:        "configtest",
    35  	EC2Endpoint: "testregion.nowhere:1234",
    36  }
    37  
    38  var testAuth = aws.Auth{"gopher", "long teeth"}
    39  
    40  // configTest specifies a config parsing test, checking that env when
    41  // parsed as the ec2 section of a config file matches baseConfigResult
    42  // when mutated by the mutate function, or that the parse matches the
    43  // given error.
    44  type configTest struct {
    45  	config        map[string]interface{}
    46  	change        map[string]interface{}
    47  	expect        map[string]interface{}
    48  	region        string
    49  	cbucket       string
    50  	pbucket       string
    51  	pbucketRegion string
    52  	accessKey     string
    53  	secretKey     string
    54  	firewallMode  string
    55  	err           string
    56  }
    57  
    58  type attrs map[string]interface{}
    59  
    60  func (t configTest) check(c *gc.C) {
    61  	attrs := testing.FakeConfig().Merge(testing.Attrs{
    62  		"type":           "ec2",
    63  		"control-bucket": "x",
    64  	}).Merge(t.config)
    65  	cfg, err := config.New(config.NoDefaults, attrs)
    66  	c.Assert(err, gc.IsNil)
    67  	e, err := environs.New(cfg)
    68  	if t.change != nil {
    69  		c.Assert(err, gc.IsNil)
    70  
    71  		// Testing a change in configuration.
    72  		var old, changed, valid *config.Config
    73  		ec2env := e.(*environ)
    74  		old = ec2env.ecfg().Config
    75  		changed, err = old.Apply(t.change)
    76  		c.Assert(err, gc.IsNil)
    77  
    78  		// Keep err for validation below.
    79  		valid, err = providerInstance.Validate(changed, old)
    80  		if err == nil {
    81  			err = ec2env.SetConfig(valid)
    82  		}
    83  	}
    84  	if t.err != "" {
    85  		c.Check(err, gc.ErrorMatches, t.err)
    86  		return
    87  	}
    88  	c.Assert(err, gc.IsNil)
    89  
    90  	ecfg := e.(*environ).ecfg()
    91  	c.Assert(ecfg.Name(), gc.Equals, "testenv")
    92  	c.Assert(ecfg.controlBucket(), gc.Equals, "x")
    93  	if t.region != "" {
    94  		c.Assert(ecfg.region(), gc.Equals, t.region)
    95  	}
    96  	if t.accessKey != "" {
    97  		c.Assert(ecfg.accessKey(), gc.Equals, t.accessKey)
    98  		c.Assert(ecfg.secretKey(), gc.Equals, t.secretKey)
    99  		expected := map[string]string{
   100  			"access-key": t.accessKey,
   101  			"secret-key": t.secretKey,
   102  		}
   103  		c.Assert(err, gc.IsNil)
   104  		actual, err := e.Provider().SecretAttrs(ecfg.Config)
   105  		c.Assert(err, gc.IsNil)
   106  		c.Assert(expected, gc.DeepEquals, actual)
   107  	} else {
   108  		c.Assert(ecfg.accessKey(), gc.DeepEquals, testAuth.AccessKey)
   109  		c.Assert(ecfg.secretKey(), gc.DeepEquals, testAuth.SecretKey)
   110  	}
   111  	if t.firewallMode != "" {
   112  		c.Assert(ecfg.FirewallMode(), gc.Equals, t.firewallMode)
   113  	}
   114  	for name, expect := range t.expect {
   115  		actual, found := ecfg.UnknownAttrs()[name]
   116  		c.Check(found, gc.Equals, true)
   117  		c.Check(actual, gc.Equals, expect)
   118  	}
   119  
   120  	// check storage bucket is configured correctly
   121  	env := e.(*environ)
   122  	c.Assert(env.Storage().(*ec2storage).bucket.Region.Name, gc.Equals, ecfg.region())
   123  }
   124  
   125  var configTests = []configTest{
   126  	{
   127  		config: attrs{},
   128  	}, {
   129  		// check that region defaults to us-east-1
   130  		config: attrs{},
   131  		region: "us-east-1",
   132  	}, {
   133  		config: attrs{
   134  			"region": "eu-west-1",
   135  		},
   136  		region: "eu-west-1",
   137  	}, {
   138  		config: attrs{
   139  			"region": "unknown",
   140  		},
   141  		err: ".*invalid region name.*",
   142  	}, {
   143  		config: attrs{
   144  			"region": "configtest",
   145  		},
   146  		region: "configtest",
   147  	}, {
   148  		config: attrs{
   149  			"region": "configtest",
   150  		},
   151  		change: attrs{
   152  			"region": "us-east-1",
   153  		},
   154  		err: `cannot change region from "configtest" to "us-east-1"`,
   155  	}, {
   156  		config: attrs{
   157  			"region": 666,
   158  		},
   159  		err: `.*expected string, got int\(666\)`,
   160  	}, {
   161  		config: attrs{
   162  			"access-key": 666,
   163  		},
   164  		err: `.*expected string, got int\(666\)`,
   165  	}, {
   166  		config: attrs{
   167  			"secret-key": 666,
   168  		},
   169  		err: `.*expected string, got int\(666\)`,
   170  	}, {
   171  		config: attrs{
   172  			"control-bucket": 666,
   173  		},
   174  		err: `.*expected string, got int\(666\)`,
   175  	}, {
   176  		change: attrs{
   177  			"control-bucket": "new-x",
   178  		},
   179  		err: `cannot change control-bucket from "x" to "new-x"`,
   180  	}, {
   181  		config: attrs{
   182  			"access-key": "jujuer",
   183  			"secret-key": "open sesame",
   184  		},
   185  		accessKey: "jujuer",
   186  		secretKey: "open sesame",
   187  	}, {
   188  		config: attrs{
   189  			"access-key": "jujuer",
   190  		},
   191  		err: ".*environment has no access-key or secret-key",
   192  	}, {
   193  		config: attrs{
   194  			"secret-key": "badness",
   195  		},
   196  		err: ".*environment has no access-key or secret-key",
   197  	}, {
   198  		config: attrs{
   199  			"admin-secret": "Futumpsh",
   200  		},
   201  	}, {
   202  		config:       attrs{},
   203  		firewallMode: config.FwInstance,
   204  	}, {
   205  		config: attrs{
   206  			"firewall-mode": "instance",
   207  		},
   208  		firewallMode: config.FwInstance,
   209  	}, {
   210  		config: attrs{
   211  			"firewall-mode": "global",
   212  		},
   213  		firewallMode: config.FwGlobal,
   214  	}, {
   215  		config: attrs{
   216  			"ssl-hostname-verification": false,
   217  		},
   218  		err: "disabling ssh-hostname-verification is not supported",
   219  	}, {
   220  		config: attrs{
   221  			"future": "hammerstein",
   222  		},
   223  		expect: attrs{
   224  			"future": "hammerstein",
   225  		},
   226  	}, {
   227  		change: attrs{
   228  			"future": "hammerstein",
   229  		},
   230  		expect: attrs{
   231  			"future": "hammerstein",
   232  		},
   233  	},
   234  }
   235  
   236  func indent(s string, with string) string {
   237  	var r string
   238  	lines := strings.Split(s, "\n")
   239  	for _, l := range lines {
   240  		r += with + l + "\n"
   241  	}
   242  	return r
   243  }
   244  
   245  func (s *ConfigSuite) SetUpTest(c *gc.C) {
   246  	s.LoggingSuite.SetUpTest(c)
   247  	s.savedHome = osenv.Home()
   248  	s.savedAccessKey = os.Getenv("AWS_ACCESS_KEY_ID")
   249  	s.savedSecretKey = os.Getenv("AWS_SECRET_ACCESS_KEY")
   250  
   251  	home := c.MkDir()
   252  	sshDir := filepath.Join(home, ".ssh")
   253  	err := os.Mkdir(sshDir, 0777)
   254  	c.Assert(err, gc.IsNil)
   255  	err = ioutil.WriteFile(filepath.Join(sshDir, "id_rsa.pub"), []byte("sshkey\n"), 0666)
   256  	c.Assert(err, gc.IsNil)
   257  
   258  	osenv.SetHome(home)
   259  	os.Setenv("AWS_ACCESS_KEY_ID", testAuth.AccessKey)
   260  	os.Setenv("AWS_SECRET_ACCESS_KEY", testAuth.SecretKey)
   261  	aws.Regions["configtest"] = configTestRegion
   262  }
   263  
   264  func (s *ConfigSuite) TearDownTest(c *gc.C) {
   265  	osenv.SetHome(s.savedHome)
   266  	os.Setenv("AWS_ACCESS_KEY_ID", s.savedAccessKey)
   267  	os.Setenv("AWS_SECRET_ACCESS_KEY", s.savedSecretKey)
   268  	delete(aws.Regions, "configtest")
   269  	s.LoggingSuite.TearDownTest(c)
   270  }
   271  
   272  func (s *ConfigSuite) TestConfig(c *gc.C) {
   273  	for i, t := range configTests {
   274  		c.Logf("test %d: %v", i, t.config)
   275  		t.check(c)
   276  	}
   277  }
   278  
   279  func (s *ConfigSuite) TestMissingAuth(c *gc.C) {
   280  	os.Setenv("AWS_ACCESS_KEY_ID", "")
   281  	os.Setenv("AWS_SECRET_ACCESS_KEY", "")
   282  	// Since r37 goamz uses these as fallbacks, so unset them too.
   283  	os.Setenv("EC2_ACCESS_KEY", "")
   284  	os.Setenv("EC2_SECRET_KEY", "")
   285  	test := configTests[0]
   286  	test.err = "environment has no access-key or secret-key"
   287  	test.check(c)
   288  }
   289  
   290  func (s *ConfigSuite) TestPrepareInsertsUniqueControlBucket(c *gc.C) {
   291  	attrs := testing.FakeConfig().Merge(testing.Attrs{
   292  		"type": "ec2",
   293  	})
   294  	cfg, err := config.New(config.NoDefaults, attrs)
   295  	c.Assert(err, gc.IsNil)
   296  
   297  	env0, err := providerInstance.Prepare(cfg)
   298  	c.Assert(err, gc.IsNil)
   299  	bucket0 := env0.(*environ).ecfg().controlBucket()
   300  	c.Assert(bucket0, gc.Matches, "[a-f0-9]{32}")
   301  
   302  	env1, err := providerInstance.Prepare(cfg)
   303  	c.Assert(err, gc.IsNil)
   304  	bucket1 := env1.(*environ).ecfg().controlBucket()
   305  	c.Assert(bucket1, gc.Matches, "[a-f0-9]{32}")
   306  
   307  	c.Assert(bucket1, gc.Not(gc.Equals), bucket0)
   308  }
   309  
   310  func (s *ConfigSuite) TestPrepareDoesNotTouchExistingControlBucket(c *gc.C) {
   311  	attrs := testing.FakeConfig().Merge(testing.Attrs{
   312  		"type":           "ec2",
   313  		"control-bucket": "burblefoo",
   314  	})
   315  	cfg, err := config.New(config.NoDefaults, attrs)
   316  	c.Assert(err, gc.IsNil)
   317  
   318  	env, err := providerInstance.Prepare(cfg)
   319  	c.Assert(err, gc.IsNil)
   320  	bucket := env.(*environ).ecfg().controlBucket()
   321  	c.Assert(bucket, gc.Equals, "burblefoo")
   322  }