Exemple #1
0
// 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
}
Exemple #2
0
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)
}
Exemple #3
0
// 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
}
Exemple #4
0
// 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
}
Exemple #5
0
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)
	}
}
Exemple #6
0
// 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
}
Exemple #8
0
// 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,
	})