// addCharmViaAPI calls the appropriate client API calls to add the // given charm URL to state. For non-public charm URLs, this function also // handles the macaroon authorization process using the given csClient. // The resulting charm URL of the added charm is displayed on stdout. func addCharmViaAPI(client *api.Client, ctx *cmd.Context, curl *charm.URL, repo charmrepo.Interface, csclient *csClient) (*charm.URL, error) { switch curl.Schema { case "local": ch, err := repo.Get(curl) if err != nil { return nil, err } stateCurl, err := client.AddLocalCharm(curl, ch) if err != nil { return nil, err } curl = stateCurl case "cs": if err := client.AddCharm(curl); err != nil { if !params.IsCodeUnauthorized(err) { return nil, errors.Mask(err) } m, err := csclient.authorize(curl) if err != nil { return nil, errors.Mask(err) } if err := client.AddCharmWithAuthorization(curl, m); err != nil { return nil, errors.Mask(err) } } default: return nil, fmt.Errorf("unsupported charm URL schema: %q", curl.Schema) } ctx.Infof("Added charm %q to the environment.", curl) return curl, nil }
func (*functionSuite) TestMask(c *gc.C) { first := errors.New("first") err := errors.Mask(first) //err maskTest c.Assert(err.Error(), gc.Equals, "first") c.Assert(errors.Cause(err), gc.Equals, err) c.Assert(errors.Details(err), jc.Contains, tagToLocation["maskTest"].String()) c.Assert(errors.Mask(nil), gc.IsNil) }
// hashAndSize calculates and returns the SHA256 hash and the size of the file // located at the given path. func hashAndSize(path string) (hash string, size int64, err error) { f, err := os.Open(path) if err != nil { return "", 0, errors.Mask(err) } defer f.Close() h := sha256.New() size, err = io.Copy(h, f) if err != nil { return "", 0, errors.Mask(err) } return fmt.Sprintf("%x", h.Sum(nil)), size, nil }
// Run implements Command.Run. func (c *listAgreementsCommand) Run(ctx *cmd.Context) error { client, err := c.BakeryClient() if err != nil { return errors.Annotate(err, "failed to create an http client") } apiClient, err := newClient(client) if err != nil { return errors.Annotate(err, "failed to create a terms API client") } agreements, err := apiClient.GetUsersAgreements() if err != nil { return errors.Annotate(err, "failed to list user agreements") } if len(agreements) == 0 { ctx.Infof("No agreements to display.") return nil } err = c.out.Write(ctx, agreements) if err != nil { return errors.Mask(err) } return nil }
func (c attrsC) Coerce(v interface{}, path []string) (interface{}, error) { // TODO consider allowing only the map variant. switch reflect.TypeOf(v).Kind() { case reflect.String: s, err := schema.String().Coerce(v, path) if err != nil { return nil, errors.Mask(err) } result, err := keyvalues.Parse(strings.Fields(s.(string)), true) if err != nil { return nil, fmt.Errorf("%s%v", pathPrefix(path), err) } return result, nil case reflect.Slice: slice0, err := attrSliceChecker.Coerce(v, path) if err != nil { return nil, errors.Mask(err) } slice := slice0.([]interface{}) fields := make([]string, len(slice)) for i, f := range slice { fields[i] = f.(string) } result, err := keyvalues.Parse(fields, true) if err != nil { return nil, fmt.Errorf("%s%v", pathPrefix(path), err) } return result, nil case reflect.Map: imap0, err := attrMapChecker.Coerce(v, path) if err != nil { return nil, errors.Mask(err) } imap := imap0.(map[interface{}]interface{}) result := make(map[string]string) for k, v := range imap { result[k.(string)] = v.(string) } return result, nil default: return nil, errors.Errorf("%sunexpected type for value, got %T(%v)", pathPrefix(path), v, v) } }
// resolve resolves the given given charm or bundle URL // string by looking it up in the appropriate charm repository. If it is // a charm store URL, the given csParams will be used to access the // charm store repository. If it is a local charm or bundle URL, the // local charm repository at the given repoPath will be used. The given // configuration will be used to add any necessary attributes to the // repo and to return the charm's supported series if possible. // // It returns the fully resolved URL, any series supported by the entity, // and the repository that holds it. func (r *charmURLResolver) resolve(urlStr string) (*charm.URL, csparams.Channel, []string, charmrepo.Interface, error) { var noChannel csparams.Channel url, err := charm.ParseURL(urlStr) if err != nil { return nil, noChannel, nil, nil, errors.Trace(err) } switch url.Schema { case "cs": repo := config.SpecializeCharmRepo(r.csRepo, r.conf).(*charmrepo.CharmStore) resultUrl, channel, supportedSeries, err := repo.ResolveWithChannel(url) if err != nil { return nil, noChannel, nil, nil, errors.Trace(err) } return resultUrl, channel, supportedSeries, repo, nil case "local": if url.Series == "" { if defaultSeries, ok := r.conf.DefaultSeries(); ok { url.Series = defaultSeries } } if url.Series == "" { possibleURL := *url possibleURL.Series = config.LatestLtsSeries() logger.Errorf("The series is not specified in the model (default-series) or with the charm. Did you mean:\n\t%s", &possibleURL) return nil, noChannel, nil, nil, errors.Errorf("cannot resolve series for charm: %q", url) } repo, err := charmrepo.NewLocalRepository(r.repoPath) if err != nil { return nil, noChannel, nil, nil, errors.Mask(err) } repo = config.SpecializeCharmRepo(repo, r.conf) resultUrl, supportedSeries, err := repo.Resolve(url) if err != nil { return nil, noChannel, nil, nil, errors.Trace(err) } return resultUrl, noChannel, supportedSeries, repo, nil default: return nil, noChannel, nil, nil, errors.Errorf("unknown schema for charm reference %q", urlStr) } }
// Run implements Command.Run. func (c *listAgreementsCommand) Run(ctx *cmd.Context) error { client, err := c.BakeryClient() if err != nil { return errors.Annotate(err, "failed to create an http client") } apiClient, err := newClient(client) if err != nil { return errors.Annotate(err, "failed to create a terms API client") } agreements, err := apiClient.GetUsersAgreements() if err != nil { return errors.Annotate(err, "failed to list user agreements") } if agreements == nil { agreements = []terms.AgreementResponse{} } err = c.out.Write(ctx, agreements) if err != nil { return errors.Mask(err) } return nil }
// csClient gives access to the charm store server and provides parameters // for connecting to the charm store. type csClient struct { jar *cookiejar.Jar params charmrepo.NewCharmStoreParams } // newCharmStoreClient is called to obtain a charm store client // including the parameters for connecting to the charm store, and // helpers to save the local authorization cookies and to authorize // non-public charm deployments. It is defined as a variable so it can // be changed for testing purposes. var newCharmStoreClient = func() (*csClient, error) { jar, client, err := newHTTPClient() if err != nil { return nil, errors.Mask(err) } return &csClient{ jar: jar, params: charmrepo.NewCharmStoreParams{ HTTPClient: client, VisitWebPage: httpbakery.OpenWebBrowser, }, }, nil } func newHTTPClient() (*cookiejar.Jar, *http.Client, error) { cookieFile := path.Join(utils.Home(), ".go-cookies") jar, err := cookiejar.New(&cookiejar.Options{ PublicSuffixList: publicsuffix.List, })