1
// Copyright 2013 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
11
jc "github.com/juju/testing/checkers"
12
gc "gopkg.in/check.v1"
13
"gopkg.in/juju/charm.v6-unstable"
14
"gopkg.in/juju/charmrepo.v2-unstable"
15
"gopkg.in/juju/charmrepo.v2-unstable/csclient"
16
"gopkg.in/juju/charmstore.v5-unstable"
18
"github.com/juju/juju/apiserver/charmrevisionupdater"
19
jujucharmstore "github.com/juju/juju/charmstore"
20
jujutesting "github.com/juju/juju/juju/testing"
21
"github.com/juju/juju/state"
22
"github.com/juju/juju/testcharms"
25
// CharmSuite provides infrastructure to set up and perform tests associated
26
// with charm versioning. A testing charm store server is created and populated
27
// with some known charms used for testing.
28
type CharmSuite struct {
29
jcSuite *jujutesting.JujuConnSuite
31
Handler charmstore.HTTPCloseHandler
32
Server *httptest.Server
33
Client *csclient.Client
34
charms map[string]*state.Charm
37
func (s *CharmSuite) SetUpSuite(c *gc.C, jcSuite *jujutesting.JujuConnSuite) {
41
func (s *CharmSuite) TearDownSuite(c *gc.C) {}
43
func (s *CharmSuite) SetUpTest(c *gc.C) {
44
db := s.jcSuite.Session.DB("juju-testing")
45
params := charmstore.ServerParams{
46
AuthUsername: "test-user",
47
AuthPassword: "test-password",
49
handler, err := charmstore.NewServer(db, nil, "", params, charmstore.V5)
50
c.Assert(err, jc.ErrorIsNil)
52
s.Server = httptest.NewServer(handler)
53
s.Client = csclient.New(csclient.Params{
55
User: params.AuthUsername,
56
Password: params.AuthPassword,
58
urls := map[string]string{
59
"mysql": "quantal/mysql-23",
60
"dummy": "quantal/dummy-24",
61
"riak": "quantal/riak-25",
62
"wordpress": "quantal/wordpress-26",
63
"logging": "quantal/logging-27",
65
for name, url := range urls {
66
testcharms.UploadCharm(c, s.Client, url, name)
68
s.jcSuite.PatchValue(&charmrepo.CacheDir, c.MkDir())
69
// Patch the charm repo initializer function: it is replaced with a charm
70
// store repo pointing to the testing server.
71
s.jcSuite.PatchValue(&charmrevisionupdater.NewCharmStoreClient, func(st *state.State) (jujucharmstore.Client, error) {
72
csURL, err := url.Parse(s.Server.URL)
73
c.Assert(err, jc.ErrorIsNil)
74
return jujucharmstore.NewCachingClient(state.MacaroonCache{st}, csURL)
76
s.charms = make(map[string]*state.Charm)
79
func (s *CharmSuite) TearDownTest(c *gc.C) {
84
// AddMachine adds a new machine to state.
85
func (s *CharmSuite) AddMachine(c *gc.C, machineId string, job state.MachineJob) {
86
m, err := s.jcSuite.State.AddOneMachine(state.MachineTemplate{
88
Jobs: []state.MachineJob{job},
90
c.Assert(err, jc.ErrorIsNil)
91
c.Assert(m.Id(), gc.Equals, machineId)
92
cons, err := m.Constraints()
93
c.Assert(err, jc.ErrorIsNil)
94
controllerCfg, err := s.jcSuite.State.ControllerConfig()
95
c.Assert(err, jc.ErrorIsNil)
96
inst, hc := jujutesting.AssertStartInstanceWithConstraints(c, s.jcSuite.Environ, controllerCfg.ControllerUUID(), m.Id(), cons)
97
err = m.SetProvisioned(inst.Id(), "fake_nonce", hc)
98
c.Assert(err, jc.ErrorIsNil)
101
// AddCharmWithRevision adds a charm with the specified revision to state.
102
func (s *CharmSuite) AddCharmWithRevision(c *gc.C, charmName string, rev int) *state.Charm {
103
ch := testcharms.Repo.CharmDir(charmName)
104
name := ch.Meta().Name
105
curl := charm.MustParseURL(fmt.Sprintf("cs:quantal/%s-%d", name, rev))
106
info := state.CharmInfo{
109
StoragePath: "dummy-path",
110
SHA256: fmt.Sprintf("%s-%d-sha256", name, rev),
112
dummy, err := s.jcSuite.State.AddCharm(info)
113
c.Assert(err, jc.ErrorIsNil)
114
s.charms[name] = dummy
118
// AddService adds a service for the specified charm to state.
119
func (s *CharmSuite) AddService(c *gc.C, charmName, serviceName string) {
120
ch, ok := s.charms[charmName]
121
c.Assert(ok, jc.IsTrue)
122
_, err := s.jcSuite.State.AddApplication(state.AddApplicationArgs{Name: serviceName, Charm: ch})
123
c.Assert(err, jc.ErrorIsNil)
126
// AddUnit adds a new unit for application to the specified machine.
127
func (s *CharmSuite) AddUnit(c *gc.C, serviceName, machineId string) {
128
svc, err := s.jcSuite.State.Application(serviceName)
129
c.Assert(err, jc.ErrorIsNil)
130
u, err := svc.AddUnit()
131
c.Assert(err, jc.ErrorIsNil)
132
m, err := s.jcSuite.State.Machine(machineId)
133
c.Assert(err, jc.ErrorIsNil)
134
err = u.AssignToMachine(m)
135
c.Assert(err, jc.ErrorIsNil)
138
// SetUnitRevision sets the unit's charm to the specified revision.
139
func (s *CharmSuite) SetUnitRevision(c *gc.C, unitName string, rev int) {
140
u, err := s.jcSuite.State.Unit(unitName)
141
c.Assert(err, jc.ErrorIsNil)
142
svc, err := u.Application()
143
c.Assert(err, jc.ErrorIsNil)
144
curl := charm.MustParseURL(fmt.Sprintf("cs:quantal/%s-%d", svc.Name(), rev))
145
err = u.SetCharmURL(curl)
146
c.Assert(err, jc.ErrorIsNil)
149
// SetupScenario adds some machines and services to state.
150
// It assumes a controller machine has already been created.
151
func (s *CharmSuite) SetupScenario(c *gc.C) {
152
s.AddMachine(c, "1", state.JobHostUnits)
153
s.AddMachine(c, "2", state.JobHostUnits)
154
s.AddMachine(c, "3", state.JobHostUnits)
156
// mysql is out of date
157
s.AddCharmWithRevision(c, "mysql", 22)
158
s.AddService(c, "mysql", "mysql")
159
s.AddUnit(c, "mysql", "1")
161
// wordpress is up to date
162
s.AddCharmWithRevision(c, "wordpress", 26)
163
s.AddService(c, "wordpress", "wordpress")
164
s.AddUnit(c, "wordpress", "2")
165
s.AddUnit(c, "wordpress", "2")
166
// wordpress/0 has a version, wordpress/1 is unknown
167
s.SetUnitRevision(c, "wordpress/0", 26)
169
// varnish is a charm that does not have a version in the mock store.
170
s.AddCharmWithRevision(c, "varnish", 5)
171
s.AddService(c, "varnish", "varnish")
172
s.AddUnit(c, "varnish", "3")