github.com/cloud-green/juju@v0.0.0-20151002100041-a00291338d3d/provider/manual/environ_test.go (about) 1 // Copyright 2012 Canonical Ltd. 2 // Licensed under the AGPLv3, see LICENCE file for details. 3 4 package manual 5 6 import ( 7 "github.com/juju/errors" 8 "github.com/juju/testing" 9 jc "github.com/juju/testing/checkers" 10 "github.com/juju/utils/arch" 11 gc "gopkg.in/check.v1" 12 13 "github.com/juju/juju/constraints" 14 "github.com/juju/juju/environs" 15 "github.com/juju/juju/environs/storage" 16 envtesting "github.com/juju/juju/environs/testing" 17 "github.com/juju/juju/instance" 18 coretesting "github.com/juju/juju/testing" 19 ) 20 21 type environSuite struct { 22 coretesting.FakeJujuHomeSuite 23 env *manualEnviron 24 } 25 26 type dummyStorage struct { 27 storage.Storage 28 } 29 30 var _ = gc.Suite(&environSuite{}) 31 32 func (s *environSuite) SetUpTest(c *gc.C) { 33 s.FakeJujuHomeSuite.SetUpTest(c) 34 env, err := manualProvider{}.Open(MinimalConfig(c)) 35 c.Assert(err, jc.ErrorIsNil) 36 s.env = env.(*manualEnviron) 37 } 38 39 func (s *environSuite) TestSetConfig(c *gc.C) { 40 err := s.env.SetConfig(MinimalConfig(c)) 41 c.Assert(err, jc.ErrorIsNil) 42 43 testConfig := MinimalConfig(c) 44 testConfig, err = testConfig.Apply(map[string]interface{}{"bootstrap-host": ""}) 45 c.Assert(err, jc.ErrorIsNil) 46 err = s.env.SetConfig(testConfig) 47 c.Assert(err, gc.ErrorMatches, "bootstrap-host must be specified") 48 } 49 50 func (s *environSuite) TestInstances(c *gc.C) { 51 var ids []instance.Id 52 53 instances, err := s.env.Instances(ids) 54 c.Assert(err, gc.Equals, environs.ErrNoInstances) 55 c.Assert(instances, gc.HasLen, 0) 56 57 ids = append(ids, BootstrapInstanceId) 58 instances, err = s.env.Instances(ids) 59 c.Assert(err, jc.ErrorIsNil) 60 c.Assert(instances, gc.HasLen, 1) 61 c.Assert(instances[0], gc.NotNil) 62 63 ids = append(ids, BootstrapInstanceId) 64 instances, err = s.env.Instances(ids) 65 c.Assert(err, jc.ErrorIsNil) 66 c.Assert(instances, gc.HasLen, 2) 67 c.Assert(instances[0], gc.NotNil) 68 c.Assert(instances[1], gc.NotNil) 69 70 ids = append(ids, instance.Id("invalid")) 71 instances, err = s.env.Instances(ids) 72 c.Assert(err, gc.Equals, environs.ErrPartialInstances) 73 c.Assert(instances, gc.HasLen, 3) 74 c.Assert(instances[0], gc.NotNil) 75 c.Assert(instances[1], gc.NotNil) 76 c.Assert(instances[2], gc.IsNil) 77 78 ids = []instance.Id{instance.Id("invalid")} 79 instances, err = s.env.Instances(ids) 80 c.Assert(err, gc.Equals, environs.ErrNoInstances) 81 c.Assert(instances, gc.HasLen, 1) 82 c.Assert(instances[0], gc.IsNil) 83 } 84 85 func (s *environSuite) TestDestroy(c *gc.C) { 86 var resultStderr string 87 var resultErr error 88 runSSHCommandTesting := func(host string, command []string, stdin string) (string, error) { 89 c.Assert(host, gc.Equals, "ubuntu@hostname") 90 c.Assert(command, gc.DeepEquals, []string{"sudo", "/bin/bash"}) 91 c.Assert(stdin, gc.DeepEquals, ` 92 set -x 93 pkill -6 jujud && exit 94 stop juju-db 95 rm -f /etc/init/juju* 96 rm -f /etc/rsyslog.d/*juju* 97 rm -fr '/var/lib/juju' '/var/log/juju' 98 exit 0 99 `) 100 return resultStderr, resultErr 101 } 102 s.PatchValue(&runSSHCommand, runSSHCommandTesting) 103 type test struct { 104 stderr string 105 err error 106 match string 107 } 108 tests := []test{ 109 {"", nil, ""}, 110 {"abc", nil, ""}, 111 {"", errors.New("oh noes"), "oh noes"}, 112 } 113 for i, t := range tests { 114 c.Logf("test %d: %v", i, t) 115 resultStderr, resultErr = t.stderr, t.err 116 err := s.env.Destroy() 117 if t.match == "" { 118 c.Assert(err, jc.ErrorIsNil) 119 } else { 120 c.Assert(err, gc.ErrorMatches, t.match) 121 } 122 } 123 } 124 125 func (s *environSuite) TestLocalStorageConfig(c *gc.C) { 126 c.Assert(s.env.StorageDir(), gc.Equals, "/var/lib/juju/storage") 127 c.Assert(s.env.cfg.storageListenAddr(), gc.Equals, ":8040") 128 c.Assert(s.env.StorageAddr(), gc.Equals, s.env.cfg.storageListenAddr()) 129 c.Assert(s.env.SharedStorageAddr(), gc.Equals, "") 130 c.Assert(s.env.SharedStorageDir(), gc.Equals, "") 131 } 132 133 func (s *environSuite) TestSupportedArchitectures(c *gc.C) { 134 arches, err := s.env.SupportedArchitectures() 135 c.Assert(err, jc.ErrorIsNil) 136 c.Assert(arches, gc.DeepEquals, arch.AllSupportedArches) 137 } 138 139 func (s *environSuite) TestSupportsNetworking(c *gc.C) { 140 _, ok := environs.SupportsNetworking(s.env) 141 c.Assert(ok, jc.IsFalse) 142 } 143 144 func (s *environSuite) TestConstraintsValidator(c *gc.C) { 145 validator, err := s.env.ConstraintsValidator() 146 c.Assert(err, jc.ErrorIsNil) 147 cons := constraints.MustParse("arch=amd64 instance-type=foo tags=bar cpu-power=10 cpu-cores=2 mem=1G") 148 unsupported, err := validator.Validate(cons) 149 c.Assert(err, jc.ErrorIsNil) 150 c.Assert(unsupported, jc.SameContents, []string{"cpu-power", "instance-type", "tags"}) 151 } 152 153 type bootstrapSuite struct { 154 coretesting.FakeJujuHomeSuite 155 env *manualEnviron 156 } 157 158 var _ = gc.Suite(&bootstrapSuite{}) 159 160 func (s *bootstrapSuite) SetUpTest(c *gc.C) { 161 s.FakeJujuHomeSuite.SetUpTest(c) 162 163 // ensure use-sshstorage=true to mimic what happens 164 // in the real client: the environment is Prepared, 165 // at which point use-sshstorage=true. 166 cfg := MinimalConfig(c) 167 cfg, err := cfg.Apply(map[string]interface{}{ 168 "use-sshstorage": true, 169 }) 170 c.Assert(err, jc.ErrorIsNil) 171 172 env, err := manualProvider{}.Open(cfg) 173 c.Assert(err, jc.ErrorIsNil) 174 s.env = env.(*manualEnviron) 175 } 176 177 func (s *bootstrapSuite) TestBootstrapClearsUseSSHStorage(c *gc.C) { 178 s.PatchValue(&manualDetectSeriesAndHardwareCharacteristics, func(string) (instance.HardwareCharacteristics, string, error) { 179 arch := arch.HostArch() 180 return instance.HardwareCharacteristics{Arch: &arch}, "precise", nil 181 }) 182 s.PatchValue(&manualCheckProvisioned, func(string) (bool, error) { 183 return false, nil 184 }) 185 186 // use-sshstorage is initially true. 187 cfg := s.env.Config() 188 c.Assert(cfg.UnknownAttrs()["use-sshstorage"], jc.IsTrue) 189 190 _, _, _, err := s.env.Bootstrap(envtesting.BootstrapContext(c), environs.BootstrapParams{}) 191 c.Assert(err, jc.ErrorIsNil) 192 193 // Bootstrap must set use-sshstorage to false within the environment. 194 cfg = s.env.Config() 195 c.Assert(cfg.UnknownAttrs()["use-sshstorage"], jc.IsFalse) 196 } 197 198 type stateServerInstancesSuite struct { 199 coretesting.FakeJujuHomeSuite 200 env *manualEnviron 201 } 202 203 var _ = gc.Suite(&stateServerInstancesSuite{}) 204 205 func (s *stateServerInstancesSuite) SetUpTest(c *gc.C) { 206 s.FakeJujuHomeSuite.SetUpTest(c) 207 208 // ensure use-sshstorage=true, or bootstrap-host 209 // verification won't happen in StateServerInstances. 210 cfg := MinimalConfig(c) 211 cfg, err := cfg.Apply(map[string]interface{}{ 212 "use-sshstorage": true, 213 }) 214 c.Assert(err, jc.ErrorIsNil) 215 216 env, err := manualProvider{}.Open(cfg) 217 c.Assert(err, jc.ErrorIsNil) 218 s.env = env.(*manualEnviron) 219 } 220 221 func (s *stateServerInstancesSuite) TestStateServerInstances(c *gc.C) { 222 var outputResult string 223 var errResult error 224 runSSHCommandTesting := func(host string, command []string, stdin string) (string, error) { 225 return outputResult, errResult 226 } 227 s.PatchValue(&runSSHCommand, runSSHCommandTesting) 228 229 type test struct { 230 output string 231 err error 232 expectedErr string 233 } 234 tests := []test{{ 235 output: "", 236 }, { 237 output: "no-agent-dir", 238 expectedErr: "environment is not bootstrapped", 239 }, { 240 output: "woo", 241 expectedErr: `unexpected output: "woo"`, 242 }, { 243 err: errors.New("an error"), 244 expectedErr: "an error", 245 }} 246 247 for i, test := range tests { 248 c.Logf("test %d", i) 249 outputResult = test.output 250 errResult = test.err 251 instances, err := s.env.StateServerInstances() 252 if test.expectedErr == "" { 253 c.Assert(err, jc.ErrorIsNil) 254 c.Assert(instances, gc.DeepEquals, []instance.Id{BootstrapInstanceId}) 255 } else { 256 c.Assert(err, gc.ErrorMatches, test.expectedErr) 257 c.Assert(instances, gc.HasLen, 0) 258 } 259 } 260 } 261 262 func (s *stateServerInstancesSuite) TestStateServerInstancesStderr(c *gc.C) { 263 // Stderr should not affect the behaviour of StateServerInstances. 264 testing.PatchExecutable(c, s, "ssh", "#!/bin/sh\nhead -n1 > /dev/null; echo abc >&2; exit 0") 265 _, err := s.env.StateServerInstances() 266 c.Assert(err, jc.ErrorIsNil) 267 } 268 269 func (s *stateServerInstancesSuite) TestStateServerInstancesError(c *gc.C) { 270 // If the ssh execution fails, its stderr will be captured in the error message. 271 testing.PatchExecutable(c, s, "ssh", "#!/bin/sh\nhead -n1 > /dev/null; echo abc >&2; exit 1") 272 _, err := s.env.StateServerInstances() 273 c.Assert(err, gc.ErrorMatches, "abc: .*") 274 } 275 276 func (s *stateServerInstancesSuite) TestStateServerInstancesInternal(c *gc.C) { 277 // If use-sshstorage=false, then we're on the bootstrap host; 278 // verification is elided. 279 env, err := manualProvider{}.Open(MinimalConfig(c)) 280 c.Assert(err, jc.ErrorIsNil) 281 282 testing.PatchExecutable(c, s, "ssh", "#!/bin/sh\nhead -n1 > /dev/null; echo abc >&2; exit 1") 283 instances, err := env.StateServerInstances() 284 c.Assert(err, jc.ErrorIsNil) 285 c.Assert(instances, gc.DeepEquals, []instance.Id{BootstrapInstanceId}) 286 }