v0.0.0-...-51f9457 Latest Latest

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

Go to latest
Published: Jul 9, 2021 License: Apache-2.0 Imports: 19 Imported by: 0



Package metadata implements handling of prefix metadata.

Each element of the package namespace (known as "package path prefix" or just "prefix") can have some metadata attached to it, like Access Control List or the prefix description. Such metadata is generally inherited by the packages that has the prefix.

The current implementation of PrefixMetadata is based on legacy ACL entities produced by Python version of the backend (see legacy.go). It will eventually be replaced.



This section is empty.


This section is empty.


func CalculateFingerprint

func CalculateFingerprint(m *api.PrefixMetadata)

CalculateFingerprint fills in Fingerprint field of the given metadata.

It is basically base64-encoded SHA1 digest of the serialized proto (excluding 'fingerprint' field itself). It doesn't have to be cryptographically secure.

Note that it is also fine if the proto encoding changes with time. We don't care about exact meaning of the fingerprint, as long as it changes each time we update the metadata (so strictly speaking we can just generate random strings and call them fingerprints).

func GetACLs

func GetACLs(m *api.PrefixMetadata) map[api.Role]stringset.Set

GetACLs returns ACLs in the metadata as a map: role -> set of principals.


type Storage

type Storage interface {
	// GetMetadata fetches metadata associated with the given prefix and all
	// parent prefixes.
	// The prefix may be an empty string, in which case the root metadata will be
	// returned, if it is defined.
	// Does not check permissions.
	// The return value is sorted by the prefix length. Prefixes without metadata
	// are skipped. For example, when requesting metadata for prefix "a/b/c/d" the
	// return value may contain entries for "", "a", "a/b", "a/b/c/d" (in that
	// order, where "" indicates the root and "a/b/c" is skipped in this example
	// as not having any metadata attached).
	// Note that the prefix of the last entry doesn't necessary match 'prefix'.
	// This happens if metadata for that prefix doesn't exist. Similarly, the
	// returns value may be completely empty slice in case there's no metadata
	// for the requested prefix and all its parent prefixes.
	// Returns a fatal error if the prefix is malformed, all other errors are
	// transient.
	GetMetadata(c context.Context, prefix string) ([]*api.PrefixMetadata, error)

	// VisitMetadata enumerates the metadata in depth-first order.
	// Can be used to fetch all metadata items at and under the given prefix.
	// The callback is called for each visited node (always starting from 'prefix'
	// itself, even if it has no metadata directly attached to it), receiving same
	// metadata list as if GetMetadata was used to fetch it. The callback can
	// decide whether to proceed with the enumeration of the corresponding subtree
	// or skip it (by returning either true or false).
	// Aborts the traversal on a first error from the callback.
	// Returns either a transient error if fetching failed, or whatever error the
	// callback returned.
	VisitMetadata(c context.Context, prefix string, cb Visitor) error

	// UpdateMetadata transactionally (with XG transaction) updates or creates
	// metadata of some prefix and returns it.
	// The prefix may be an empty string, in which case the root metadata will
	// be updated, if allowed.
	// Does not check permissions. Does not check the format of the updated
	// metadata.
	// It fetches the metadata object and calls the callback to modify it. The
	// callback may be called multiple times when retrying the transaction. If the
	// callback mutates the metadata and doesn't return an error, the metadata's
	// fingerprint is updated, the metadata is saved to the storage and returned
	// to the caller.
	// If the metadata object doesn't exist yet, the callback will be called with
	// an empty object that has only 'Prefix' field populated. The callback then
	// can populate the rest of the fields. If it doesn't touch any fields
	// (but still succeeds), UpdateMetadata will return nil PrefixMetadata, to
	// indicate the metadata is still absent.
	// If the callback returns an error, it will be returned as is. If the
	// transaction itself fails, returns a transient error.
	UpdateMetadata(c context.Context, prefix string, cb func(ctx context.Context, m *api.PrefixMetadata) error) (*api.PrefixMetadata, error)

Storage knows how to store, fetch and update prefix metadata, as well as how to calculate its fingerprint.

The metadata is organized in a forest-like structure, where each node is associated with some package prefix (e.g. has a name "a/b/c"). The single root ("") may or may not be present, depending on the implementation.

It doesn't try to understand what metadata means, just fingerprints, stores and enumerates it.

This functionality is organized into an interface to simplify mocking. Use GetStorage to grab a real implementation.

func GetStorage

func GetStorage() Storage

GetStorage returns production implementation of the metadata storage.

type Visitor

type Visitor func(prefix string, md []*api.PrefixMetadata) (cont bool, err error)

Visitor is a callback passed to VisitMetadata.

It decides whether to continue exploring this metadata subtree or not.

Jump to

Keyboard shortcuts

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