Permalink
Switch branches/tags
Find file
Fetching contributors…
Cannot retrieve contributors at this time
242 lines (213 sloc) 7.02 KB
// Copyright 2012 Canonical Ltd.
// Licensed under the AGPLv3, see LICENCE file for details.
package manual
import (
"os"
"github.com/juju/errors"
"github.com/juju/testing"
jc "github.com/juju/testing/checkers"
"github.com/juju/utils/arch"
gc "gopkg.in/check.v1"
"github.com/juju/juju/constraints"
"github.com/juju/juju/environs"
"github.com/juju/juju/environs/manual"
"github.com/juju/juju/instance"
coretesting "github.com/juju/juju/testing"
)
type baseEnvironSuite struct {
coretesting.FakeJujuXDGDataHomeSuite
env *manualEnviron
}
func (s *baseEnvironSuite) SetUpTest(c *gc.C) {
s.FakeJujuXDGDataHomeSuite.SetUpTest(c)
env, err := manualProvider{}.Open(environs.OpenParams{
Cloud: CloudSpec(),
Config: MinimalConfig(c),
})
c.Assert(err, jc.ErrorIsNil)
s.env = env.(*manualEnviron)
}
type environSuite struct {
baseEnvironSuite
}
var _ = gc.Suite(&environSuite{})
func (s *environSuite) TestInstances(c *gc.C) {
var ids []instance.Id
instances, err := s.env.Instances(ids)
c.Assert(err, gc.Equals, environs.ErrNoInstances)
c.Assert(instances, gc.HasLen, 0)
ids = append(ids, BootstrapInstanceId)
instances, err = s.env.Instances(ids)
c.Assert(err, jc.ErrorIsNil)
c.Assert(instances, gc.HasLen, 1)
c.Assert(instances[0], gc.NotNil)
ids = append(ids, BootstrapInstanceId)
instances, err = s.env.Instances(ids)
c.Assert(err, jc.ErrorIsNil)
c.Assert(instances, gc.HasLen, 2)
c.Assert(instances[0], gc.NotNil)
c.Assert(instances[1], gc.NotNil)
ids = append(ids, instance.Id("invalid"))
instances, err = s.env.Instances(ids)
c.Assert(err, gc.Equals, environs.ErrPartialInstances)
c.Assert(instances, gc.HasLen, 3)
c.Assert(instances[0], gc.NotNil)
c.Assert(instances[1], gc.NotNil)
c.Assert(instances[2], gc.IsNil)
ids = []instance.Id{instance.Id("invalid")}
instances, err = s.env.Instances(ids)
c.Assert(err, gc.Equals, environs.ErrNoInstances)
c.Assert(instances, gc.HasLen, 1)
c.Assert(instances[0], gc.IsNil)
}
func (s *environSuite) TestDestroyController(c *gc.C) {
var resultStdout string
var resultErr error
runSSHCommandTesting := func(host string, command []string, stdin string) (string, string, error) {
c.Assert(host, gc.Equals, "ubuntu@hostname")
c.Assert(command, gc.DeepEquals, []string{"sudo", "/bin/bash"})
c.Assert(stdin, gc.Equals, `
set -x
touch '/var/lib/juju/uninstall-agent'
# If jujud is running, we then wait for a while for it to stop.
stopped=0
if pkill -6 jujud; then
for i in `+"`seq 1 30`"+`; do
if pgrep jujud > /dev/null ; then
sleep 1
else
echo "jujud stopped"
stopped=1
break
fi
done
fi
if [ $stopped -ne 1 ]; then
# If jujud didn't stop nicely, we kill it hard here.
pkill -9 jujud
service juju-db stop
fi
rm -f /etc/init/juju*
rm -f /etc/systemd/system/juju*
rm -fr '/var/lib/juju' '/var/log/juju'
exit 0
`)
return resultStdout, "", resultErr
}
s.PatchValue(&runSSHCommand, runSSHCommandTesting)
type test struct {
stdout string
err error
match string
}
tests := []test{
{"", nil, ""},
{"abc", nil, ""},
{"", errors.New("oh noes"), "oh noes"},
}
for i, t := range tests {
c.Logf("test %d: %v", i, t)
resultStdout, resultErr = t.stdout, t.err
err := s.env.DestroyController("controller-uuid")
if t.match == "" {
c.Assert(err, jc.ErrorIsNil)
} else {
c.Assert(err, gc.ErrorMatches, t.match)
}
}
}
func (s *environSuite) TestSupportsNetworking(c *gc.C) {
_, ok := environs.SupportsNetworking(s.env)
c.Assert(ok, jc.IsFalse)
}
func (s *environSuite) TestConstraintsValidator(c *gc.C) {
s.PatchValue(&manual.DetectSeriesAndHardwareCharacteristics,
func(string) (instance.HardwareCharacteristics, string, error) {
amd64 := "amd64"
return instance.HardwareCharacteristics{
Arch: &amd64,
}, "", nil
},
)
validator, err := s.env.ConstraintsValidator()
c.Assert(err, jc.ErrorIsNil)
cons := constraints.MustParse("arch=amd64 instance-type=foo tags=bar cpu-power=10 cores=2 mem=1G virt-type=kvm")
unsupported, err := validator.Validate(cons)
c.Assert(err, jc.ErrorIsNil)
c.Assert(unsupported, jc.SameContents, []string{"cpu-power", "instance-type", "tags", "virt-type"})
}
func (s *environSuite) TestConstraintsValidatorInsideController(c *gc.C) {
// Patch os.Args so it appears that we're running in "jujud", and then
// patch the host arch so it looks like we're running arm64.
s.PatchValue(&os.Args, []string{"/some/where/containing/jujud", "whatever"})
s.PatchValue(&arch.HostArch, func() string { return arch.ARM64 })
validator, err := s.env.ConstraintsValidator()
c.Assert(err, jc.ErrorIsNil)
cons := constraints.MustParse("arch=arm64")
_, err = validator.Validate(cons)
c.Assert(err, jc.ErrorIsNil)
}
type controllerInstancesSuite struct {
baseEnvironSuite
}
var _ = gc.Suite(&controllerInstancesSuite{})
func (s *controllerInstancesSuite) TestControllerInstances(c *gc.C) {
var outputResult string
var errResult error
runSSHCommandTesting := func(host string, command []string, stdin string) (string, string, error) {
return outputResult, "", errResult
}
s.PatchValue(&runSSHCommand, runSSHCommandTesting)
type test struct {
output string
err error
expectedErr string
}
tests := []test{{
output: "",
}, {
output: "no-agent-dir",
expectedErr: "model is not bootstrapped",
}, {
output: "woo",
expectedErr: `unexpected output: "woo"`,
}, {
err: errors.New("an error"),
expectedErr: "an error",
}}
for i, test := range tests {
c.Logf("test %d", i)
outputResult = test.output
errResult = test.err
instances, err := s.env.ControllerInstances("not-used")
if test.expectedErr == "" {
c.Assert(err, jc.ErrorIsNil)
c.Assert(instances, gc.DeepEquals, []instance.Id{BootstrapInstanceId})
} else {
c.Assert(err, gc.ErrorMatches, test.expectedErr)
c.Assert(instances, gc.HasLen, 0)
}
}
}
func (s *controllerInstancesSuite) TestControllerInstancesStderr(c *gc.C) {
// Stderr should not affect the behaviour of ControllerInstances.
testing.PatchExecutable(c, s, "ssh", "#!/bin/sh\nhead -n1 > /dev/null; echo abc >&2; exit 0")
_, err := s.env.ControllerInstances("not-used")
c.Assert(err, jc.ErrorIsNil)
}
func (s *controllerInstancesSuite) TestControllerInstancesError(c *gc.C) {
// If the ssh execution fails, its stderr will be captured in the error message.
testing.PatchExecutable(c, s, "ssh", "#!/bin/sh\nhead -n1 > /dev/null; echo abc >&2; exit 1")
_, err := s.env.ControllerInstances("not-used")
c.Assert(err, gc.ErrorMatches, "abc: .*")
}
func (s *controllerInstancesSuite) TestControllerInstancesInternal(c *gc.C) {
// Patch os.Args so it appears that we're running in "jujud".
s.PatchValue(&os.Args, []string{"/some/where/containing/jujud", "whatever"})
// Patch the ssh executable so that it would cause an error if we
// were to call it.
testing.PatchExecutable(c, s, "ssh", "#!/bin/sh\nhead -n1 > /dev/null; echo abc >&2; exit 1")
instances, err := s.env.ControllerInstances("not-used")
c.Assert(err, jc.ErrorIsNil)
c.Assert(instances, gc.DeepEquals, []instance.Id{BootstrapInstanceId})
}