launchpad.net/~rogpeppe/juju-core/500-errgo-fix@v0.0.0-20140213181702-000000002356/cmd/juju/bootstrap_test.go (about)

     1  // Copyright 2012, 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package main
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"strings"
    10  
    11  	gc "launchpad.net/gocheck"
    12  
    13  	"launchpad.net/juju-core/cmd"
    14  	"launchpad.net/juju-core/constraints"
    15  	"launchpad.net/juju-core/environs"
    16  	"launchpad.net/juju-core/environs/configstore"
    17  	"launchpad.net/juju-core/environs/filestorage"
    18  	"launchpad.net/juju-core/environs/imagemetadata"
    19  	imtesting "launchpad.net/juju-core/environs/imagemetadata/testing"
    20  	"launchpad.net/juju-core/environs/simplestreams"
    21  	"launchpad.net/juju-core/environs/storage"
    22  	"launchpad.net/juju-core/environs/sync"
    23  	envtesting "launchpad.net/juju-core/environs/testing"
    24  	envtools "launchpad.net/juju-core/environs/tools"
    25  	ttesting "launchpad.net/juju-core/environs/tools/testing"
    26  	"launchpad.net/juju-core/errors"
    27  	"launchpad.net/juju-core/provider/dummy"
    28  	coretesting "launchpad.net/juju-core/testing"
    29  	"launchpad.net/juju-core/testing/testbase"
    30  	coretools "launchpad.net/juju-core/tools"
    31  	"launchpad.net/juju-core/version"
    32  )
    33  
    34  type BootstrapSuite struct {
    35  	testbase.LoggingSuite
    36  	coretesting.MgoSuite
    37  	envtesting.ToolsFixture
    38  }
    39  
    40  var _ = gc.Suite(&BootstrapSuite{})
    41  
    42  func (s *BootstrapSuite) SetUpSuite(c *gc.C) {
    43  	s.LoggingSuite.SetUpSuite(c)
    44  	s.MgoSuite.SetUpSuite(c)
    45  }
    46  
    47  func (s *BootstrapSuite) SetUpTest(c *gc.C) {
    48  	s.LoggingSuite.SetUpTest(c)
    49  	s.MgoSuite.SetUpTest(c)
    50  	s.ToolsFixture.SetUpTest(c)
    51  
    52  	// Set up a local source with tools.
    53  	sourceDir := createToolsSource(c, vAll)
    54  	s.PatchValue(&envtools.DefaultBaseURL, sourceDir)
    55  }
    56  
    57  func (s *BootstrapSuite) TearDownSuite(c *gc.C) {
    58  	s.MgoSuite.TearDownSuite(c)
    59  	s.LoggingSuite.TearDownSuite(c)
    60  }
    61  
    62  func (s *BootstrapSuite) TearDownTest(c *gc.C) {
    63  	s.ToolsFixture.TearDownTest(c)
    64  	s.MgoSuite.TearDownTest(c)
    65  	s.LoggingSuite.TearDownTest(c)
    66  	dummy.Reset()
    67  }
    68  
    69  type bootstrapRetryTest struct {
    70  	info               string
    71  	args               []string
    72  	expectedAllowRetry []bool
    73  	err                string
    74  	// If version != "", version.Current will be
    75  	// set to it for the duration of the test.
    76  	version string
    77  	// If addVersionToSource is true, then "version"
    78  	// above will be populated in the tools source.
    79  	addVersionToSource bool
    80  }
    81  
    82  var bootstrapRetryTests = []bootstrapRetryTest{{
    83  	info:               "no tools uploaded, first check has no retries; no matching binary in source; sync fails with no second attempt",
    84  	expectedAllowRetry: []bool{false},
    85  	err:                "cannot find bootstrap tools: no matching tools available",
    86  	version:            "1.16.0-precise-amd64",
    87  }, {
    88  	info:               "no tools uploaded, first check has no retries; matching binary in source; check after sync has retries",
    89  	expectedAllowRetry: []bool{false, true},
    90  	err:                "cannot find bootstrap tools: tools not found",
    91  	version:            "1.16.0-precise-amd64",
    92  	addVersionToSource: true,
    93  }, {
    94  	info:               "no tools uploaded, first check has no retries; no matching binary in source; check after upload has retries",
    95  	expectedAllowRetry: []bool{false, true},
    96  	err:                "cannot find bootstrap tools: tools not found",
    97  	version:            "1.15.1-precise-amd64", // dev version to force upload
    98  }, {
    99  	info:               "new tools uploaded, so we want to allow retries to give them a chance at showing up",
   100  	args:               []string{"--upload-tools"},
   101  	expectedAllowRetry: []bool{true},
   102  	err:                "cannot find bootstrap tools: no matching tools available",
   103  }}
   104  
   105  // Test test checks that bootstrap calls FindTools with the expected allowRetry flag.
   106  func (s *BootstrapSuite) TestAllowRetries(c *gc.C) {
   107  	for i, test := range bootstrapRetryTests {
   108  		c.Logf("test %d: %s\n", i, test.info)
   109  		s.runAllowRetriesTest(c, test)
   110  	}
   111  }
   112  
   113  func (s *BootstrapSuite) runAllowRetriesTest(c *gc.C, test bootstrapRetryTest) {
   114  	toolsVersions := envtesting.VAll
   115  	if test.version != "" {
   116  		testVersion := version.MustParseBinary(test.version)
   117  		restore := testbase.PatchValue(&version.Current, testVersion)
   118  		defer restore()
   119  		if test.addVersionToSource {
   120  			toolsVersions = append([]version.Binary{}, toolsVersions...)
   121  			toolsVersions = append(toolsVersions, testVersion)
   122  		}
   123  	}
   124  	_, fake := makeEmptyFakeHome(c)
   125  	defer fake.Restore()
   126  	sourceDir := createToolsSource(c, toolsVersions)
   127  	s.PatchValue(&envtools.DefaultBaseURL, sourceDir)
   128  
   129  	var findToolsRetryValues []bool
   130  	mockFindTools := func(cloudInst environs.ConfigGetter, majorVersion, minorVersion int,
   131  		filter coretools.Filter, allowRetry bool) (list coretools.List, err error) {
   132  		findToolsRetryValues = append(findToolsRetryValues, allowRetry)
   133  		return nil, errors.NotFoundf("tools")
   134  	}
   135  
   136  	restore := envtools.TestingPatchBootstrapFindTools(mockFindTools)
   137  	defer restore()
   138  
   139  	_, errc := runCommand(nullContext(), new(BootstrapCommand), test.args...)
   140  	err := <-errc
   141  	c.Check(findToolsRetryValues, gc.DeepEquals, test.expectedAllowRetry)
   142  	c.Check(err, gc.ErrorMatches, test.err)
   143  }
   144  
   145  func (s *BootstrapSuite) TestTest(c *gc.C) {
   146  	s.PatchValue(&sync.Upload, mockUploadTools)
   147  	for i, test := range bootstrapTests {
   148  		c.Logf("\ntest %d: %s", i, test.info)
   149  		test.run(c)
   150  	}
   151  }
   152  
   153  type bootstrapTest struct {
   154  	info string
   155  	// binary version string used to set version.Current
   156  	version string
   157  	sync    bool
   158  	args    []string
   159  	err     string
   160  	// binary version strings for expected tools; if set, no default tools
   161  	// will be uploaded before running the test.
   162  	uploads     []string
   163  	constraints constraints.Value
   164  }
   165  
   166  func (test bootstrapTest) run(c *gc.C) {
   167  	// Create home with dummy provider and remove all
   168  	// of its envtools.
   169  	env, fake := makeEmptyFakeHome(c)
   170  	defer fake.Restore()
   171  
   172  	if test.version != "" {
   173  		origVersion := version.Current
   174  		version.Current = version.MustParseBinary(test.version)
   175  		defer func() { version.Current = origVersion }()
   176  	}
   177  
   178  	uploadCount := len(test.uploads)
   179  	if uploadCount == 0 {
   180  		usefulVersion := version.Current
   181  		usefulVersion.Series = env.Config().DefaultSeries()
   182  		envtesting.AssertUploadFakeToolsVersions(c, env.Storage(), usefulVersion)
   183  	}
   184  
   185  	// Run command and check for uploads.
   186  	opc, errc := runCommand(nullContext(), new(BootstrapCommand), test.args...)
   187  	if uploadCount > 0 {
   188  		for i := 0; i < uploadCount; i++ {
   189  			c.Check((<-opc).(dummy.OpPutFile).Env, gc.Equals, "peckham")
   190  		}
   191  		list, err := envtools.FindTools(
   192  			env, version.Current.Major, version.Current.Minor, coretools.Filter{}, envtools.DoNotAllowRetry)
   193  		c.Check(err, gc.IsNil)
   194  		c.Logf("found: " + list.String())
   195  		urls := list.URLs()
   196  		c.Check(urls, gc.HasLen, len(test.uploads))
   197  		for _, v := range test.uploads {
   198  			c.Logf("seeking: " + v)
   199  			vers := version.MustParseBinary(v)
   200  			_, found := urls[vers]
   201  			c.Check(found, gc.Equals, true)
   202  		}
   203  	}
   204  
   205  	// Check for remaining operations/errors.
   206  	if test.err != "" {
   207  		c.Check(<-errc, gc.ErrorMatches, test.err)
   208  		return
   209  	}
   210  	if !c.Check(<-errc, gc.IsNil) {
   211  		return
   212  	}
   213  	if len(test.uploads) > 0 {
   214  		indexFile := (<-opc).(dummy.OpPutFile)
   215  		c.Check(indexFile.FileName, gc.Equals, "tools/streams/v1/index.json")
   216  		productFile := (<-opc).(dummy.OpPutFile)
   217  		c.Check(productFile.FileName, gc.Equals, "tools/streams/v1/com.ubuntu.juju:released:tools.json")
   218  	}
   219  	opPutBootstrapVerifyFile := (<-opc).(dummy.OpPutFile)
   220  	c.Check(opPutBootstrapVerifyFile.Env, gc.Equals, "peckham")
   221  	c.Check(opPutBootstrapVerifyFile.FileName, gc.Equals, environs.VerificationFilename)
   222  
   223  	opPutBootstrapInitFile := (<-opc).(dummy.OpPutFile)
   224  	c.Check(opPutBootstrapInitFile.Env, gc.Equals, "peckham")
   225  	c.Check(opPutBootstrapInitFile.FileName, gc.Equals, "provider-state")
   226  
   227  	opBootstrap := (<-opc).(dummy.OpBootstrap)
   228  	c.Check(opBootstrap.Env, gc.Equals, "peckham")
   229  	c.Check(opBootstrap.Constraints, gc.DeepEquals, test.constraints)
   230  
   231  	store, err := configstore.Default()
   232  	c.Assert(err, gc.IsNil)
   233  	// Check a CA cert/key was generated by reloading the environment.
   234  	env, err = environs.NewFromName("peckham", store)
   235  	c.Assert(err, gc.IsNil)
   236  	_, hasCert := env.Config().CACert()
   237  	c.Check(hasCert, gc.Equals, true)
   238  	_, hasKey := env.Config().CAPrivateKey()
   239  	c.Check(hasKey, gc.Equals, true)
   240  }
   241  
   242  var bootstrapTests = []bootstrapTest{{
   243  	info: "no args, no error, no uploads, no constraints",
   244  }, {
   245  	info: "bad arg",
   246  	args: []string{"twiddle"},
   247  	err:  `unrecognized args: \["twiddle"\]`,
   248  }, {
   249  	info: "bad --constraints",
   250  	args: []string{"--constraints", "bad=wrong"},
   251  	err:  `invalid value "bad=wrong" for flag --constraints: unknown constraint "bad"`,
   252  }, {
   253  	info: "bad --series",
   254  	args: []string{"--series", "bad1"},
   255  	err:  `invalid value "bad1" for flag --series: invalid series name "bad1"`,
   256  }, {
   257  	info: "lonely --series",
   258  	args: []string{"--series", "fine"},
   259  	err:  `--series requires --upload-tools`,
   260  }, {
   261  	info:    "bad environment",
   262  	version: "1.2.3-precise-amd64",
   263  	args:    []string{"-e", "brokenenv"},
   264  	err:     `dummy.Bootstrap is broken`,
   265  }, {
   266  	info:        "constraints",
   267  	args:        []string{"--constraints", "mem=4G cpu-cores=4"},
   268  	constraints: constraints.MustParse("mem=4G cpu-cores=4"),
   269  }, {
   270  	info:    "--upload-tools picks all reasonable series",
   271  	version: "1.2.3-saucy-amd64",
   272  	args:    []string{"--upload-tools"},
   273  	uploads: []string{
   274  		"1.2.3.1-saucy-amd64",   // from version.Current
   275  		"1.2.3.1-raring-amd64",  // from env.Config().DefaultSeries()
   276  		"1.2.3.1-precise-amd64", // from environs/config.DefaultSeries
   277  	},
   278  }, {
   279  	info:    "--upload-tools only uploads each file once",
   280  	version: "1.2.3-precise-amd64",
   281  	args:    []string{"--upload-tools"},
   282  	uploads: []string{
   283  		"1.2.3.1-raring-amd64",
   284  		"1.2.3.1-precise-amd64",
   285  	},
   286  }, {
   287  	info:    "--upload-tools rejects invalid series",
   288  	version: "1.2.3-saucy-amd64",
   289  	args:    []string{"--upload-tools", "--series", "ping,ping,pong"},
   290  	err:     `invalid series "ping"`,
   291  }, {
   292  	info:    "--upload-tools always bumps build number",
   293  	version: "1.2.3.4-raring-amd64",
   294  	args:    []string{"--upload-tools"},
   295  	uploads: []string{
   296  		"1.2.3.5-raring-amd64",
   297  		"1.2.3.5-precise-amd64",
   298  	},
   299  }}
   300  
   301  func (s *BootstrapSuite) TestBootstrapTwice(c *gc.C) {
   302  	env, fake := makeEmptyFakeHome(c)
   303  	defer fake.Restore()
   304  	defaultSeriesVersion := version.Current
   305  	defaultSeriesVersion.Series = env.Config().DefaultSeries()
   306  
   307  	ctx := coretesting.Context(c)
   308  	code := cmd.Main(&BootstrapCommand{}, ctx, nil)
   309  	c.Check(code, gc.Equals, 0)
   310  
   311  	ctx2 := coretesting.Context(c)
   312  	code2 := cmd.Main(&BootstrapCommand{}, ctx2, nil)
   313  	c.Check(code2, gc.Equals, 1)
   314  	c.Check(coretesting.Stderr(ctx2), gc.Equals, "error: environment is already bootstrapped\n")
   315  	c.Check(coretesting.Stdout(ctx2), gc.Equals, "")
   316  }
   317  
   318  func (s *BootstrapSuite) TestInvalidLocalSource(c *gc.C) {
   319  	s.PatchValue(&version.Current.Number, version.MustParse("1.2.0"))
   320  	env, fake := makeEmptyFakeHome(c)
   321  	defer fake.Restore()
   322  
   323  	// Bootstrap the environment with an invalid source.
   324  	// The command returns with an error.
   325  	ctx := coretesting.Context(c)
   326  	code := cmd.Main(&BootstrapCommand{}, ctx, []string{"--metadata-source", c.MkDir()})
   327  	c.Check(code, gc.Equals, 1)
   328  
   329  	// Now check that there are no tools available.
   330  	_, err := envtools.FindTools(
   331  		env, version.Current.Major, version.Current.Minor, coretools.Filter{}, envtools.DoNotAllowRetry)
   332  	c.Assert(err, gc.FitsTypeOf, errors.NotFoundf(""))
   333  }
   334  
   335  // createImageMetadata creates some image metadata in a local directory.
   336  func createImageMetadata(c *gc.C) (string, []*imagemetadata.ImageMetadata) {
   337  	// Generate some image metadata.
   338  	im := []*imagemetadata.ImageMetadata{
   339  		{
   340  			Id:         "1234",
   341  			Arch:       "amd64",
   342  			Version:    "13.04",
   343  			RegionName: "region",
   344  			Endpoint:   "endpoint",
   345  		},
   346  	}
   347  	cloudSpec := &simplestreams.CloudSpec{
   348  		Region:   "region",
   349  		Endpoint: "endpoint",
   350  	}
   351  	sourceDir := c.MkDir()
   352  	sourceStor, err := filestorage.NewFileStorageWriter(sourceDir, filestorage.UseDefaultTmpDir)
   353  	c.Assert(err, gc.IsNil)
   354  	err = imagemetadata.MergeAndWriteMetadata("raring", im, cloudSpec, sourceStor)
   355  	c.Assert(err, gc.IsNil)
   356  	return sourceDir, im
   357  }
   358  
   359  // checkImageMetadata checks that the environment contains the expected image metadata.
   360  func checkImageMetadata(c *gc.C, stor storage.StorageReader, expected []*imagemetadata.ImageMetadata) {
   361  	metadata := imtesting.ParseMetadataFromStorage(c, stor)
   362  	c.Assert(metadata, gc.HasLen, 1)
   363  	c.Assert(expected[0], gc.DeepEquals, metadata[0])
   364  }
   365  
   366  func (s *BootstrapSuite) TestUploadLocalImageMetadata(c *gc.C) {
   367  	sourceDir, expected := createImageMetadata(c)
   368  	env, fake := makeEmptyFakeHome(c)
   369  	defer fake.Restore()
   370  
   371  	// Bootstrap the environment with the valid source.
   372  	ctx := coretesting.Context(c)
   373  	code := cmd.Main(&BootstrapCommand{}, ctx, []string{"--metadata-source", sourceDir})
   374  	c.Check(code, gc.Equals, 0)
   375  	c.Assert(imagemetadata.DefaultBaseURL, gc.Equals, imagemetadata.UbuntuCloudImagesURL)
   376  
   377  	// Now check the image metadata has been uploaded.
   378  	checkImageMetadata(c, env.Storage(), expected)
   379  }
   380  
   381  func (s *BootstrapSuite) TestAutoSyncLocalSource(c *gc.C) {
   382  	sourceDir := createToolsSource(c, vAll)
   383  	s.PatchValue(&version.Current.Number, version.MustParse("1.2.0"))
   384  	env, fake := makeEmptyFakeHome(c)
   385  	defer fake.Restore()
   386  
   387  	// Bootstrap the environment with the valid source.
   388  	// The bootstrapping has to show no error, because the tools
   389  	// are automatically synchronized.
   390  	ctx := coretesting.Context(c)
   391  	code := cmd.Main(&BootstrapCommand{}, ctx, []string{"--metadata-source", sourceDir})
   392  	c.Check(code, gc.Equals, 0)
   393  
   394  	// Now check the available tools which are the 1.2.0 envtools.
   395  	checkTools(c, env, v120All)
   396  }
   397  
   398  func (s *BootstrapSuite) setupAutoUploadTest(c *gc.C, vers, series string) environs.Environ {
   399  	s.PatchValue(&sync.Upload, mockUploadTools)
   400  	sourceDir := createToolsSource(c, vAll)
   401  	s.PatchValue(&envtools.DefaultBaseURL, sourceDir)
   402  
   403  	// Change the tools location to be the test location and also
   404  	// the version and ensure their later restoring.
   405  	// Set the current version to be something for which there are no tools
   406  	// so we can test that an upload is forced.
   407  	origVersion := version.Current
   408  	version.Current.Number = version.MustParse(vers)
   409  	version.Current.Series = series
   410  	s.AddCleanup(func(*gc.C) { version.Current = origVersion })
   411  
   412  	// Create home with dummy provider and remove all
   413  	// of its envtools.
   414  	env, fake := makeEmptyFakeHome(c)
   415  	s.AddCleanup(func(*gc.C) { fake.Restore() })
   416  	return env
   417  }
   418  
   419  func (s *BootstrapSuite) TestAutoUploadAfterFailedSync(c *gc.C) {
   420  	otherSeries := "precise"
   421  	if otherSeries == version.Current.Series {
   422  		otherSeries = "raring"
   423  	}
   424  	env := s.setupAutoUploadTest(c, "1.7.3", otherSeries)
   425  	// Run command and check for that upload has been run for tools matching the current juju version.
   426  	opc, errc := runCommand(nullContext(), new(BootstrapCommand))
   427  	c.Assert(<-errc, gc.IsNil)
   428  	c.Assert((<-opc).(dummy.OpPutFile).Env, gc.Equals, "peckham")
   429  	list, err := envtools.FindTools(env, version.Current.Major, version.Current.Minor, coretools.Filter{}, false)
   430  	c.Assert(err, gc.IsNil)
   431  	c.Logf("found: " + list.String())
   432  	urls := list.URLs()
   433  	c.Assert(urls, gc.HasLen, 2)
   434  	expectedVers := []version.Binary{
   435  		version.MustParseBinary(fmt.Sprintf("1.7.3.1-%s-%s", otherSeries, version.Current.Arch)),
   436  		version.MustParseBinary(fmt.Sprintf("1.7.3.1-%s-%s", version.Current.Series, version.Current.Arch)),
   437  	}
   438  	for _, vers := range expectedVers {
   439  		c.Logf("seeking: " + vers.String())
   440  		_, found := urls[vers]
   441  		c.Check(found, gc.Equals, true)
   442  	}
   443  }
   444  
   445  func (s *BootstrapSuite) TestAutoUploadOnlyForDev(c *gc.C) {
   446  	s.setupAutoUploadTest(c, "1.8.3", "precise")
   447  	_, errc := runCommand(nullContext(), new(BootstrapCommand))
   448  	err := <-errc
   449  	c.Assert(err, gc.ErrorMatches, "cannot find bootstrap tools: no matching tools available")
   450  }
   451  
   452  func (s *BootstrapSuite) TestMissingToolsError(c *gc.C) {
   453  	s.setupAutoUploadTest(c, "1.8.3", "precise")
   454  	context := coretesting.Context(c)
   455  	code := cmd.Main(&BootstrapCommand{}, context, nil)
   456  	c.Assert(code, gc.Equals, 1)
   457  	errText := context.Stderr.(*bytes.Buffer).String()
   458  	errText = strings.Replace(errText, "\n", "", -1)
   459  	expectedErrText := "error: cannot find bootstrap tools: no matching tools available"
   460  	c.Assert(errText, gc.Matches, expectedErrText)
   461  }
   462  
   463  func uploadToolsAlwaysFails(stor storage.Storage, forceVersion *version.Number, series ...string) (*coretools.Tools, error) {
   464  	return nil, fmt.Errorf("an error")
   465  }
   466  
   467  func (s *BootstrapSuite) TestMissingToolsUploadFailedError(c *gc.C) {
   468  	s.setupAutoUploadTest(c, "1.7.3", "precise")
   469  	s.PatchValue(&sync.Upload, uploadToolsAlwaysFails)
   470  	context := coretesting.Context(c)
   471  	code := cmd.Main(&BootstrapCommand{}, context, nil)
   472  	c.Assert(code, gc.Equals, 1)
   473  	errText := context.Stderr.(*bytes.Buffer).String()
   474  	errText = strings.Replace(errText, "\n", "", -1)
   475  	expectedErrText := "error: cannot find bootstrap tools: an error"
   476  	c.Assert(errText, gc.Matches, expectedErrText)
   477  }
   478  
   479  func (s *BootstrapSuite) TestBootstrapDestroy(c *gc.C) {
   480  	_, fake := makeEmptyFakeHome(c)
   481  	defer fake.Restore()
   482  	opc, errc := runCommand(nullContext(), new(BootstrapCommand), "-e", "brokenenv")
   483  	err := <-errc
   484  	c.Assert(err, gc.ErrorMatches, "dummy.Bootstrap is broken")
   485  	var opDestroy *dummy.OpDestroy
   486  	for opDestroy == nil {
   487  		select {
   488  		case op := <-opc:
   489  			switch op := op.(type) {
   490  			case dummy.OpDestroy:
   491  				opDestroy = &op
   492  			}
   493  		default:
   494  			c.Error("expected call to env.Destroy")
   495  			return
   496  		}
   497  	}
   498  	c.Assert(opDestroy.Error, gc.ErrorMatches, "dummy.Destroy is broken")
   499  }
   500  
   501  // createToolsSource writes the mock tools and metadata into a temporary
   502  // directory and returns it.
   503  func createToolsSource(c *gc.C, versions []version.Binary) string {
   504  	versionStrings := make([]string, len(versions))
   505  	for i, vers := range versions {
   506  		versionStrings[i] = vers.String()
   507  	}
   508  	source := c.MkDir()
   509  	ttesting.MakeTools(c, source, "releases", versionStrings)
   510  	return source
   511  }
   512  
   513  // makeEmptyFakeHome creates a faked home without envtools.
   514  func makeEmptyFakeHome(c *gc.C) (environs.Environ, *coretesting.FakeHome) {
   515  	fake := coretesting.MakeFakeHome(c, envConfig)
   516  	dummy.Reset()
   517  	store, err := configstore.Default()
   518  	c.Assert(err, gc.IsNil)
   519  	env, err := environs.PrepareFromName("peckham", store)
   520  	c.Assert(err, gc.IsNil)
   521  	envtesting.RemoveAllTools(c, env)
   522  	return env, fake
   523  }
   524  
   525  // checkTools check if the environment contains the passed envtools.
   526  func checkTools(c *gc.C, env environs.Environ, expected []version.Binary) {
   527  	list, err := envtools.FindTools(
   528  		env, version.Current.Major, version.Current.Minor, coretools.Filter{}, envtools.DoNotAllowRetry)
   529  	c.Check(err, gc.IsNil)
   530  	c.Logf("found: " + list.String())
   531  	urls := list.URLs()
   532  	c.Check(urls, gc.HasLen, len(expected))
   533  }
   534  
   535  var (
   536  	v100d64 = version.MustParseBinary("1.0.0-raring-amd64")
   537  	v100p64 = version.MustParseBinary("1.0.0-precise-amd64")
   538  	v100q32 = version.MustParseBinary("1.0.0-quantal-i386")
   539  	v100q64 = version.MustParseBinary("1.0.0-quantal-amd64")
   540  	v120d64 = version.MustParseBinary("1.2.0-raring-amd64")
   541  	v120p64 = version.MustParseBinary("1.2.0-precise-amd64")
   542  	v120q32 = version.MustParseBinary("1.2.0-quantal-i386")
   543  	v120q64 = version.MustParseBinary("1.2.0-quantal-amd64")
   544  	v190p32 = version.MustParseBinary("1.9.0-precise-i386")
   545  	v190q64 = version.MustParseBinary("1.9.0-quantal-amd64")
   546  	v200p64 = version.MustParseBinary("2.0.0-precise-amd64")
   547  	v100All = []version.Binary{
   548  		v100d64, v100p64, v100q64, v100q32,
   549  	}
   550  	v120All = []version.Binary{
   551  		v120d64, v120p64, v120q64, v120q32,
   552  	}
   553  	vAll = []version.Binary{
   554  		v100d64, v100p64, v100q32, v100q64,
   555  		v120d64, v120p64, v120q32, v120q64,
   556  		v190p32, v190q64,
   557  		v200p64,
   558  	}
   559  )