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 }