luci: go.chromium.org/luci/cipd/appengine/impl/metadata Index | Files

package metadata

import "go.chromium.org/luci/cipd/appengine/impl/metadata"

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.

Index

Package Files

doc.go fingerprint.go legacy.go metadata.go

func CalculateFingerprint Uses

func CalculateFingerprint(m api.PrefixMetadata) string

CalculateFingerprint derives a fingerprint string for 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).

type Storage Uses

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 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(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 Uses

func GetStorage() Storage

GetStorage returns production implementation of the metadata storage.

type Visitor Uses

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.

Package metadata imports 18 packages (graph) and is imported by 2 packages. Updated 2018-08-21. Refresh now. Tools for package owners.