5
"launchpad.net/goamz/aws"
6
amzec2 "launchpad.net/goamz/ec2"
7
"launchpad.net/goamz/ec2/ec2test"
8
"launchpad.net/goamz/s3"
9
"launchpad.net/goamz/s3/s3test"
10
. "launchpad.net/gocheck"
11
"launchpad.net/goyaml"
12
"launchpad.net/juju-core/constraints"
13
"launchpad.net/juju-core/environs"
14
"launchpad.net/juju-core/environs/ec2"
15
"launchpad.net/juju-core/environs/jujutest"
16
envtesting "launchpad.net/juju-core/environs/testing"
17
"launchpad.net/juju-core/state"
18
"launchpad.net/juju-core/testing"
19
"launchpad.net/juju-core/utils"
23
type ProviderSuite struct{}
25
var _ = Suite(&ProviderSuite{})
27
var testImagesContent = []jujutest.FileContent{{
28
Name: "/query/precise/server/released.current.txt",
30
"precise\tserver\trelease\t20121017\tebs\tamd64\ttest\tami-20800c10\taki-98e26fa8\t\tparavirtual\n" +
31
"precise\tserver\trelease\t20121017\tebs\ti386\ttest\tami-00000034\tparavirtual\n",
33
Name: "/query/quantal/server/released.current.txt",
35
"quantal\tserver\trelease\t20121017\tebs\tamd64\ttest\tami-40f97070\taki-98e26fa8\t\tparavirtual\n" +
36
"quantal\tserver\trelease\t20121017\tebs\ti386\ttest\tami-01000034\taki-98e26fa8\t\tparavirtual\n",
38
Name: "/query/raring/server/released.current.txt",
40
"raring\tserver\trelease\t20121017\tebs\tamd64\ttest\tami-40f97070\taki-98e26fa8\t\tparavirtual\n" +
41
"raring\tserver\trelease\t20121017\tebs\ti386\ttest\tami-40f97070\taki-98e26fa8\t\tparavirtual\n",
44
// testInstanceTypeContent holds the cost in USDe-3/hour for each of the
45
// few available instance types in the convenient fictional "test" region.
46
var testInstanceTypeContent = map[string]uint64{
54
func (s *ProviderSuite) TestMetadata(c *C) {
55
metadataContent := []jujutest.FileContent{
56
{"/2011-01-01/meta-data/instance-id", "dummy.instance.id"},
57
{"/2011-01-01/meta-data/public-hostname", "public.dummy.address.invalid"},
58
{"/2011-01-01/meta-data/local-hostname", "private.dummy.address.invalid"},
60
ec2.UseTestMetadata(metadataContent)
61
defer ec2.UseTestMetadata(nil)
63
p, err := environs.Provider("ec2")
66
addr, err := p.PublicAddress()
68
c.Assert(addr, Equals, "public.dummy.address.invalid")
70
addr, err = p.PrivateAddress()
72
c.Assert(addr, Equals, "private.dummy.address.invalid")
74
id, err := p.InstanceId()
76
c.Assert(id, Equals, state.InstanceId("dummy.instance.id"))
79
func registerLocalTests() {
80
// N.B. Make sure the region we use here
81
// has entries in the images/query txt files.
82
aws.Regions["test"] = aws.Region{
85
attrs := map[string]interface{}{
89
"control-bucket": "test-bucket",
90
"public-bucket": "public-tools",
91
"public-bucket-region": "test",
92
"admin-secret": "local-secret",
95
"authorized-keys": "foo",
96
"ca-cert": testing.CACert,
97
"ca-private-key": testing.CAKey,
100
Suite(&localServerSuite{
101
Tests: jujutest.Tests{
102
TestConfig: jujutest.TestConfig{attrs},
105
Suite(&localLiveSuite{
106
LiveTests: LiveTests{
107
LiveTests: jujutest.LiveTests{
108
TestConfig: jujutest.TestConfig{attrs},
112
Suite(&localNonUSEastSuite{
113
tests: jujutest.Tests{
114
TestConfig: jujutest.TestConfig{attrs},
117
config: &s3test.Config{
118
Send409Conflict: true,
124
// localLiveSuite runs tests from LiveTests using a fake
125
// EC2 server that runs within the test process itself.
126
type localLiveSuite struct {
133
func (t *localLiveSuite) SetUpSuite(c *C) {
134
t.LoggingSuite.SetUpSuite(c)
135
ec2.UseTestImageData(testImagesContent)
136
ec2.UseTestInstanceTypeData(testInstanceTypeContent)
138
t.LiveTests.SetUpSuite(c)
139
t.env = t.LiveTests.Env
140
ec2.ShortTimeouts(true)
143
func (t *localLiveSuite) TearDownSuite(c *C) {
144
t.LiveTests.TearDownSuite(c)
147
ec2.ShortTimeouts(false)
148
ec2.UseTestImageData(nil)
149
ec2.UseTestInstanceTypeData(nil)
150
t.LoggingSuite.TearDownSuite(c)
153
func (t *localLiveSuite) SetUpTest(c *C) {
154
t.LoggingSuite.SetUpTest(c)
155
t.LiveTests.SetUpTest(c)
158
func (t *localLiveSuite) TearDownTest(c *C) {
159
t.LiveTests.TearDownTest(c)
160
t.LoggingSuite.TearDownTest(c)
163
// localServer represents a fake EC2 server running within
164
// the test process itself.
165
type localServer struct {
166
ec2srv *ec2test.Server
168
config *s3test.Config
171
func (srv *localServer) startServer(c *C) {
173
srv.ec2srv, err = ec2test.NewServer()
175
c.Fatalf("cannot start ec2 test server: %v", err)
177
srv.s3srv, err = s3test.NewServer(srv.config)
179
c.Fatalf("cannot start s3 test server: %v", err)
181
aws.Regions["test"] = aws.Region{
183
EC2Endpoint: srv.ec2srv.URL(),
184
S3Endpoint: srv.s3srv.URL(),
185
S3LocationConstraint: true,
187
s3inst := s3.New(aws.Auth{}, aws.Regions["test"])
188
writeablePublicStorage := ec2.BucketStorage(s3inst.Bucket("public-tools"))
189
envtesting.UploadFakeTools(c, writeablePublicStorage)
193
// addSpice adds some "spice" to the local server
194
// by adding state that may cause tests to fail.
195
func (srv *localServer) addSpice(c *C) {
196
states := []amzec2.InstanceState{
197
ec2test.ShuttingDown,
201
for _, state := range states {
202
srv.ec2srv.NewInstances(1, "m1.small", "ami-a7f539ce", state, nil)
206
func (srv *localServer) stopServer(c *C) {
209
// Clear out the region because the server address is
211
delete(aws.Regions, "test")
214
// localServerSuite contains tests that run against a fake EC2 server
215
// running within the test process itself. These tests can test things that
216
// would be unreasonably slow or expensive to test on a live Amazon server.
217
// It starts a new local ec2test server for each test. The server is
218
// accessed by using the "test" region, which is changed to point to the
219
// network address of the local server.
220
type localServerSuite struct {
227
func (t *localServerSuite) SetUpSuite(c *C) {
228
t.LoggingSuite.SetUpSuite(c)
229
ec2.UseTestImageData(testImagesContent)
230
ec2.UseTestInstanceTypeData(testInstanceTypeContent)
231
t.Tests.SetUpSuite(c)
232
ec2.ShortTimeouts(true)
235
func (t *localServerSuite) TearDownSuite(c *C) {
236
t.Tests.TearDownSuite(c)
237
ec2.ShortTimeouts(false)
238
ec2.UseTestImageData(nil)
239
ec2.UseTestInstanceTypeData(nil)
240
t.LoggingSuite.TearDownSuite(c)
243
func (t *localServerSuite) SetUpTest(c *C) {
244
t.LoggingSuite.SetUpTest(c)
250
func (t *localServerSuite) TearDownTest(c *C) {
251
t.Tests.TearDownTest(c)
253
t.LoggingSuite.TearDownTest(c)
256
func (t *localServerSuite) TestBootstrapInstanceUserDataAndState(c *C) {
257
policy := t.env.AssignmentPolicy()
258
c.Assert(policy, Equals, state.AssignNew)
260
envtesting.UploadFakeTools(c, t.env.Storage())
261
err := environs.Bootstrap(t.env, constraints.Value{})
264
// check that the state holds the id of the bootstrap machine.
265
bootstrapState, err := ec2.LoadState(t.env)
267
c.Assert(bootstrapState.StateInstances, HasLen, 1)
269
insts, err := t.env.Instances(bootstrapState.StateInstances)
271
c.Assert(insts, HasLen, 1)
272
c.Check(insts[0].Id(), Equals, bootstrapState.StateInstances[0])
274
info, apiInfo, err := t.env.StateInfo()
276
c.Assert(info, NotNil)
278
// check that the user data is configured to start zookeeper
279
// and the machine and provisioning agents.
280
inst := t.srv.ec2srv.Instance(string(insts[0].Id()))
281
c.Assert(inst, NotNil)
282
bootstrapDNS, err := insts[0].DNSName()
284
c.Assert(bootstrapDNS, Not(Equals), "")
286
userData, err := utils.Gunzip(inst.UserData)
288
c.Logf("first instance: UserData: %q", userData)
289
var x map[interface{}]interface{}
290
err = goyaml.Unmarshal(userData, &x)
292
CheckPackage(c, x, "git", true)
293
CheckScripts(c, x, "jujud bootstrap-state", true)
294
// TODO check for provisioning agent
295
// TODO check for machine agent
297
// check that a new instance will be started without
298
// zookeeper, with a machine agent, and without a
299
// provisioning agent.
300
series := t.env.Config().DefaultSeries()
301
info.Tag = "machine-1"
302
apiInfo.Tag = "machine-1"
303
inst1, err := t.env.StartInstance("1", "fake_nonce", series, constraints.Value{}, info, apiInfo)
305
inst = t.srv.ec2srv.Instance(string(inst1.Id()))
306
c.Assert(inst, NotNil)
307
userData, err = utils.Gunzip(inst.UserData)
309
c.Logf("second instance: UserData: %q", userData)
311
err = goyaml.Unmarshal(userData, &x)
313
CheckPackage(c, x, "zookeeperd", false)
314
// TODO check for provisioning agent
315
// TODO check for machine agent
317
err = t.env.Destroy(append(insts, inst1))
320
_, err = ec2.LoadState(t.env)
321
c.Assert(err, NotNil)
324
// If match is true, CheckScripts checks that at least one script started
325
// by the cloudinit data matches the given regexp pattern, otherwise it
326
// checks that no script matches. It's exported so it can be used by tests
327
// defined in ec2_test.
328
func CheckScripts(c *C, x map[interface{}]interface{}, pattern string, match bool) {
329
scripts0 := x["runcmd"]
331
c.Errorf("cloudinit has no entry for runcmd")
334
scripts := scripts0.([]interface{})
335
re := regexp.MustCompile(pattern)
337
for _, s0 := range scripts {
339
if re.MatchString(s) {
344
case match && !found:
345
c.Errorf("script %q not found in %q", pattern, scripts)
346
case !match && found:
347
c.Errorf("script %q found but not expected in %q", pattern, scripts)
351
// CheckPackage checks that the cloudinit will or won't install the given
352
// package, depending on the value of match. It's exported so it can be
353
// used by tests defined outside the ec2 package.
354
func CheckPackage(c *C, x map[interface{}]interface{}, pkg string, match bool) {
355
pkgs0 := x["packages"]
358
c.Errorf("cloudinit has no entry for packages")
363
pkgs := pkgs0.([]interface{})
366
for _, p0 := range pkgs {
373
case match && !found:
374
c.Errorf("package %q not found in %v", pkg, pkgs)
375
case !match && found:
376
c.Errorf("%q found but not expected in %v", pkg, pkgs)
380
// localNonUSEastSuite is similar to localServerSuite but the S3 mock server
382
type localNonUSEastSuite struct {
389
func (t *localNonUSEastSuite) SetUpSuite(c *C) {
390
t.LoggingSuite.SetUpSuite(c)
391
ec2.UseTestImageData(testImagesContent)
392
ec2.UseTestInstanceTypeData(testInstanceTypeContent)
393
t.tests.SetUpSuite(c)
394
ec2.ShortTimeouts(true)
397
func (t *localNonUSEastSuite) TearDownSuite(c *C) {
398
ec2.ShortTimeouts(false)
399
ec2.UseTestImageData(nil)
400
ec2.UseTestInstanceTypeData(nil)
401
t.LoggingSuite.TearDownSuite(c)
404
func (t *localNonUSEastSuite) SetUpTest(c *C) {
405
t.LoggingSuite.SetUpTest(c)
411
func (t *localNonUSEastSuite) TearDownTest(c *C) {
412
t.tests.TearDownTest(c)
414
t.LoggingSuite.TearDownTest(c)
417
func (t *localNonUSEastSuite) TestPutBucket(c *C) {
418
p := ec2.WritablePublicStorage(t.env).(ec2.Storage)
419
for i := 0; i < 5; i++ {
422
err := p.Put("test-file", &buf, 0)