Version: v0.0.0-...-569398f Latest Latest

This package is not in the latest version of its module.

Go to latest
Published: Dec 1, 2022 License: GPL-3.0 Imports: 44 Imported by: 113



Package store has support to use the Ubuntu Store for querying and downloading of snaps, and the related services.

Package store has support to use the Ubuntu Store for querying and downloading of snaps, and the related services.

Package store has support to use the Ubuntu Store for querying and downloading of snaps, and the related services.

Package store has support to use the Ubuntu Store for querying and downloading of snaps, and the related services.



View Source
const (

	// UbuntuCoreWireProtocol is the protocol level we support when
	// communicating with the store. History:
	//  - "1": client supports squashfs snaps
	UbuntuCoreWireProtocol = "1"


View Source
var (

	// macaroonACLAPI points to Developer API endpoint to get an ACL macaroon
	MacaroonACLAPI = developerAPIBase + "dev/api/acl/"

	// UbuntuoneLocation is the Ubuntuone location as defined in the store macaroon
	UbuntuoneLocation = authLocation()
	// UbuntuoneDischargeAPI points to SSO endpoint to discharge a macaroon
	UbuntuoneDischargeAPI = ubuntuoneAPIBase + "/tokens/discharge"
	// UbuntuoneRefreshDischargeAPI points to SSO endpoint to refresh a discharge macaroon
	UbuntuoneRefreshDischargeAPI = ubuntuoneAPIBase + "/tokens/refresh"
View Source
var (
	// ErrBadQuery is returned from Find when the query has special characters in strange places.
	ErrBadQuery = errors.New("bad query")

	// ErrInvalidScope is returned from Find when an invalid scope is requested.
	ErrInvalidScope = errors.New("invalid scope")

	// ErrSnapNotFound is returned when a snap can not be found
	ErrSnapNotFound = errors.New("snap not found")

	// ErrUnauthenticated is returned when authentication is needed to complete the query
	ErrUnauthenticated = errors.New("you need to log in first")

	// ErrAuthenticationNeeds2fa is returned if the authentication needs 2factor
	ErrAuthenticationNeeds2fa = errors.New("two factor authentication required")

	// Err2faFailed is returned when 2fa failed (e.g., a bad token was given)
	Err2faFailed = errors.New("two factor authentication failed")

	// ErrInvalidCredentials is returned on login error
	// It can also be returned when refreshing the discharge
	// macaroon if the user has changed their password.
	ErrInvalidCredentials = errors.New("invalid credentials")

	// ErrTOSNotAccepted is returned when the user has not accepted the store's terms of service.
	ErrTOSNotAccepted = errors.New("terms of service not accepted")

	// ErrNoPaymentMethods is returned when the user has no valid payment methods associated with their account.
	ErrNoPaymentMethods = errors.New("no payment methods")

	// ErrPaymentDeclined is returned when the user's payment method was declined by the upstream payment provider.
	ErrPaymentDeclined = errors.New("payment declined")

	// ErrLocalSnap is returned when an operation that only applies to snaps that come from a store was attempted on a local snap.
	ErrLocalSnap = errors.New("cannot perform operation on local snap")

	// ErrNoUpdateAvailable is returned when an update is attempetd for a snap that has no update available.
	ErrNoUpdateAvailable = errors.New("snap has no updates available")
View Source
var (
	// ErrNoSerial indicates that a device serial is not set yet.
	ErrNoSerial = errors.New("no device serial yet")
View Source
var ErrTooManyRequests = errors.New("too many requests")


func ClientUserAgent

func ClientUserAgent(ctx context.Context) string

ClientUserAgent returns the user agent of the client that talks to snapd

func WithClientUserAgent

func WithClientUserAgent(parent context.Context, req *http.Request) context.Context

ClientUserAgentContext carries the client user agent that talks to snapd


type AssertionQuery

type AssertionQuery interface {
	ToResolve() (map[asserts.Grouping][]*asserts.AtRevision, map[asserts.Grouping][]*asserts.AtSequence, error)

	AddError(e error, ref *asserts.Ref) error
	AddSequenceError(e error, atSeq *asserts.AtSequence) error
	AddGroupingError(e error, grouping asserts.Grouping) error

type AssertionResult

type AssertionResult struct {
	Grouping   asserts.Grouping
	StreamURLs []string

AssertionResult encapsulates the non-error result for one assertion grouping fetch action.

type AuthRefreshNeed

type AuthRefreshNeed struct {
	Device bool
	User   bool

AuthRefreshNeed represents which authorization data needs refreshing.

type AuthorizeOptions

type AuthorizeOptions struct {
	// contains filtered or unexported fields

type Authorizer

type Authorizer interface {
	// Authorize authorizes the given request.
	// If implementing multiple kind of authorization at the same
	// time all they should be performed separately ignoring
	// errors, as the higher-level code might as well treat Authorize
	// as best-effort and only log any returned error.
	Authorize(r *http.Request, dauthCtx DeviceAndAuthContext, user *auth.UserState, opts *AuthorizeOptions) error

	// CanAuthorizeForUser should return true if the Authorizer
	// can authorize requests on behalf of a user, either
	// by the Authorizer using implicit data or by using auth data
	// carried by UserState, in which case the availability of
	// that explicit data in user should be checked.
	CanAuthorizeForUser(user *auth.UserState) bool

An Authorizer can authorize a request using credentials directly or indirectly available.

type CacheManager

type CacheManager struct {
	// contains filtered or unexported fields

cacheManager implements a downloadCache via content based hard linking

func NewCacheManager

func NewCacheManager(cacheDir string, maxItems int) *CacheManager

NewCacheManager returns a new CacheManager with the given cacheDir and the given maximum amount of items. The idea behind it is the following algorithm:

  1. When starting a download, check if it exists in $cacheDir
  2. If found, update its mtime, hardlink into target location, and return success
  3. If not found, download the snap
  4. On success, hardlink into $cacheDir/<digest>
  5. If cache dir has more than maxItems entries, remove oldest mtimes until it has maxItems

The caching part is done here, the downloading happens in the store.go code.

func (*CacheManager) Get

func (cm *CacheManager) Get(cacheKey, targetPath string) error

Get gets the given cacheKey content and puts it into targetPath

func (*CacheManager) GetPath

func (cm *CacheManager) GetPath(cacheKey string) string

GetPath returns the full path of the given content in the cache or empty string

func (*CacheManager) Put

func (cm *CacheManager) Put(cacheKey, sourcePath string) error

Put adds a new file to the cache with the given cacheKey

type Config

type Config struct {
	// Store API base URLs. The assertions url is only separate because it can
	// be overridden by its own env var.
	StoreBaseURL      *url.URL
	AssertionsBaseURL *url.URL

	// Authorizer used to authorize requests, can be nil and a default
	// will be used.
	Authorizer Authorizer

	// StoreID is the store id used if we can't get one through the DeviceAndAuthContext.
	StoreID string

	Architecture string
	Series       string

	DetailFields []string
	InfoFields   []string
	// search v2 fields
	FindFields  []string
	DeltaFormat string

	// CacheDownloads is the number of downloads that should be cached
	CacheDownloads int

	// Proxy returns the HTTP proxy to use when talking to the store
	Proxy func(*http.Request) (*url.URL, error)

Config represents the configuration to access the snap store

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns a copy of the default configuration ready to be adapted.

type CurrentSnap

type CurrentSnap struct {
	InstanceName     string
	SnapID           string
	Revision         snap.Revision
	TrackingChannel  string
	RefreshedDate    time.Time
	IgnoreValidation bool
	Block            []snap.Revision
	Epoch            snap.Epoch
	CohortKey        string
	// ValidationSets is an optional array of validation set primary keys.
	ValidationSets []snapasserts.ValidationSetKey

type DeviceAndAuthContext

type DeviceAndAuthContext interface {
	Device() (*auth.DeviceState, error)

	UpdateDeviceAuth(device *auth.DeviceState, sessionMacaroon string) (actual *auth.DeviceState, err error)

	UpdateUserAuth(user *auth.UserState, discharges []string) (actual *auth.UserState, err error)

	StoreID(fallback string) (string, error)

	DeviceSessionRequestParams(nonce string) (*DeviceSessionRequestParams, error)
	ProxyStoreParams(defaultURL *url.URL) (proxyStoreID string, proxySroreURL *url.URL, err error)

	CloudInfo() (*auth.CloudInfo, error)

A DeviceAndAuthContext mediates access to device and auth information for the store.

type DeviceSessionRequestParams

type DeviceSessionRequestParams struct {
	Request *asserts.DeviceSessionRequest
	Serial  *asserts.Serial
	Model   *asserts.Model

DeviceSessionRequestParams gathers the assertions and information to be sent to request a device session.

func (*DeviceSessionRequestParams) EncodedModel

func (p *DeviceSessionRequestParams) EncodedModel() string

func (*DeviceSessionRequestParams) EncodedRequest

func (p *DeviceSessionRequestParams) EncodedRequest() string

func (*DeviceSessionRequestParams) EncodedSerial

func (p *DeviceSessionRequestParams) EncodedSerial() string

type DownloadError

type DownloadError struct {
	Code int
	URL  *url.URL

DownloadError represents a download error

func (*DownloadError) Error

func (e *DownloadError) Error() string

type DownloadOptions

type DownloadOptions struct {
	RateLimit           int64
	IsAutoRefresh       bool
	LeavePartialOnError bool

type HashError

type HashError struct {
	// contains filtered or unexported fields

func (HashError) Error

func (e HashError) Error() string

type InvalidAuthDataError

type InvalidAuthDataError map[string]stringList

InvalidAuthDataError signals that the authentication data didn't pass validation.

func (InvalidAuthDataError) Error

func (e InvalidAuthDataError) Error() string

type PasswordPolicyError

type PasswordPolicyError map[string]stringList

PasswordPolicyError is returned in a few corner cases, most notably when the password has been force-reset.

func (PasswordPolicyError) Error

func (e PasswordPolicyError) Error() string

type RefreshOptions

type RefreshOptions struct {
	// RefreshManaged indicates to the store that the refresh is
	// managed via snapd-control.
	RefreshManaged bool
	IsAutoRefresh  bool

	PrivacyKey string

type RefreshingAuthorizer

type RefreshingAuthorizer interface {

	// Refresh transient authorization data.
	RefreshAuth(need AuthRefreshNeed, dauthCtx DeviceAndAuthContext, user *auth.UserState, client *http.Client) error

type RevisionNotAvailableError

type RevisionNotAvailableError struct {
	Action   string
	Channel  string
	Releases []channel.Channel

RevisionNotAvailableError is returned when an install is attempted for a snap but the/a revision is not available (given install constraints).

func (*RevisionNotAvailableError) Error

func (e *RevisionNotAvailableError) Error() string
type Search struct {
	// Query is a term to search by or a prefix (if Prefix is true)
	Query  string
	Prefix bool

	CommonID string

	// category is "section" in search v1
	Category string
	Private  bool
	Scope    string

A Search is what you do in order to Find something

type SnapAction

type SnapAction struct {
	Action       string
	InstanceName string
	SnapID       string
	Channel      string
	Revision     snap.Revision
	CohortKey    string
	Flags        SnapActionFlags
	Epoch        snap.Epoch
	// ValidationSets is an optional array of validation set primary keys
	// (relevant for install and refresh actions).
	ValidationSets []snapasserts.ValidationSetKey

type SnapActionError

type SnapActionError struct {
	// NoResults is set if there were no results in the response
	NoResults bool
	// Refresh errors by snap name.
	Refresh map[string]error
	// Install errors by snap name.
	Install map[string]error
	// Download errors by snap name.
	Download map[string]error
	// Other errors.
	Other []error

SnapActionError conveys errors that were reported on otherwise overall successful snap action (install/refresh) request.

func (SnapActionError) Error

func (e SnapActionError) Error() string

func (SnapActionError) SingleOpError

func (e SnapActionError) SingleOpError() (op, name string, err error)

SingleOpError returns the single operation, snap name, and error if e represents a single error of a single operation on a single snap (i.e. if e.Other is empty, and e.Refresh, e.Install and e.Download have a single error in total). In any other case, the error returned will be nil.

type SnapActionFlags

type SnapActionFlags int
const (
	SnapActionIgnoreValidation SnapActionFlags = 1 << iota

type SnapActionResult

type SnapActionResult struct {
	RedirectChannel string

SnapActionResult encapsulates the non-error result of a single action of the SnapAction call.

type SnapAdder

type SnapAdder interface {
	AddSnap(snapName, version, summary string, commands []string) error

type SnapSpec

type SnapSpec struct {
	Name string

A SnapSpec describes a single snap wanted from SnapInfo

type Store

type Store struct {
	// contains filtered or unexported fields

Store represents the ubuntu snap store

func New

func New(cfg *Config, dauthCtx DeviceAndAuthContext) *Store

New creates a new Store with the given access configuration and for given the store id.

func (*Store) Assertion

func (s *Store) Assertion(assertType *asserts.AssertionType, primaryKey []string, user *auth.UserState) (asserts.Assertion, error)

Assertion retrieves the assertion for the given type and primary key.

func (*Store) Buy

func (s *Store) Buy(options *client.BuyOptions, user *auth.UserState) (*client.BuyResult, error)

Buy sends a buy request for the specified snap. Returns the state of the order: Complete, Cancelled.

func (*Store) CacheDownloads

func (s *Store) CacheDownloads() int

func (*Store) ConnectivityCheck

func (s *Store) ConnectivityCheck() (status map[string]bool, err error)

func (*Store) CreateCohorts

func (s *Store) CreateCohorts(ctx context.Context, snaps []string) (map[string]string, error)

func (*Store) Download

func (s *Store) Download(ctx context.Context, name string, targetPath string, downloadInfo *snap.DownloadInfo, pbar progress.Meter, user *auth.UserState, dlOpts *DownloadOptions) error

Download downloads the snap addressed by download info and returns its filename. The file is saved in temporary storage, and should be removed after use to prevent the disk from running out of space.

func (*Store) DownloadAssertions

func (s *Store) DownloadAssertions(streamURLs []string, b *asserts.Batch, user *auth.UserState) error

DownloadAssertions download the assertion streams at the given URLs and adds their assertions to the given asserts.Batch.

func (*Store) DownloadStream

func (s *Store) DownloadStream(ctx context.Context, name string, downloadInfo *snap.DownloadInfo, resume int64, user *auth.UserState) (io.ReadCloser, int, error)

DownloadStream will copy the snap from the request to the io.Reader

func (*Store) EnsureDeviceSession

func (s *Store) EnsureDeviceSession() error

EnsureDeviceSession makes sure the store has a device session available. Expects the store to have an AuthContext.

func (*Store) Find

func (s *Store) Find(ctx context.Context, search *Search, user *auth.UserState) ([]*snap.Info, error)

Find finds (installable) snaps from the store, matching the given Search.

func (*Store) LoginUser

func (s *Store) LoginUser(username, password, otp string) (string, string, error)

LoginUser logs user in the store and returns the authentication macaroons.

func (*Store) ReadyToBuy

func (s *Store) ReadyToBuy(user *auth.UserState) error

ReadyToBuy returns nil if the user's account has accepted T&Cs and has a payment method registered, and an error otherwise

func (*Store) Sections

func (s *Store) Sections(ctx context.Context, user *auth.UserState) ([]string, error)

Sections retrieves the list of available store sections.

func (*Store) SeqFormingAssertion

func (s *Store) SeqFormingAssertion(assertType *asserts.AssertionType, sequenceKey []string, sequence int, user *auth.UserState) (asserts.Assertion, error)

SeqFormingAssertion retrieves the sequence-forming assertion for the given type (currently validation-set only). For sequence <= 0 we query for the latest sequence, otherwise the latest revision of the given sequence is requested.

func (*Store) SetCacheDownloads

func (s *Store) SetCacheDownloads(fileCount int)

func (*Store) SnapAction

func (s *Store) SnapAction(ctx context.Context, currentSnaps []*CurrentSnap, actions []*SnapAction, assertQuery AssertionQuery, user *auth.UserState, opts *RefreshOptions) ([]SnapActionResult, []AssertionResult, error)

SnapAction queries the store for snap information for the given install/refresh actions, given the context information about current installed snaps in currentSnaps. If the request was overall successul (200) but there were reported errors it will return both the snap infos and an SnapActionError. Orthogonally and at the same time it can be used to fetch or update assertions by passing an AssertionQuery whose ToResolve specifies the assertions and revisions to consider. Assertion related errors are reported via the AssertionQuery Add*Error methods.

func (*Store) SnapExists

func (s *Store) SnapExists(ctx context.Context, snapSpec SnapSpec, user *auth.UserState) (naming.SnapRef, *channel.Channel, error)

SnapInfo checks whether the store-hosted snap matching the given spec exists and returns a reference with it name and snap-id and default channel, or an error.

func (*Store) SnapInfo

func (s *Store) SnapInfo(ctx context.Context, snapSpec SnapSpec, user *auth.UserState) (*snap.Info, error)

SnapInfo returns the snap.Info for the store-hosted snap matching the given spec, or an error.

func (*Store) SuggestedCurrency

func (s *Store) SuggestedCurrency() string

SuggestedCurrency retrieves the cached value for the store's suggested currency

func (*Store) UserInfo

func (s *Store) UserInfo(email string) (userinfo *User, err error)

func (*Store) WriteCatalogs

func (s *Store) WriteCatalogs(ctx context.Context, names io.Writer, adder SnapAdder) error

WriteCatalogs queries the "commands" endpoint and writes the command names into the given io.Writer.

type TransferSpeedMonitoringWriter

type TransferSpeedMonitoringWriter struct {
	// contains filtered or unexported fields

implements io.Writer interface XXX: move to osutil?

func NewTransferSpeedMonitoringWriterAndContext

func NewTransferSpeedMonitoringWriterAndContext(origCtx context.Context, measureTimeWindow time.Duration, minDownloadSpeedBps float64) (*TransferSpeedMonitoringWriter, context.Context)

NewTransferSpeedMonitoringWriterAndContext returns an io.Writer that measures write speed in measureTimeWindow windows and cancels the operation if minDownloadSpeedBps is not achieved. Monitor() must be called to start actual measurement.

func (*TransferSpeedMonitoringWriter) Err

Err returns the transferSpeedError if encountered when measurement was run.

func (*TransferSpeedMonitoringWriter) Monitor

func (w *TransferSpeedMonitoringWriter) Monitor() (quit chan bool)

Monitor starts a new measurement for write operations and returns a quit channel that should be closed by the caller to finish the measurement.

func (*TransferSpeedMonitoringWriter) Write

func (w *TransferSpeedMonitoringWriter) Write(p []byte) (n int, err error)

type UnexpectedHTTPStatusError

type UnexpectedHTTPStatusError struct {
	OpSummary  string
	StatusCode int
	Method     string
	URL        *url.URL
	OopsID     string

UnexpectedHTTPStatusError represents an error where the store returned an unexpected HTTP status code, i.e. a status code that doesn't represent success nor an expected error condition with known handling (e.g. a 404 when instead presence is always expected).

func (*UnexpectedHTTPStatusError) Error

func (e *UnexpectedHTTPStatusError) Error() string

type User

type User struct {
	Username         string
	SSHKeys          []string
	OpenIDIdentifier string

type UserAuthUpdater

type UserAuthUpdater interface {
	UpdateUserAuth(user *auth.UserState, discharges []string) (actual *auth.UserState, err error)

type UserAuthorizer

type UserAuthorizer struct{}

UserAuthorizer authorizes requests using user credentials managed via the DeviceAndAuthContext.

func (UserAuthorizer) Authorize

func (UserAuthorizer) CanAuthorizeForUser

func (a UserAuthorizer) CanAuthorizeForUser(user *auth.UserState) bool

func (UserAuthorizer) RefreshAuth

func (a UserAuthorizer) RefreshAuth(need AuthRefreshNeed, dauthCtx DeviceAndAuthContext, user *auth.UserState, client *http.Client) error

func (UserAuthorizer) RefreshUser

func (a UserAuthorizer) RefreshUser(user *auth.UserState, upd UserAuthUpdater, client *http.Client) error

RefreshUser will refresh user discharge macaroon and update state via the UserAuthUpdater.


Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL