func (s *suite) TestMacaroonAuthorization(c *gc.C) { ch := charmRepo.CharmDir("wordpress") curl := charm.MustParseReference("~charmers/utopic/wordpress-42") purl := charm.MustParseReference("utopic/wordpress-42") err := s.client.UploadCharmWithRevision(curl, ch, 42) c.Assert(err, gc.IsNil) err = s.client.Put("/"+curl.Path()+"/meta/perm/read", []string{"bob"}) c.Assert(err, gc.IsNil) // Create a client without basic auth credentials client := csclient.New(csclient.Params{ URL: s.srv.URL, }) var result struct{ IdRevision struct{ Revision int } } // TODO 2015-01-23: once supported, rewrite the test using POST requests. _, err = client.Meta(purl, &result) c.Assert(err, gc.ErrorMatches, `cannot get "/utopic/wordpress-42/meta/any\?include=id-revision": cannot get discharge from ".*": third party refused discharge: cannot discharge: no discharge`) c.Assert(httpbakery.IsDischargeError(errgo.Cause(err)), gc.Equals, true) s.discharge = func(cond, arg string) ([]checkers.Caveat, error) { return []checkers.Caveat{checkers.DeclaredCaveat("username", "bob")}, nil } _, err = client.Meta(curl, &result) c.Assert(err, gc.IsNil) c.Assert(result.IdRevision.Revision, gc.Equals, curl.Revision) visitURL := "http://0.1.2.3/visitURL" s.discharge = func(cond, arg string) ([]checkers.Caveat, error) { return nil, &httpbakery.Error{ Code: httpbakery.ErrInteractionRequired, Message: "interaction required", Info: &httpbakery.ErrorInfo{ VisitURL: visitURL, WaitURL: "http://0.1.2.3/waitURL", }} } client = csclient.New(csclient.Params{ URL: s.srv.URL, VisitWebPage: func(vurl *neturl.URL) error { c.Check(vurl.String(), gc.Equals, visitURL) return fmt.Errorf("stopping interaction") }}) _, err = client.Meta(purl, &result) c.Assert(err, gc.ErrorMatches, `cannot get "/utopic/wordpress-42/meta/any\?include=id-revision": cannot get discharge from ".*": cannot start interactive session: stopping interaction`) c.Assert(result.IdRevision.Revision, gc.Equals, curl.Revision) c.Assert(httpbakery.IsInteractionError(errgo.Cause(err)), gc.Equals, true) }
func (s *suite) SetUpTest(c *gc.C) { s.IsolatedMgoSuite.SetUpTest(c) s.startServer(c, s.Session) s.client = csclient.New(csclient.Params{ URL: s.srv.URL, User: s.serverParams.AuthUsername, Password: s.serverParams.AuthPassword, }) }
// NewCharmStore creates and returns a charm store repository. // The given parameters are used to instantiate the charm store. // // The errors returned from the interface methods will // preserve the causes returned from the underlying csclient // methods. func NewCharmStore(p NewCharmStoreParams) Interface { return &CharmStore{ client: csclient.New(csclient.Params{ URL: p.URL, HTTPClient: p.HTTPClient, VisitWebPage: p.VisitWebPage, }), } }
func (s *suite) TestDoAuthorization(c *gc.C) { // Add a charm to be deleted. err := s.client.UploadCharmWithRevision( charm.MustParseReference("~charmers/utopic/wordpress-42"), charmRepo.CharmArchive(c.MkDir(), "wordpress"), 42, ) c.Assert(err, gc.IsNil) // Check that when we use incorrect authorization, // we get an error trying to delete the charm client := csclient.New(csclient.Params{ URL: s.srv.URL, User: s.serverParams.AuthUsername, Password: "******", }) req, err := http.NewRequest("DELETE", "", nil) c.Assert(err, gc.IsNil) _, err = client.Do(req, "/~charmers/utopic/wordpress-42/archive") c.Assert(err, gc.ErrorMatches, "invalid user name or password") c.Assert(errgo.Cause(err), gc.Equals, params.ErrUnauthorized) client = csclient.New(csclient.Params{ URL: s.srv.URL, User: s.serverParams.AuthUsername, Password: s.serverParams.AuthPassword, }) // Check that the charm is still there. err = client.Get("/~charmers/utopic/wordpress-42/expand-id", nil) c.Assert(err, gc.IsNil) // Then check that when we use the correct authorization, // the delete succeeds. req, err = http.NewRequest("DELETE", "", nil) c.Assert(err, gc.IsNil) resp, err := client.Do(req, "/~charmers/utopic/wordpress-42/archive") c.Assert(err, gc.IsNil) resp.Body.Close() // Check that it's now really gone. err = client.Get("/utopic/wordpress-42/expand-id", nil) c.Assert(err, gc.ErrorMatches, `no matching charm or bundle for "cs:utopic/wordpress-42"`) }
func main() { flag.Parse() bundleName := flag.Arg(0) setCacheDir() data, err := ioutil.ReadAll(os.Stdin) if err != nil { log.Fatal(err) } cs := csclient.New(csclient.Params{}) isSubordinate := isSubordinateFunc(cs) bundles, err := migratebundle.Migrate(data, isSubordinate) if err != nil { log.Fatal(err) } if len(bundles) != 1 && bundleName == "" { var names []string for name := range bundles { names = append(names, name) } sort.Strings(names) log.Fatal("bundle name argument required (available bundles: %v)", strings.Join(names, " ")) } var bd *charm.BundleData if bundleName != "" { bd := bundles[bundleName] if bd == nil { log.Fatal("bundle %q not found in bundle", bundleName) } } else { for _, b := range bundles { bd = b } } if !*verify { return } csRepo := charmrepo.NewCharmStore(charmrepo.NewCharmStoreParams{}) charms, err := fetchCharms(csRepo, bd.RequiredCharms()) if err != nil { log.Fatal(err) } if err := bd.VerifyWithCharms(verifyConstraint, charms); err != nil { verr := err.(*charm.VerificationError) fmt.Fprintf(os.Stderr, "verification failed with %d errors\n", len(verr.Errors)) for _, err := range verr.Errors { fmt.Fprintf(os.Stderr, "%s\n", err) } os.Exit(1) } data, err = yaml.Marshal(bd) if err != nil { log.Fatal(err) } os.Stdout.Write(data) }
func badResponseClient(resp *http.Response, err error) *csclient.Client { client := httpbakery.NewHTTPClient() client.Transport = &cannedRoundTripper{ resp: resp, error: err, } return csclient.New(csclient.Params{ URL: "http://0.1.2.3", User: "******", HTTPClient: client, }) }
func (s *suite) TestLogin(c *gc.C) { ch := charmRepo.CharmDir("wordpress") url := charm.MustParseReference("~charmers/utopic/wordpress-42") purl := charm.MustParseReference("utopic/wordpress-42") err := s.client.UploadCharmWithRevision(url, ch, 42) c.Assert(err, gc.IsNil) err = s.client.Put("/"+url.Path()+"/meta/perm/read", []string{"bob"}) c.Assert(err, gc.IsNil) httpClient := httpbakery.NewHTTPClient() client := csclient.New(csclient.Params{ URL: s.srv.URL, HTTPClient: httpClient, }) var result struct{ IdRevision struct{ Revision int } } _, err = client.Meta(purl, &result) c.Assert(err, gc.NotNil) // Try logging in when the discharger fails. err = client.Login() c.Assert(err, gc.ErrorMatches, `cannot retrieve the authentication macaroon: cannot get discharge from ".*": third party refused discharge: cannot discharge: no discharge`) // Allow the discharge. s.discharge = func(cond, arg string) ([]checkers.Caveat, error) { return []checkers.Caveat{checkers.DeclaredCaveat("username", "bob")}, nil } err = client.Login() c.Assert(err, gc.IsNil) // Change discharge so that we're sure the cookies are being // used rather than the discharge mechanism. s.discharge = func(cond, arg string) ([]checkers.Caveat, error) { return nil, fmt.Errorf("no discharge") } // Check that the request still works. _, err = client.Meta(purl, &result) c.Assert(err, gc.IsNil) c.Assert(result.IdRevision.Revision, gc.Equals, url.Revision) // Check that we've got one cookie. srvURL, err := neturl.Parse(s.srv.URL) c.Assert(err, gc.IsNil) c.Assert(httpClient.Jar.Cookies(srvURL), gc.HasLen, 1) // Log in again. err = client.Login() c.Assert(err, gc.IsNil) // Check that we still only have one cookie. c.Assert(httpClient.Jar.Cookies(srvURL), gc.HasLen, 1) }
func (s *suite) TestWhoAmI(c *gc.C) { httpClient := httpbakery.NewHTTPClient() client := csclient.New(csclient.Params{ URL: s.srv.URL, HTTPClient: httpClient, }) response, err := client.WhoAmI() c.Assert(err, gc.ErrorMatches, `cannot retrieve whoami response: cannot get discharge from ".*": third party refused discharge: cannot discharge: no discharge`) s.discharge = func(cond, arg string) ([]checkers.Caveat, error) { return []checkers.Caveat{checkers.DeclaredCaveat("username", "bob")}, nil } response, err = client.WhoAmI() c.Assert(err, gc.IsNil) c.Assert(response.User, gc.Equals, "bob") }
func (s *suite) TestDefaultServerURL(c *gc.C) { // Add a charm used for tests. err := s.client.UploadCharmWithRevision( charm.MustParseReference("~charmers/vivid/testing-wordpress-42"), charmRepo.CharmDir("wordpress"), 42, ) c.Assert(err, gc.IsNil) // Patch the default server URL. s.PatchValue(&csclient.ServerURL, s.srv.URL) // Instantiate a client using the default server URL. client := csclient.New(csclient.Params{ User: s.serverParams.AuthUsername, Password: s.serverParams.AuthPassword, }) c.Assert(client.ServerURL(), gc.Equals, s.srv.URL) // Check that the request succeeds. err = client.Get("/vivid/testing-wordpress-42/expand-id", nil) c.Assert(err, gc.IsNil) }
func (s *suite) TestSetHTTPHeader(c *gc.C) { var header http.Header srv := httptest.NewServer(http.HandlerFunc(func(_ http.ResponseWriter, req *http.Request) { header = req.Header })) defer srv.Close() sendRequest := func(client *csclient.Client) { req, err := http.NewRequest("GET", "", nil) c.Assert(err, jc.ErrorIsNil) _, err = client.Do(req, "/") c.Assert(err, jc.ErrorIsNil) } client := csclient.New(csclient.Params{ URL: srv.URL, }) // Make a first request without custom headers. sendRequest(client) defaultHeaderLen := len(header) // Make a second request adding a couple of custom headers. h := make(http.Header) h.Set("k1", "v1") h.Add("k2", "v2") h.Add("k2", "v3") client.SetHTTPHeader(h) sendRequest(client) c.Assert(header, gc.HasLen, defaultHeaderLen+len(h)) c.Assert(header.Get("k1"), gc.Equals, "v1") c.Assert(header[http.CanonicalHeaderKey("k2")], jc.DeepEquals, []string{"v2", "v3"}) // Make a third request without custom headers. client.SetHTTPHeader(nil) sendRequest(client) c.Assert(header, gc.HasLen, defaultHeaderLen) }