123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279 |
- package source
- import (
- "encoding/json"
- "strconv"
- "strings"
- "github.com/containerd/containerd/reference"
- "github.com/moby/buildkit/client"
- "github.com/moby/buildkit/solver/pb"
- digest "github.com/opencontainers/go-digest"
- specs "github.com/opencontainers/image-spec/specs-go/v1"
- "github.com/pkg/errors"
- )
- var (
- errInvalid = errors.New("invalid")
- errNotFound = errors.New("not found")
- )
- type ResolveMode int
- const (
- ResolveModeDefault ResolveMode = iota
- ResolveModeForcePull
- ResolveModePreferLocal
- )
- const (
- DockerImageScheme = "docker-image"
- GitScheme = "git"
- LocalScheme = "local"
- HttpScheme = "http"
- HttpsScheme = "https"
- )
- type Identifier interface {
- ID() string // until sources are in process this string comparison could be avoided
- }
- func FromString(s string) (Identifier, error) {
- // TODO: improve this
- parts := strings.SplitN(s, "://", 2)
- if len(parts) != 2 {
- return nil, errors.Wrapf(errInvalid, "failed to parse %s", s)
- }
- switch parts[0] {
- case DockerImageScheme:
- return NewImageIdentifier(parts[1])
- case GitScheme:
- return NewGitIdentifier(parts[1])
- case LocalScheme:
- return NewLocalIdentifier(parts[1])
- case HttpsScheme:
- return NewHttpIdentifier(parts[1], true)
- case HttpScheme:
- return NewHttpIdentifier(parts[1], false)
- default:
- return nil, errors.Wrapf(errNotFound, "unknown schema %s", parts[0])
- }
- }
- func FromLLB(op *pb.Op_Source, platform *pb.Platform) (Identifier, error) {
- id, err := FromString(op.Source.Identifier)
- if err != nil {
- return nil, err
- }
- if id, ok := id.(*ImageIdentifier); ok {
- if platform != nil {
- id.Platform = &specs.Platform{
- OS: platform.OS,
- Architecture: platform.Architecture,
- Variant: platform.Variant,
- OSVersion: platform.OSVersion,
- OSFeatures: platform.OSFeatures,
- }
- }
- for k, v := range op.Source.Attrs {
- switch k {
- case pb.AttrImageResolveMode:
- rm, err := ParseImageResolveMode(v)
- if err != nil {
- return nil, err
- }
- id.ResolveMode = rm
- case pb.AttrImageRecordType:
- rt, err := parseImageRecordType(v)
- if err != nil {
- return nil, err
- }
- id.RecordType = rt
- }
- }
- }
- if id, ok := id.(*GitIdentifier); ok {
- for k, v := range op.Source.Attrs {
- switch k {
- case pb.AttrKeepGitDir:
- if v == "true" {
- id.KeepGitDir = true
- }
- case pb.AttrFullRemoteURL:
- id.Remote = v
- case pb.AttrAuthHeaderSecret:
- id.AuthHeaderSecret = v
- case pb.AttrAuthTokenSecret:
- id.AuthTokenSecret = v
- }
- }
- }
- if id, ok := id.(*LocalIdentifier); ok {
- for k, v := range op.Source.Attrs {
- switch k {
- case pb.AttrLocalSessionID:
- id.SessionID = v
- if p := strings.SplitN(v, ":", 2); len(p) == 2 {
- id.Name = p[0] + "-" + id.Name
- id.SessionID = p[1]
- }
- case pb.AttrIncludePatterns:
- var patterns []string
- if err := json.Unmarshal([]byte(v), &patterns); err != nil {
- return nil, err
- }
- id.IncludePatterns = patterns
- case pb.AttrExcludePatterns:
- var patterns []string
- if err := json.Unmarshal([]byte(v), &patterns); err != nil {
- return nil, err
- }
- id.ExcludePatterns = patterns
- case pb.AttrFollowPaths:
- var paths []string
- if err := json.Unmarshal([]byte(v), &paths); err != nil {
- return nil, err
- }
- id.FollowPaths = paths
- case pb.AttrSharedKeyHint:
- id.SharedKeyHint = v
- }
- }
- }
- if id, ok := id.(*HttpIdentifier); ok {
- for k, v := range op.Source.Attrs {
- switch k {
- case pb.AttrHTTPChecksum:
- dgst, err := digest.Parse(v)
- if err != nil {
- return nil, err
- }
- id.Checksum = dgst
- case pb.AttrHTTPFilename:
- id.Filename = v
- case pb.AttrHTTPPerm:
- i, err := strconv.ParseInt(v, 0, 64)
- if err != nil {
- return nil, err
- }
- id.Perm = int(i)
- case pb.AttrHTTPUID:
- i, err := strconv.ParseInt(v, 0, 64)
- if err != nil {
- return nil, err
- }
- id.UID = int(i)
- case pb.AttrHTTPGID:
- i, err := strconv.ParseInt(v, 0, 64)
- if err != nil {
- return nil, err
- }
- id.GID = int(i)
- }
- }
- }
- return id, nil
- }
- type ImageIdentifier struct {
- Reference reference.Spec
- Platform *specs.Platform
- ResolveMode ResolveMode
- RecordType client.UsageRecordType
- }
- func NewImageIdentifier(str string) (*ImageIdentifier, error) {
- ref, err := reference.Parse(str)
- if err != nil {
- return nil, errors.WithStack(err)
- }
- if ref.Object == "" {
- return nil, errors.WithStack(reference.ErrObjectRequired)
- }
- return &ImageIdentifier{Reference: ref}, nil
- }
- func (_ *ImageIdentifier) ID() string {
- return DockerImageScheme
- }
- type LocalIdentifier struct {
- Name string
- SessionID string
- IncludePatterns []string
- ExcludePatterns []string
- FollowPaths []string
- SharedKeyHint string
- }
- func NewLocalIdentifier(str string) (*LocalIdentifier, error) {
- return &LocalIdentifier{Name: str}, nil
- }
- func (*LocalIdentifier) ID() string {
- return LocalScheme
- }
- func NewHttpIdentifier(str string, tls bool) (*HttpIdentifier, error) {
- proto := "https://"
- if !tls {
- proto = "http://"
- }
- return &HttpIdentifier{TLS: tls, URL: proto + str}, nil
- }
- type HttpIdentifier struct {
- TLS bool
- URL string
- Checksum digest.Digest
- Filename string
- Perm int
- UID int
- GID int
- }
- func (_ *HttpIdentifier) ID() string {
- return HttpsScheme
- }
- func (r ResolveMode) String() string {
- switch r {
- case ResolveModeDefault:
- return pb.AttrImageResolveModeDefault
- case ResolveModeForcePull:
- return pb.AttrImageResolveModeForcePull
- case ResolveModePreferLocal:
- return pb.AttrImageResolveModePreferLocal
- default:
- return ""
- }
- }
- func ParseImageResolveMode(v string) (ResolveMode, error) {
- switch v {
- case pb.AttrImageResolveModeDefault, "":
- return ResolveModeDefault, nil
- case pb.AttrImageResolveModeForcePull:
- return ResolveModeForcePull, nil
- case pb.AttrImageResolveModePreferLocal:
- return ResolveModePreferLocal, nil
- default:
- return 0, errors.Errorf("invalid resolvemode: %s", v)
- }
- }
- func parseImageRecordType(v string) (client.UsageRecordType, error) {
- switch client.UsageRecordType(v) {
- case "", client.UsageRecordTypeRegular:
- return client.UsageRecordTypeRegular, nil
- case client.UsageRecordTypeInternal:
- return client.UsageRecordTypeInternal, nil
- case client.UsageRecordTypeFrontend:
- return client.UsageRecordTypeFrontend, nil
- default:
- return "", errors.Errorf("invalid record type %s", v)
- }
- }
|