1
// Copyright 2012, 2013 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
8
. "launchpad.net/gocheck"
9
"launchpad.net/juju-core/constraints"
10
"launchpad.net/juju-core/environs/config"
11
"launchpad.net/juju-core/errors"
12
"launchpad.net/juju-core/instance"
13
"launchpad.net/juju-core/juju/testing"
14
"launchpad.net/juju-core/state"
15
"launchpad.net/juju-core/state/api"
16
"launchpad.net/juju-core/state/api/params"
17
coretesting "launchpad.net/juju-core/testing"
18
"launchpad.net/juju-core/testing/checkers"
23
func TestAll(t *stdtesting.T) {
24
coretesting.MgoTestPackage(t)
27
type baseSuite struct {
31
var _ = Suite(&baseSuite{})
33
func chanReadEmpty(c *C, ch <-chan struct{}, what string) bool {
37
case <-time.After(10 * time.Second):
38
c.Fatalf("timed out reading from %s", what)
43
func chanReadStrings(c *C, ch <-chan []string, what string) ([]string, bool) {
45
case changes, ok := <-ch:
47
case <-time.After(10 * time.Second):
48
c.Fatalf("timed out reading from %s", what)
53
func chanReadConfig(c *C, ch <-chan *config.Config, what string) (*config.Config, bool) {
55
case envConfig, ok := <-ch:
57
case <-time.After(10 * time.Second):
58
c.Fatalf("timed out reading from %s", what)
63
func removeServiceAndUnits(c *C, service *state.Service) {
64
// Destroy all units for the service.
65
units, err := service.AllUnits()
67
for _, unit := range units {
68
err = unit.EnsureDead()
73
err = service.Destroy()
76
err = service.Refresh()
77
c.Assert(err, checkers.Satisfies, errors.IsNotFoundError)
80
// apiAuthenticator represents a simple authenticator object with only the
81
// SetPassword and Tag methods. This will fit types from both the state
82
// and api packages, as those in the api package do not have PasswordValid().
83
type apiAuthenticator interface {
85
SetPassword(string) error
88
func setDefaultPassword(c *C, e apiAuthenticator) {
89
err := e.SetPassword(defaultPassword(e))
93
func defaultPassword(e apiAuthenticator) string {
94
return e.Tag() + " password"
97
type setStatuser interface {
98
SetStatus(status params.Status, info string) error
101
func setDefaultStatus(c *C, entity setStatuser) {
102
err := entity.SetStatus(params.StatusStarted, "")
106
func (s *baseSuite) tryOpenState(c *C, e apiAuthenticator, password string) error {
107
stateInfo := s.StateInfo(c)
108
stateInfo.Tag = e.Tag()
109
stateInfo.Password = password
110
st, err := state.Open(stateInfo, state.DialOpts{
111
Timeout: 25 * time.Millisecond,
119
// openAs connects to the API state as the given entity
120
// with the default password for that entity.
121
func (s *baseSuite) openAs(c *C, tag string) *api.State {
122
_, info, err := s.APIConn.Environ.StateInfo()
125
info.Password = fmt.Sprintf("%s password", tag)
126
c.Logf("opening state; entity %q; password %q", info.Tag, info.Password)
127
st, err := api.Open(info, api.DialOpts{})
133
// scenarioStatus describes the expected state
134
// of the juju environment set up by setUpScenario.
135
var scenarioStatus = &api.Status{
136
Machines: map[string]api.MachineInfo{
138
InstanceId: "i-machine-0",
141
InstanceId: "i-machine-1",
144
InstanceId: "i-machine-2",
149
// setUpScenario makes an environment scenario suitable for
150
// testing most kinds of access scenario. It returns
151
// a list of all the entities in the scenario.
153
// When the scenario is initialized, we have:
157
// instance-id="i-machine-0"
158
// nonce="fake_nonce"
159
// jobs=manage-environ
160
// status=started, info=""
162
// instance-id="i-machine-1"
163
// nonce="fake_nonce"
165
// status=started, info=""
166
// constraints=mem=1G
168
// instance-id="i-machine-2"
169
// nonce="fake_nonce"
171
// status=started, info=""
175
// deployer-name=machine-1
177
// deployer-name=unit-wordpress-0
179
// deployer-name=machine-2
181
// deployer-name=unit-wordpress-1
183
// The passwords for all returned entities are
184
// set to the entity name with a " password" suffix.
186
// Note that there is nothing special about machine-0
187
// here - it's the environment manager in this scenario
188
// just because machine 0 has traditionally been the
189
// environment manager (bootstrap machine), so is
190
// hopefully easier to remember as such.
191
func (s *baseSuite) setUpScenario(c *C) (entities []string) {
192
add := func(e state.Tagger) {
193
entities = append(entities, e.Tag())
195
u, err := s.State.User("admin")
197
setDefaultPassword(c, u)
200
u, err = s.State.AddUser("other", "")
202
setDefaultPassword(c, u)
205
m, err := s.State.AddMachine("series", state.JobManageEnviron)
207
c.Assert(m.Tag(), Equals, "machine-0")
208
err = m.SetProvisioned(instance.Id("i-"+m.Tag()), "fake_nonce", nil)
210
setDefaultPassword(c, m)
211
setDefaultStatus(c, m)
214
_, err = s.State.AddService("mysql", s.AddTestingCharm(c, "mysql"))
217
wordpress, err := s.State.AddService("wordpress", s.AddTestingCharm(c, "wordpress"))
220
_, err = s.State.AddService("logging", s.AddTestingCharm(c, "logging"))
223
eps, err := s.State.InferEndpoints([]string{"logging", "wordpress"})
225
rel, err := s.State.AddRelation(eps...)
228
for i := 0; i < 2; i++ {
229
wu, err := wordpress.AddUnit()
231
c.Assert(wu.Tag(), Equals, fmt.Sprintf("unit-wordpress-%d", i))
232
setDefaultPassword(c, wu)
235
m, err := s.State.AddMachine("series", state.JobHostUnits)
237
c.Assert(m.Tag(), Equals, fmt.Sprintf("machine-%d", i+1))
239
err = m.SetConstraints(constraints.MustParse("mem=1G"))
242
err = m.SetProvisioned(instance.Id("i-"+m.Tag()), "fake_nonce", nil)
244
setDefaultPassword(c, m)
245
setDefaultStatus(c, m)
248
err = wu.AssignToMachine(m)
251
deployer, ok := wu.DeployerTag()
252
c.Assert(ok, Equals, true)
253
c.Assert(deployer, Equals, fmt.Sprintf("machine-%d", i+1))
255
wru, err := rel.Unit(wu)
258
// Create the subordinate unit as a side-effect of entering
259
// scope in the principal's relation-unit.
260
err = wru.EnterScope(nil)
263
lu, err := s.State.Unit(fmt.Sprintf("logging/%d", i))
265
c.Assert(lu.IsPrincipal(), Equals, false)
266
deployer, ok = lu.DeployerTag()
267
c.Assert(ok, Equals, true)
268
c.Assert(deployer, Equals, fmt.Sprintf("unit-wordpress-%d", i))
269
setDefaultPassword(c, lu)