github.com/axw/juju@v0.0.0-20161005053422-4bd6544d08d4/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 "os" 8 9 "github.com/juju/errors" 10 "github.com/juju/testing" 11 jc "github.com/juju/testing/checkers" 12 "github.com/juju/utils/arch" 13 gc "gopkg.in/check.v1" 14 15 "github.com/juju/juju/constraints" 16 "github.com/juju/juju/environs" 17 "github.com/juju/juju/environs/manual" 18 "github.com/juju/juju/instance" 19 coretesting "github.com/juju/juju/testing" 20 ) 21 22 type baseEnvironSuite struct { 23 coretesting.FakeJujuXDGDataHomeSuite 24 env *manualEnviron 25 } 26 27 func (s *baseEnvironSuite) SetUpTest(c *gc.C) { 28 s.FakeJujuXDGDataHomeSuite.SetUpTest(c) 29 env, err := manualProvider{}.Open(environs.OpenParams{ 30 Cloud: CloudSpec(), 31 Config: MinimalConfig(c), 32 }) 33 c.Assert(err, jc.ErrorIsNil) 34 s.env = env.(*manualEnviron) 35 } 36 37 type environSuite struct { 38 baseEnvironSuite 39 } 40 41 var _ = gc.Suite(&environSuite{}) 42 43 func (s *environSuite) TestInstances(c *gc.C) { 44 var ids []instance.Id 45 46 instances, err := s.env.Instances(ids) 47 c.Assert(err, gc.Equals, environs.ErrNoInstances) 48 c.Assert(instances, gc.HasLen, 0) 49 50 ids = append(ids, BootstrapInstanceId) 51 instances, err = s.env.Instances(ids) 52 c.Assert(err, jc.ErrorIsNil) 53 c.Assert(instances, gc.HasLen, 1) 54 c.Assert(instances[0], gc.NotNil) 55 56 ids = append(ids, BootstrapInstanceId) 57 instances, err = s.env.Instances(ids) 58 c.Assert(err, jc.ErrorIsNil) 59 c.Assert(instances, gc.HasLen, 2) 60 c.Assert(instances[0], gc.NotNil) 61 c.Assert(instances[1], gc.NotNil) 62 63 ids = append(ids, instance.Id("invalid")) 64 instances, err = s.env.Instances(ids) 65 c.Assert(err, gc.Equals, environs.ErrPartialInstances) 66 c.Assert(instances, gc.HasLen, 3) 67 c.Assert(instances[0], gc.NotNil) 68 c.Assert(instances[1], gc.NotNil) 69 c.Assert(instances[2], gc.IsNil) 70 71 ids = []instance.Id{instance.Id("invalid")} 72 instances, err = s.env.Instances(ids) 73 c.Assert(err, gc.Equals, environs.ErrNoInstances) 74 c.Assert(instances, gc.HasLen, 1) 75 c.Assert(instances[0], gc.IsNil) 76 } 77 78 func (s *environSuite) TestDestroyController(c *gc.C) { 79 var resultStdout string 80 var resultErr error 81 runSSHCommandTesting := func(host string, command []string, stdin string) (string, string, error) { 82 c.Assert(host, gc.Equals, "ubuntu@hostname") 83 c.Assert(command, gc.DeepEquals, []string{"sudo", "/bin/bash"}) 84 c.Assert(stdin, gc.Equals, ` 85 set -x 86 touch '/var/lib/juju/uninstall-agent' 87 # If jujud is running, we then wait for a while for it to stop. 88 stopped=0 89 if pkill -6 jujud; then 90 for i in `+"`seq 1 30`"+`; do 91 if pgrep jujud > /dev/null ; then 92 sleep 1 93 else 94 echo "jujud stopped" 95 stopped=1 96 break 97 fi 98 done 99 fi 100 if [ $stopped -ne 1 ]; then 101 # If jujud didn't stop nicely, we kill it hard here. 102 pkill -9 jujud 103 service juju-db stop 104 fi 105 rm -f /etc/init/juju* 106 rm -f /etc/systemd/system/juju* 107 rm -fr '/var/lib/juju' '/var/log/juju' 108 exit 0 109 `) 110 return resultStdout, "", resultErr 111 } 112 s.PatchValue(&runSSHCommand, runSSHCommandTesting) 113 type test struct { 114 stdout string 115 err error 116 match string 117 } 118 tests := []test{ 119 {"", nil, ""}, 120 {"abc", nil, ""}, 121 {"", errors.New("oh noes"), "oh noes"}, 122 } 123 for i, t := range tests { 124 c.Logf("test %d: %v", i, t) 125 resultStdout, resultErr = t.stdout, t.err 126 err := s.env.DestroyController("controller-uuid") 127 if t.match == "" { 128 c.Assert(err, jc.ErrorIsNil) 129 } else { 130 c.Assert(err, gc.ErrorMatches, t.match) 131 } 132 } 133 } 134 135 func (s *environSuite) TestSupportsNetworking(c *gc.C) { 136 _, ok := environs.SupportsNetworking(s.env) 137 c.Assert(ok, jc.IsFalse) 138 } 139 140 func (s *environSuite) TestConstraintsValidator(c *gc.C) { 141 s.PatchValue(&manual.DetectSeriesAndHardwareCharacteristics, 142 func(string) (instance.HardwareCharacteristics, string, error) { 143 amd64 := "amd64" 144 return instance.HardwareCharacteristics{ 145 Arch: &amd64, 146 }, "", nil 147 }, 148 ) 149 150 validator, err := s.env.ConstraintsValidator() 151 c.Assert(err, jc.ErrorIsNil) 152 cons := constraints.MustParse("arch=amd64 instance-type=foo tags=bar cpu-power=10 cores=2 mem=1G virt-type=kvm") 153 unsupported, err := validator.Validate(cons) 154 c.Assert(err, jc.ErrorIsNil) 155 c.Assert(unsupported, jc.SameContents, []string{"cpu-power", "instance-type", "tags", "virt-type"}) 156 } 157 158 func (s *environSuite) TestConstraintsValidatorInsideController(c *gc.C) { 159 // Patch os.Args so it appears that we're running in "jujud", and then 160 // patch the host arch so it looks like we're running arm64. 161 s.PatchValue(&os.Args, []string{"/some/where/containing/jujud", "whatever"}) 162 s.PatchValue(&arch.HostArch, func() string { return arch.ARM64 }) 163 164 validator, err := s.env.ConstraintsValidator() 165 c.Assert(err, jc.ErrorIsNil) 166 cons := constraints.MustParse("arch=arm64") 167 _, err = validator.Validate(cons) 168 c.Assert(err, jc.ErrorIsNil) 169 } 170 171 type controllerInstancesSuite struct { 172 baseEnvironSuite 173 } 174 175 var _ = gc.Suite(&controllerInstancesSuite{}) 176 177 func (s *controllerInstancesSuite) TestControllerInstances(c *gc.C) { 178 var outputResult string 179 var errResult error 180 runSSHCommandTesting := func(host string, command []string, stdin string) (string, string, error) { 181 return outputResult, "", errResult 182 } 183 s.PatchValue(&runSSHCommand, runSSHCommandTesting) 184 185 type test struct { 186 output string 187 err error 188 expectedErr string 189 } 190 tests := []test{{ 191 output: "", 192 }, { 193 output: "no-agent-dir", 194 expectedErr: "model is not bootstrapped", 195 }, { 196 output: "woo", 197 expectedErr: `unexpected output: "woo"`, 198 }, { 199 err: errors.New("an error"), 200 expectedErr: "an error", 201 }} 202 203 for i, test := range tests { 204 c.Logf("test %d", i) 205 outputResult = test.output 206 errResult = test.err 207 instances, err := s.env.ControllerInstances("not-used") 208 if test.expectedErr == "" { 209 c.Assert(err, jc.ErrorIsNil) 210 c.Assert(instances, gc.DeepEquals, []instance.Id{BootstrapInstanceId}) 211 } else { 212 c.Assert(err, gc.ErrorMatches, test.expectedErr) 213 c.Assert(instances, gc.HasLen, 0) 214 } 215 } 216 } 217 218 func (s *controllerInstancesSuite) TestControllerInstancesStderr(c *gc.C) { 219 // Stderr should not affect the behaviour of ControllerInstances. 220 testing.PatchExecutable(c, s, "ssh", "#!/bin/sh\nhead -n1 > /dev/null; echo abc >&2; exit 0") 221 _, err := s.env.ControllerInstances("not-used") 222 c.Assert(err, jc.ErrorIsNil) 223 } 224 225 func (s *controllerInstancesSuite) TestControllerInstancesError(c *gc.C) { 226 // If the ssh execution fails, its stderr will be captured in the error message. 227 testing.PatchExecutable(c, s, "ssh", "#!/bin/sh\nhead -n1 > /dev/null; echo abc >&2; exit 1") 228 _, err := s.env.ControllerInstances("not-used") 229 c.Assert(err, gc.ErrorMatches, "abc: .*") 230 } 231 232 func (s *controllerInstancesSuite) TestControllerInstancesInternal(c *gc.C) { 233 // Patch os.Args so it appears that we're running in "jujud". 234 s.PatchValue(&os.Args, []string{"/some/where/containing/jujud", "whatever"}) 235 // Patch the ssh executable so that it would cause an error if we 236 // were to call it. 237 testing.PatchExecutable(c, s, "ssh", "#!/bin/sh\nhead -n1 > /dev/null; echo abc >&2; exit 1") 238 instances, err := s.env.ControllerInstances("not-used") 239 c.Assert(err, jc.ErrorIsNil) 240 c.Assert(instances, gc.DeepEquals, []instance.Id{BootstrapInstanceId}) 241 }