github.com/mattyw/juju@v0.0.0-20140610034352-732aecd63861/environs/manual/bootstrap_test.go (about)

     1  // Copyright 2013 Canonical Ltd.
     2  // Licensed under the AGPLv3, see LICENCE file for details.
     3  
     4  package manual_test
     5  
     6  import (
     7  	"fmt"
     8  	"io"
     9  	"os"
    10  
    11  	gc "launchpad.net/gocheck"
    12  
    13  	"github.com/juju/juju/environs"
    14  	"github.com/juju/juju/environs/bootstrap"
    15  	"github.com/juju/juju/environs/cloudinit"
    16  	"github.com/juju/juju/environs/filestorage"
    17  	"github.com/juju/juju/environs/manual"
    18  	"github.com/juju/juju/environs/storage"
    19  	"github.com/juju/juju/environs/tools"
    20  	"github.com/juju/juju/instance"
    21  	"github.com/juju/juju/juju/testing"
    22  	coretesting "github.com/juju/juju/testing"
    23  	"github.com/juju/juju/version"
    24  )
    25  
    26  type bootstrapSuite struct {
    27  	testing.JujuConnSuite
    28  	env *localStorageEnviron
    29  }
    30  
    31  var _ = gc.Suite(&bootstrapSuite{})
    32  
    33  type localStorageEnviron struct {
    34  	environs.Environ
    35  	storage     storage.Storage
    36  	storageAddr string
    37  	storageDir  string
    38  }
    39  
    40  func (e *localStorageEnviron) Storage() storage.Storage {
    41  	return e.storage
    42  }
    43  
    44  func (e *localStorageEnviron) StorageAddr() string {
    45  	return e.storageAddr
    46  }
    47  
    48  func (e *localStorageEnviron) StorageDir() string {
    49  	return e.storageDir
    50  }
    51  
    52  func (s *bootstrapSuite) SetUpTest(c *gc.C) {
    53  	s.JujuConnSuite.SetUpTest(c)
    54  	s.env = &localStorageEnviron{
    55  		Environ:    s.Conn.Environ,
    56  		storageDir: c.MkDir(),
    57  	}
    58  	storage, err := filestorage.NewFileStorageWriter(s.env.storageDir)
    59  	c.Assert(err, gc.IsNil)
    60  	s.env.storage = storage
    61  }
    62  
    63  func (s *bootstrapSuite) getArgs(c *gc.C) manual.BootstrapArgs {
    64  	hostname, err := os.Hostname()
    65  	c.Assert(err, gc.IsNil)
    66  	toolsList, err := tools.FindBootstrapTools(s.Conn.Environ, tools.BootstrapToolsParams{})
    67  	c.Assert(err, gc.IsNil)
    68  	arch := "amd64"
    69  	return manual.BootstrapArgs{
    70  		Host:          hostname,
    71  		DataDir:       "/var/lib/juju",
    72  		Environ:       s.env,
    73  		PossibleTools: toolsList,
    74  		Series:        "precise",
    75  		HardwareCharacteristics: &instance.HardwareCharacteristics{
    76  			Arch: &arch,
    77  		},
    78  		Context: coretesting.Context(c),
    79  	}
    80  }
    81  
    82  func (s *bootstrapSuite) TestBootstrap(c *gc.C) {
    83  	args := s.getArgs(c)
    84  	args.Host = "ubuntu@" + args.Host
    85  
    86  	defer fakeSSH{SkipDetection: true}.install(c).Restore()
    87  	err := manual.Bootstrap(args)
    88  	c.Assert(err, gc.IsNil)
    89  
    90  	bootstrapState, err := bootstrap.LoadState(s.env.Storage())
    91  	c.Assert(err, gc.IsNil)
    92  	c.Assert(
    93  		bootstrapState.StateInstances,
    94  		gc.DeepEquals,
    95  		[]instance.Id{manual.BootstrapInstanceId},
    96  	)
    97  
    98  	// Do it all again; this should work, despite the fact that
    99  	// there's a bootstrap state file. Existence for that is
   100  	// checked in general bootstrap code (environs/bootstrap).
   101  	defer fakeSSH{SkipDetection: true}.install(c).Restore()
   102  	err = manual.Bootstrap(args)
   103  	c.Assert(err, gc.IsNil)
   104  
   105  	// We *do* check that the machine has no juju* upstart jobs, though.
   106  	defer fakeSSH{
   107  		Provisioned:        true,
   108  		SkipDetection:      true,
   109  		SkipProvisionAgent: true,
   110  	}.install(c).Restore()
   111  	err = manual.Bootstrap(args)
   112  	c.Assert(err, gc.Equals, manual.ErrProvisioned)
   113  }
   114  
   115  func (s *bootstrapSuite) TestBootstrapScriptFailure(c *gc.C) {
   116  	args := s.getArgs(c)
   117  	args.Host = "ubuntu@" + args.Host
   118  	defer fakeSSH{SkipDetection: true, ProvisionAgentExitCode: 1}.install(c).Restore()
   119  	err := manual.Bootstrap(args)
   120  	c.Assert(err, gc.NotNil)
   121  
   122  	// Since the script failed, the state file should have been
   123  	// removed from storage.
   124  	_, err = bootstrap.LoadState(s.env.Storage())
   125  	c.Check(err, gc.Equals, environs.ErrNotBootstrapped)
   126  }
   127  
   128  func (s *bootstrapSuite) TestBootstrapEmptyDataDir(c *gc.C) {
   129  	args := s.getArgs(c)
   130  	args.DataDir = ""
   131  	c.Assert(manual.Bootstrap(args), gc.ErrorMatches, "data-dir argument is empty")
   132  }
   133  
   134  func (s *bootstrapSuite) TestBootstrapEmptyHost(c *gc.C) {
   135  	args := s.getArgs(c)
   136  	args.Host = ""
   137  	c.Assert(manual.Bootstrap(args), gc.ErrorMatches, "host argument is empty")
   138  }
   139  
   140  func (s *bootstrapSuite) TestBootstrapNilEnviron(c *gc.C) {
   141  	args := s.getArgs(c)
   142  	args.Environ = nil
   143  	c.Assert(manual.Bootstrap(args), gc.ErrorMatches, "environ argument is nil")
   144  }
   145  
   146  func (s *bootstrapSuite) TestBootstrapNoMatchingTools(c *gc.C) {
   147  	// Empty tools list.
   148  	args := s.getArgs(c)
   149  	args.PossibleTools = nil
   150  	defer fakeSSH{SkipDetection: true, SkipProvisionAgent: true}.install(c).Restore()
   151  	c.Assert(manual.Bootstrap(args), gc.ErrorMatches, "possible tools is empty")
   152  
   153  	// Non-empty list, but none that match the series/arch.
   154  	args = s.getArgs(c)
   155  	args.Series = "edgy"
   156  	defer fakeSSH{SkipDetection: true, SkipProvisionAgent: true}.install(c).Restore()
   157  	c.Assert(manual.Bootstrap(args), gc.ErrorMatches, "no matching tools available")
   158  }
   159  
   160  func (s *bootstrapSuite) TestBootstrapToolsFileURL(c *gc.C) {
   161  	storageName := tools.StorageName(version.Current)
   162  	sftpURL, err := s.env.Storage().URL(storageName)
   163  	c.Assert(err, gc.IsNil)
   164  	fileURL := fmt.Sprintf("file://%s/%s", s.env.storageDir, storageName)
   165  	s.testBootstrapToolsURL(c, sftpURL, fileURL)
   166  }
   167  
   168  func (s *bootstrapSuite) TestBootstrapToolsExternalURL(c *gc.C) {
   169  	const externalURL = "http://test.invalid/tools.tgz"
   170  	s.testBootstrapToolsURL(c, externalURL, externalURL)
   171  }
   172  
   173  func (s *bootstrapSuite) testBootstrapToolsURL(c *gc.C, toolsURL, expectedURL string) {
   174  	s.PatchValue(manual.ProvisionMachineAgent, func(host string, mcfg *cloudinit.MachineConfig, w io.Writer) error {
   175  		c.Assert(mcfg.Tools.URL, gc.Equals, expectedURL)
   176  		return nil
   177  	})
   178  	args := s.getArgs(c)
   179  	args.PossibleTools[0].URL = toolsURL
   180  	defer fakeSSH{SkipDetection: true}.install(c).Restore()
   181  	err := manual.Bootstrap(args)
   182  	c.Assert(err, gc.IsNil)
   183  }