208 lines
6.8 KiB
Go
208 lines
6.8 KiB
Go
package solver
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/containerd/containerd/content"
|
|
digest "github.com/opencontainers/go-digest"
|
|
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
|
)
|
|
|
|
// Vertex is a node in a build graph. It defines an interface for a
|
|
// content-addressable operation and its inputs.
|
|
type Vertex interface {
|
|
// Digest returns a checksum of the definition up to the vertex including
|
|
// all of its inputs.
|
|
Digest() digest.Digest
|
|
|
|
// Sys returns an object used to resolve the executor for this vertex.
|
|
// In LLB solver, this value would be of type `llb.Op`.
|
|
Sys() interface{}
|
|
|
|
// Options return metadata associated with the vertex that doesn't change the
|
|
// definition or equality check of it.
|
|
Options() VertexOptions
|
|
|
|
// Inputs returns an array of edges the vertex depends on. An input edge is
|
|
// a vertex and an index from the returned array of results from an executor
|
|
// returned by Sys(). A vertex may have zero inputs.
|
|
Inputs() []Edge
|
|
|
|
Name() string
|
|
}
|
|
|
|
// Index is an index value for the return array of an operation. Index starts
|
|
// counting from zero.
|
|
type Index int
|
|
|
|
// Edge is a connection point between vertexes. An edge references a specific
|
|
// output of a vertex's operation. Edges are used as inputs to other vertexes.
|
|
type Edge struct {
|
|
Index Index
|
|
Vertex Vertex
|
|
}
|
|
|
|
// VertexOptions define optional metadata for a vertex that doesn't change the
|
|
// definition or equality check of it. These options are not contained in the
|
|
// vertex digest.
|
|
type VertexOptions struct {
|
|
IgnoreCache bool
|
|
CacheSources []CacheManager
|
|
Description map[string]string // text values with no special meaning for solver
|
|
ExportCache *bool
|
|
// WorkerConstraint
|
|
}
|
|
|
|
// Result is an abstract return value for a solve
|
|
type Result interface {
|
|
ID() string
|
|
Release(context.Context) error
|
|
Sys() interface{}
|
|
}
|
|
|
|
// CachedResult is a result connected with its cache key
|
|
type CachedResult interface {
|
|
Result
|
|
CacheKeys() []ExportableCacheKey
|
|
}
|
|
|
|
// CacheExportMode is the type for setting cache exporting modes
|
|
type CacheExportMode int
|
|
|
|
const (
|
|
// CacheExportModeMin exports a topmost allowed vertex and its dependencies
|
|
// that already have transferable layers
|
|
CacheExportModeMin CacheExportMode = iota
|
|
// CacheExportModeMax exports all possible non-root vertexes
|
|
CacheExportModeMax
|
|
// CacheExportModeRemoteOnly only exports vertexes that already have
|
|
// transferable layers
|
|
CacheExportModeRemoteOnly
|
|
)
|
|
|
|
// CacheExportOpt defines options for exporting build cache
|
|
type CacheExportOpt struct {
|
|
// Convert can convert a build result to transferable object
|
|
Convert func(context.Context, Result) (*Remote, error)
|
|
// Mode defines a cache export algorithm
|
|
Mode CacheExportMode
|
|
}
|
|
|
|
// CacheExporter can export the artifacts of the build chain
|
|
type CacheExporter interface {
|
|
ExportTo(ctx context.Context, t CacheExporterTarget, opt CacheExportOpt) ([]CacheExporterRecord, error)
|
|
}
|
|
|
|
// CacheExporterTarget defines object capable of receiving exports
|
|
type CacheExporterTarget interface {
|
|
Add(dgst digest.Digest) CacheExporterRecord
|
|
Visit(interface{})
|
|
Visited(interface{}) bool
|
|
}
|
|
|
|
// CacheExporterRecord is a single object being exported
|
|
type CacheExporterRecord interface {
|
|
AddResult(createdAt time.Time, result *Remote)
|
|
LinkFrom(src CacheExporterRecord, index int, selector string)
|
|
}
|
|
|
|
// Remote is a descriptor or a list of stacked descriptors that can be pulled
|
|
// from a content provider
|
|
// TODO: add closer to keep referenced data from getting deleted
|
|
type Remote struct {
|
|
Descriptors []ocispec.Descriptor
|
|
Provider content.Provider
|
|
}
|
|
|
|
// CacheLink is a link between two cache records
|
|
type CacheLink struct {
|
|
Source digest.Digest `json:",omitempty"`
|
|
Input Index `json:",omitempty"`
|
|
Output Index `json:",omitempty"`
|
|
Base digest.Digest `json:",omitempty"`
|
|
Selector digest.Digest `json:",omitempty"`
|
|
}
|
|
|
|
// Op defines how the solver can evaluate the properties of a vertex operation.
|
|
// An op is executed in the worker, and is retrieved from the vertex by the
|
|
// value of `vertex.Sys()`. The solver is configured with a resolve function to
|
|
// convert a `vertex.Sys()` into an `Op`.
|
|
type Op interface {
|
|
// CacheMap returns structure describing how the operation is cached.
|
|
// Currently only roots are allowed to return multiple cache maps per op.
|
|
CacheMap(context.Context, int) (*CacheMap, bool, error)
|
|
|
|
// Exec runs an operation given results from previous operations.
|
|
Exec(ctx context.Context, inputs []Result) (outputs []Result, err error)
|
|
}
|
|
|
|
type ResultBasedCacheFunc func(context.Context, Result) (digest.Digest, error)
|
|
|
|
// CacheMap is a description for calculating the cache key of an operation.
|
|
type CacheMap struct {
|
|
// Digest returns a checksum for the operation. The operation result can be
|
|
// cached by a checksum that combines this digest and the cache keys of the
|
|
// operation's inputs.
|
|
//
|
|
// For example, in LLB this digest is a manifest digest for OCI images, or
|
|
// commit SHA for git sources.
|
|
Digest digest.Digest
|
|
|
|
// Deps contain optional selectors or content-based cache functions for its
|
|
// inputs.
|
|
Deps []struct {
|
|
// Selector is a digest that is merged with the cache key of the input.
|
|
// Selectors are not merged with the result of the `ComputeDigestFunc` for
|
|
// this input.
|
|
Selector digest.Digest
|
|
|
|
// ComputeDigestFunc should return a digest for the input based on its return
|
|
// value.
|
|
//
|
|
// For example, in LLB this is invoked to calculate the cache key based on
|
|
// the checksum of file contents from input snapshots.
|
|
ComputeDigestFunc ResultBasedCacheFunc
|
|
}
|
|
}
|
|
|
|
// ExportableCacheKey is a cache key connected with an exporter that can export
|
|
// a chain of cacherecords pointing to that key
|
|
type ExportableCacheKey struct {
|
|
*CacheKey
|
|
Exporter CacheExporter
|
|
}
|
|
|
|
// CacheRecord is an identifier for loading in cache
|
|
type CacheRecord struct {
|
|
ID string
|
|
Size int
|
|
CreatedAt time.Time
|
|
Priority int
|
|
|
|
cacheManager *cacheManager
|
|
key *CacheKey
|
|
}
|
|
|
|
// CacheManager determines if there is a result that matches the cache keys
|
|
// generated during the build that could be reused instead of fully
|
|
// reevaluating the vertex and its inputs. There can be multiple cache
|
|
// managers, and specific managers can be defined per vertex using
|
|
// `VertexOptions`.
|
|
type CacheManager interface {
|
|
// ID is used to identify cache providers that are backed by same source
|
|
// to avoid duplicate calls to the same provider.
|
|
ID() string
|
|
|
|
// Query searches for cache paths from one cache key to the output of a
|
|
// possible match.
|
|
Query(inp []CacheKeyWithSelector, inputIndex Index, dgst digest.Digest, outputIndex Index) ([]*CacheKey, error)
|
|
Records(ck *CacheKey) ([]*CacheRecord, error)
|
|
|
|
// Load loads a cache record into a result reference.
|
|
Load(ctx context.Context, rec *CacheRecord) (Result, error)
|
|
|
|
// Save saves a result based on a cache key
|
|
Save(key *CacheKey, s Result, createdAt time.Time) (*ExportableCacheKey, error)
|
|
}
|