11
"github.com/julienschmidt/httprouter"
13
"gopkg.in/macaroon-bakery.v0/bakery"
14
"gopkg.in/macaroon-bakery.v0/bakery/checkers"
15
"gopkg.in/macaroon-bakery.v0/bakerytest"
16
"gopkg.in/macaroon-bakery.v0/httpbakery"
18
"gopkg.in/juju/charmstore.v4/internal/charmstore"
19
"gopkg.in/juju/charmstore.v4/internal/storetesting"
20
"gopkg.in/juju/charmstore.v4/internal/v4"
23
type commonSuite struct {
24
storetesting.IsolatedMgoSuite
26
// srv holds the store HTTP handler.
29
// srvParams holds the parameters that the
30
// srv handler was started with
31
srvParams charmstore.ServerParams
33
// noMacaroonSrv holds the store HTTP handler
34
// for an instance of the store without identity
35
// enabled. If enableIdentity is false, this is
37
noMacaroonSrv http.Handler
39
// noMacaroonSrvParams holds the parameters that the
40
// noMacaroonSrv handler was started with
41
noMacaroonSrvParams charmstore.ServerParams
43
// store holds an instance of *charm.Store
44
// that can be used to access the charmstore database
46
store *charmstore.Store
48
// esSuite is set only when enableES is set to true.
49
esSuite *storetesting.ElasticSearchSuite
51
// discharge holds the function that will be used
52
// to check third party caveats by the mock
53
// discharger. This will be ignored if enableIdentity was
54
// not true before commonSuite.SetUpTest is invoked.
56
// It may be set by tests to influence the behavior of the
58
discharge func(cav, arg string) ([]checkers.Caveat, error)
60
discharger *bakerytest.Discharger
62
idMServer *httptest.Server
64
// The following fields may be set before
65
// SetUpSuite is invoked on commonSuite
66
// and influences how the suite sets itself up.
68
// enableIdentity holds whether the charmstore server
69
// will be started with a configured identity service.
72
// enableES holds whether the charmstore server will be
73
// started with Elastic Search enabled.
77
func (s *commonSuite) SetUpSuite(c *gc.C) {
78
s.IsolatedMgoSuite.SetUpSuite(c)
80
s.esSuite = new(storetesting.ElasticSearchSuite)
81
s.esSuite.SetUpSuite(c)
85
func (s *commonSuite) TearDownSuite(c *gc.C) {
87
s.esSuite.TearDownSuite(c)
91
func (s *commonSuite) SetUpTest(c *gc.C) {
92
s.IsolatedMgoSuite.SetUpTest(c)
94
s.esSuite.SetUpTest(c)
98
s.idMServer = httptest.NewServer(s.idM)
103
func (s *commonSuite) TearDownTest(c *gc.C) {
105
if s.esSuite != nil {
106
s.esSuite.TearDownTest(c)
108
if s.discharger != nil {
112
s.IsolatedMgoSuite.TearDownTest(c)
115
// startServer creates a new charmstore server.
116
func (s *commonSuite) startServer(c *gc.C) {
117
config := charmstore.ServerParams{
118
AuthUsername: testUsername,
119
AuthPassword: testPassword,
121
if s.enableIdentity {
122
s.discharge = func(_, _ string) ([]checkers.Caveat, error) {
123
return nil, errgo.New("no discharge")
125
discharger := bakerytest.NewDischarger(nil, func(_ *http.Request, cond string, arg string) ([]checkers.Caveat, error) {
126
return s.discharge(cond, arg)
128
config.IdentityLocation = discharger.Location()
129
config.PublicKeyLocator = discharger
130
config.IdentityAPIURL = s.idMServer.URL
132
var si *charmstore.SearchIndex
134
si = &charmstore.SearchIndex{
135
Database: s.esSuite.ES,
136
Index: s.esSuite.TestIndex,
139
db := s.Session.DB("charmstore")
141
s.srv, err = charmstore.NewServer(db, si, config, map[string]charmstore.NewAPIHandlerFunc{"v4": v4.NewAPIHandler})
142
c.Assert(err, gc.IsNil)
145
if s.enableIdentity {
146
config.IdentityLocation = ""
147
config.PublicKeyLocator = nil
148
config.IdentityAPIURL = ""
149
s.noMacaroonSrv, err = charmstore.NewServer(db, si, config, map[string]charmstore.NewAPIHandlerFunc{"v4": v4.NewAPIHandler})
150
c.Assert(err, gc.IsNil)
152
s.noMacaroonSrv = s.srv
154
s.noMacaroonSrvParams = config
156
pool, err := charmstore.NewPool(db, si, &bakery.NewServiceParams{})
157
c.Assert(err, gc.IsNil)
158
s.store = pool.Store()
161
func storeURL(path string) string {
165
func bakeryDo(client *http.Client) func(*http.Request) (*http.Response, error) {
167
client = httpbakery.NewHTTPClient()
169
return func(req *http.Request) (*http.Response, error) {
171
return httpbakery.DoWithBody(client, req, httpbakery.SeekerBody(req.Body.(io.ReadSeeker)), noInteraction)
173
return httpbakery.Do(client, req, noInteraction)
178
// groups may be set to determine the mapping
179
// from user to groups for that user.
180
groups map[string][]string
182
// body may be set to cause serveGroups to return
183
// an arbitrary HTTP response body.
186
// status may be set to indicate the HTTP status code
187
// when body is not nil.
190
router *httprouter.Router
195
groups: make(map[string][]string),
196
router: httprouter.New(),
198
idM.router.GET("/v1/u/:user/idpgroups", idM.serveGroups)
202
func (idM *idM) ServeHTTP(w http.ResponseWriter, req *http.Request) {
203
idM.router.ServeHTTP(w, req)
206
func (idM *idM) serveGroups(w http.ResponseWriter, req *http.Request, p httprouter.Params) {
209
w.WriteHeader(idM.status)
211
w.Write([]byte(idM.body))
214
u := p.ByName("user")
218
enc := json.NewEncoder(w)
219
if err := enc.Encode(idM.groups[u]); err != nil {