1
// Copyright 2013 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
10
gc "launchpad.net/gocheck"
11
"launchpad.net/goyaml"
13
"launchpad.net/juju-core/environs"
14
"launchpad.net/juju-core/environs/config"
15
"launchpad.net/juju-core/environs/localstorage"
16
"launchpad.net/juju-core/errors"
17
"launchpad.net/juju-core/instance"
18
"launchpad.net/juju-core/provider"
19
"launchpad.net/juju-core/testing"
20
jc "launchpad.net/juju-core/testing/checkers"
23
type StateSuite struct{}
25
var _ = gc.Suite(&StateSuite{})
27
// makeDummyStorage creates a local storage.
28
// Returns a cleanup function that must be called when done with the storage.
29
func makeDummyStorage(c *gc.C) (environs.Storage, func()) {
30
listener, err := localstorage.Serve("127.0.0.1:0", c.MkDir())
31
c.Assert(err, gc.IsNil)
32
storage := localstorage.Client(listener.Addr().String())
33
cleanup := func() { listener.Close() }
34
return storage, cleanup
37
func (*StateSuite) TestCreateStateFileWritesEmptyStateFile(c *gc.C) {
38
storage, cleanup := makeDummyStorage(c)
41
url, err := provider.CreateStateFile(storage)
42
c.Assert(err, gc.IsNil)
44
reader, err := storage.Get(provider.StateFile)
45
c.Assert(err, gc.IsNil)
46
data, err := ioutil.ReadAll(reader)
47
c.Assert(err, gc.IsNil)
48
c.Check(string(data), gc.Equals, "")
49
c.Assert(url, gc.NotNil)
50
expectedURL, err := storage.URL(provider.StateFile)
51
c.Assert(err, gc.IsNil)
52
c.Check(url, gc.Equals, expectedURL)
55
func (suite *StateSuite) TestSaveStateWritesStateFile(c *gc.C) {
56
storage, cleanup := makeDummyStorage(c)
59
state := provider.BootstrapState{
60
StateInstances: []instance.Id{instance.Id("an-instance-id")},
61
Characteristics: []instance.HardwareCharacteristics{{Arch: &arch}}}
62
marshaledState, err := goyaml.Marshal(state)
63
c.Assert(err, gc.IsNil)
65
err = provider.SaveState(storage, &state)
66
c.Assert(err, gc.IsNil)
68
loadedState, err := storage.Get(provider.StateFile)
69
c.Assert(err, gc.IsNil)
70
content, err := ioutil.ReadAll(loadedState)
71
c.Assert(err, gc.IsNil)
72
c.Check(content, gc.DeepEquals, marshaledState)
75
func (suite *StateSuite) setUpSavedState(c *gc.C, storage environs.Storage) provider.BootstrapState {
77
state := provider.BootstrapState{
78
StateInstances: []instance.Id{instance.Id("an-instance-id")},
79
Characteristics: []instance.HardwareCharacteristics{{Arch: &arch}}}
80
content, err := goyaml.Marshal(state)
81
c.Assert(err, gc.IsNil)
82
err = storage.Put(provider.StateFile, ioutil.NopCloser(bytes.NewReader(content)), int64(len(content)))
83
c.Assert(err, gc.IsNil)
87
func (suite *StateSuite) TestLoadStateReadsStateFile(c *gc.C) {
88
storage, cleanup := makeDummyStorage(c)
90
state := suite.setUpSavedState(c, storage)
91
storedState, err := provider.LoadState(storage)
92
c.Assert(err, gc.IsNil)
93
c.Check(*storedState, gc.DeepEquals, state)
96
func (suite *StateSuite) TestLoadStateFromURLReadsStateFile(c *gc.C) {
97
storage, cleanup := makeDummyStorage(c)
99
state := suite.setUpSavedState(c, storage)
100
url, err := storage.URL(provider.StateFile)
101
c.Assert(err, gc.IsNil)
102
storedState, err := provider.LoadStateFromURL(url)
103
c.Assert(err, gc.IsNil)
104
c.Check(*storedState, gc.DeepEquals, state)
107
func (suite *StateSuite) TestLoadStateMissingFile(c *gc.C) {
108
storage, cleanup := makeDummyStorage(c)
111
_, err := provider.LoadState(storage)
113
c.Check(err, jc.Satisfies, errors.IsNotBootstrapped)
116
func (suite *StateSuite) TestLoadStateIntegratesWithSaveState(c *gc.C) {
117
storage, cleanup := makeDummyStorage(c)
120
state := provider.BootstrapState{
121
StateInstances: []instance.Id{instance.Id("an-instance-id")},
122
Characteristics: []instance.HardwareCharacteristics{{Arch: &arch}}}
123
err := provider.SaveState(storage, &state)
124
c.Assert(err, gc.IsNil)
125
storedState, err := provider.LoadState(storage)
126
c.Assert(err, gc.IsNil)
128
c.Check(*storedState, gc.DeepEquals, state)
131
func (suite *StateSuite) TestGetDNSNamesAcceptsNil(c *gc.C) {
132
result := provider.GetDNSNames(nil)
133
c.Check(result, gc.DeepEquals, []string{})
136
func (suite *StateSuite) TestGetDNSNamesReturnsNames(c *gc.C) {
137
instances := []instance.Instance{
138
&dnsNameFakeInstance{name: "foo"},
139
&dnsNameFakeInstance{name: "bar"},
142
c.Check(provider.GetDNSNames(instances), gc.DeepEquals, []string{"foo", "bar"})
145
func (suite *StateSuite) TestGetDNSNamesIgnoresNils(c *gc.C) {
146
c.Check(provider.GetDNSNames([]instance.Instance{nil, nil}), gc.DeepEquals, []string{})
149
func (suite *StateSuite) TestGetDNSNamesIgnoresInstancesWithoutNames(c *gc.C) {
150
instances := []instance.Instance{&dnsNameFakeInstance{err: instance.ErrNoDNSName}}
151
c.Check(provider.GetDNSNames(instances), gc.DeepEquals, []string{})
154
func (suite *StateSuite) TestGetDNSNamesIgnoresInstancesWithBlankNames(c *gc.C) {
155
instances := []instance.Instance{&dnsNameFakeInstance{name: ""}}
156
c.Check(provider.GetDNSNames(instances), gc.DeepEquals, []string{})
159
func (suite *StateSuite) TestComposeAddressesAcceptsNil(c *gc.C) {
160
c.Check(provider.ComposeAddresses(nil, 1433), gc.DeepEquals, []string{})
163
func (suite *StateSuite) TestComposeAddressesSuffixesAddresses(c *gc.C) {
165
provider.ComposeAddresses([]string{"onehost", "otherhost"}, 1957),
167
[]string{"onehost:1957", "otherhost:1957"})
170
func (suite *StateSuite) TestGetStateInfo(c *gc.C) {
171
cert := testing.CACert
172
cfg, err := config.New(map[string]interface{}{
173
// Some config items we're going to test for:
177
// And some required but irrelevant items:
180
"ca-private-key": testing.CAKey,
182
c.Assert(err, gc.IsNil)
183
hostnames := []string{"onehost", "otherhost"}
185
stateInfo, apiInfo := provider.GetStateInfo(cfg, hostnames)
187
c.Check(stateInfo.Addrs, gc.DeepEquals, []string{"onehost:123", "otherhost:123"})
188
c.Check(string(stateInfo.CACert), gc.Equals, cert)
189
c.Check(apiInfo.Addrs, gc.DeepEquals, []string{"onehost:456", "otherhost:456"})
190
c.Check(string(apiInfo.CACert), gc.Equals, cert)