mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 18:13:42 +08:00 
			
		
		
		
	Bump github.com/gogo/googleapis to v1.3.2 Bump github.com/docker/cli to master Signed-off-by: Silvin Lubecki <silvin.lubecki@docker.com>
		
			
				
	
	
		
			429 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			429 lines
		
	
	
		
			9.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package llb
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	_ "crypto/sha256"
 | 
						|
	"encoding/json"
 | 
						|
	"os"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"github.com/docker/distribution/reference"
 | 
						|
	"github.com/moby/buildkit/solver/pb"
 | 
						|
	"github.com/moby/buildkit/util/apicaps"
 | 
						|
	digest "github.com/opencontainers/go-digest"
 | 
						|
	"github.com/pkg/errors"
 | 
						|
)
 | 
						|
 | 
						|
type SourceOp struct {
 | 
						|
	MarshalCache
 | 
						|
	id          string
 | 
						|
	attrs       map[string]string
 | 
						|
	output      Output
 | 
						|
	constraints Constraints
 | 
						|
	err         error
 | 
						|
}
 | 
						|
 | 
						|
func NewSource(id string, attrs map[string]string, c Constraints) *SourceOp {
 | 
						|
	s := &SourceOp{
 | 
						|
		id:          id,
 | 
						|
		attrs:       attrs,
 | 
						|
		constraints: c,
 | 
						|
	}
 | 
						|
	s.output = &output{vertex: s, platform: c.Platform}
 | 
						|
	return s
 | 
						|
}
 | 
						|
 | 
						|
func (s *SourceOp) Validate() error {
 | 
						|
	if s.err != nil {
 | 
						|
		return s.err
 | 
						|
	}
 | 
						|
	if s.id == "" {
 | 
						|
		return errors.Errorf("source identifier can't be empty")
 | 
						|
	}
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func (s *SourceOp) Marshal(constraints *Constraints) (digest.Digest, []byte, *pb.OpMetadata, error) {
 | 
						|
	if s.Cached(constraints) {
 | 
						|
		return s.Load()
 | 
						|
	}
 | 
						|
	if err := s.Validate(); err != nil {
 | 
						|
		return "", nil, nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	if strings.HasPrefix(s.id, "local://") {
 | 
						|
		if _, hasSession := s.attrs[pb.AttrLocalSessionID]; !hasSession {
 | 
						|
			uid := s.constraints.LocalUniqueID
 | 
						|
			if uid == "" {
 | 
						|
				uid = constraints.LocalUniqueID
 | 
						|
			}
 | 
						|
			s.attrs[pb.AttrLocalUniqueID] = uid
 | 
						|
			addCap(&s.constraints, pb.CapSourceLocalUnique)
 | 
						|
		}
 | 
						|
	}
 | 
						|
	proto, md := MarshalConstraints(constraints, &s.constraints)
 | 
						|
 | 
						|
	proto.Op = &pb.Op_Source{
 | 
						|
		Source: &pb.SourceOp{Identifier: s.id, Attrs: s.attrs},
 | 
						|
	}
 | 
						|
 | 
						|
	if !platformSpecificSource(s.id) {
 | 
						|
		proto.Platform = nil
 | 
						|
	}
 | 
						|
 | 
						|
	dt, err := proto.Marshal()
 | 
						|
	if err != nil {
 | 
						|
		return "", nil, nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	s.Store(dt, md, constraints)
 | 
						|
	return s.Load()
 | 
						|
}
 | 
						|
 | 
						|
func (s *SourceOp) Output() Output {
 | 
						|
	return s.output
 | 
						|
}
 | 
						|
 | 
						|
func (s *SourceOp) Inputs() []Output {
 | 
						|
	return nil
 | 
						|
}
 | 
						|
 | 
						|
func Image(ref string, opts ...ImageOption) State {
 | 
						|
	r, err := reference.ParseNormalizedNamed(ref)
 | 
						|
	if err == nil {
 | 
						|
		ref = reference.TagNameOnly(r).String()
 | 
						|
	}
 | 
						|
	var info ImageInfo
 | 
						|
	for _, opt := range opts {
 | 
						|
		opt.SetImageOption(&info)
 | 
						|
	}
 | 
						|
 | 
						|
	addCap(&info.Constraints, pb.CapSourceImage)
 | 
						|
 | 
						|
	attrs := map[string]string{}
 | 
						|
	if info.resolveMode != 0 {
 | 
						|
		attrs[pb.AttrImageResolveMode] = info.resolveMode.String()
 | 
						|
		if info.resolveMode == ResolveModeForcePull {
 | 
						|
			addCap(&info.Constraints, pb.CapSourceImageResolveMode) // only require cap for security enforced mode
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if info.RecordType != "" {
 | 
						|
		attrs[pb.AttrImageRecordType] = info.RecordType
 | 
						|
	}
 | 
						|
 | 
						|
	src := NewSource("docker-image://"+ref, attrs, info.Constraints) // controversial
 | 
						|
	if err != nil {
 | 
						|
		src.err = err
 | 
						|
	}
 | 
						|
	if info.metaResolver != nil {
 | 
						|
		_, dt, err := info.metaResolver.ResolveImageConfig(context.TODO(), ref, ResolveImageConfigOpt{
 | 
						|
			Platform:    info.Constraints.Platform,
 | 
						|
			ResolveMode: info.resolveMode.String(),
 | 
						|
		})
 | 
						|
		if err != nil {
 | 
						|
			src.err = err
 | 
						|
		} else {
 | 
						|
			st, err := NewState(src.Output()).WithImageConfig(dt)
 | 
						|
			if err == nil {
 | 
						|
				return st
 | 
						|
			}
 | 
						|
			src.err = err
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return NewState(src.Output())
 | 
						|
}
 | 
						|
 | 
						|
type ImageOption interface {
 | 
						|
	SetImageOption(*ImageInfo)
 | 
						|
}
 | 
						|
 | 
						|
type imageOptionFunc func(*ImageInfo)
 | 
						|
 | 
						|
func (fn imageOptionFunc) SetImageOption(ii *ImageInfo) {
 | 
						|
	fn(ii)
 | 
						|
}
 | 
						|
 | 
						|
var MarkImageInternal = imageOptionFunc(func(ii *ImageInfo) {
 | 
						|
	ii.RecordType = "internal"
 | 
						|
})
 | 
						|
 | 
						|
type ResolveMode int
 | 
						|
 | 
						|
const (
 | 
						|
	ResolveModeDefault ResolveMode = iota
 | 
						|
	ResolveModeForcePull
 | 
						|
	ResolveModePreferLocal
 | 
						|
)
 | 
						|
 | 
						|
func (r ResolveMode) SetImageOption(ii *ImageInfo) {
 | 
						|
	ii.resolveMode = r
 | 
						|
}
 | 
						|
 | 
						|
func (r ResolveMode) String() string {
 | 
						|
	switch r {
 | 
						|
	case ResolveModeDefault:
 | 
						|
		return pb.AttrImageResolveModeDefault
 | 
						|
	case ResolveModeForcePull:
 | 
						|
		return pb.AttrImageResolveModeForcePull
 | 
						|
	case ResolveModePreferLocal:
 | 
						|
		return pb.AttrImageResolveModePreferLocal
 | 
						|
	default:
 | 
						|
		return ""
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
type ImageInfo struct {
 | 
						|
	constraintsWrapper
 | 
						|
	metaResolver ImageMetaResolver
 | 
						|
	resolveMode  ResolveMode
 | 
						|
	RecordType   string
 | 
						|
}
 | 
						|
 | 
						|
func Git(remote, ref string, opts ...GitOption) State {
 | 
						|
	url := ""
 | 
						|
 | 
						|
	for _, prefix := range []string{
 | 
						|
		"http://", "https://", "git://", "git@",
 | 
						|
	} {
 | 
						|
		if strings.HasPrefix(remote, prefix) {
 | 
						|
			url = strings.Split(remote, "#")[0]
 | 
						|
			remote = strings.TrimPrefix(remote, prefix)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	id := remote
 | 
						|
 | 
						|
	if ref != "" {
 | 
						|
		id += "#" + ref
 | 
						|
	}
 | 
						|
 | 
						|
	gi := &GitInfo{}
 | 
						|
	for _, o := range opts {
 | 
						|
		o.SetGitOption(gi)
 | 
						|
	}
 | 
						|
	attrs := map[string]string{}
 | 
						|
	if gi.KeepGitDir {
 | 
						|
		attrs[pb.AttrKeepGitDir] = "true"
 | 
						|
		addCap(&gi.Constraints, pb.CapSourceGitKeepDir)
 | 
						|
	}
 | 
						|
	if url != "" {
 | 
						|
		attrs[pb.AttrFullRemoteURL] = url
 | 
						|
		addCap(&gi.Constraints, pb.CapSourceGitFullURL)
 | 
						|
	}
 | 
						|
 | 
						|
	addCap(&gi.Constraints, pb.CapSourceGit)
 | 
						|
 | 
						|
	source := NewSource("git://"+id, attrs, gi.Constraints)
 | 
						|
	return NewState(source.Output())
 | 
						|
}
 | 
						|
 | 
						|
type GitOption interface {
 | 
						|
	SetGitOption(*GitInfo)
 | 
						|
}
 | 
						|
type gitOptionFunc func(*GitInfo)
 | 
						|
 | 
						|
func (fn gitOptionFunc) SetGitOption(gi *GitInfo) {
 | 
						|
	fn(gi)
 | 
						|
}
 | 
						|
 | 
						|
type GitInfo struct {
 | 
						|
	constraintsWrapper
 | 
						|
	KeepGitDir bool
 | 
						|
}
 | 
						|
 | 
						|
func KeepGitDir() GitOption {
 | 
						|
	return gitOptionFunc(func(gi *GitInfo) {
 | 
						|
		gi.KeepGitDir = true
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func Scratch() State {
 | 
						|
	return NewState(nil)
 | 
						|
}
 | 
						|
 | 
						|
func Local(name string, opts ...LocalOption) State {
 | 
						|
	gi := &LocalInfo{}
 | 
						|
 | 
						|
	for _, o := range opts {
 | 
						|
		o.SetLocalOption(gi)
 | 
						|
	}
 | 
						|
	attrs := map[string]string{}
 | 
						|
	if gi.SessionID != "" {
 | 
						|
		attrs[pb.AttrLocalSessionID] = gi.SessionID
 | 
						|
		addCap(&gi.Constraints, pb.CapSourceLocalSessionID)
 | 
						|
	}
 | 
						|
	if gi.IncludePatterns != "" {
 | 
						|
		attrs[pb.AttrIncludePatterns] = gi.IncludePatterns
 | 
						|
		addCap(&gi.Constraints, pb.CapSourceLocalIncludePatterns)
 | 
						|
	}
 | 
						|
	if gi.FollowPaths != "" {
 | 
						|
		attrs[pb.AttrFollowPaths] = gi.FollowPaths
 | 
						|
		addCap(&gi.Constraints, pb.CapSourceLocalFollowPaths)
 | 
						|
	}
 | 
						|
	if gi.ExcludePatterns != "" {
 | 
						|
		attrs[pb.AttrExcludePatterns] = gi.ExcludePatterns
 | 
						|
		addCap(&gi.Constraints, pb.CapSourceLocalExcludePatterns)
 | 
						|
	}
 | 
						|
	if gi.SharedKeyHint != "" {
 | 
						|
		attrs[pb.AttrSharedKeyHint] = gi.SharedKeyHint
 | 
						|
		addCap(&gi.Constraints, pb.CapSourceLocalSharedKeyHint)
 | 
						|
	}
 | 
						|
 | 
						|
	addCap(&gi.Constraints, pb.CapSourceLocal)
 | 
						|
 | 
						|
	source := NewSource("local://"+name, attrs, gi.Constraints)
 | 
						|
	return NewState(source.Output())
 | 
						|
}
 | 
						|
 | 
						|
type LocalOption interface {
 | 
						|
	SetLocalOption(*LocalInfo)
 | 
						|
}
 | 
						|
 | 
						|
type localOptionFunc func(*LocalInfo)
 | 
						|
 | 
						|
func (fn localOptionFunc) SetLocalOption(li *LocalInfo) {
 | 
						|
	fn(li)
 | 
						|
}
 | 
						|
 | 
						|
func SessionID(id string) LocalOption {
 | 
						|
	return localOptionFunc(func(li *LocalInfo) {
 | 
						|
		li.SessionID = id
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func IncludePatterns(p []string) LocalOption {
 | 
						|
	return localOptionFunc(func(li *LocalInfo) {
 | 
						|
		if len(p) == 0 {
 | 
						|
			li.IncludePatterns = ""
 | 
						|
			return
 | 
						|
		}
 | 
						|
		dt, _ := json.Marshal(p) // empty on error
 | 
						|
		li.IncludePatterns = string(dt)
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func FollowPaths(p []string) LocalOption {
 | 
						|
	return localOptionFunc(func(li *LocalInfo) {
 | 
						|
		if len(p) == 0 {
 | 
						|
			li.FollowPaths = ""
 | 
						|
			return
 | 
						|
		}
 | 
						|
		dt, _ := json.Marshal(p) // empty on error
 | 
						|
		li.FollowPaths = string(dt)
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func ExcludePatterns(p []string) LocalOption {
 | 
						|
	return localOptionFunc(func(li *LocalInfo) {
 | 
						|
		if len(p) == 0 {
 | 
						|
			li.ExcludePatterns = ""
 | 
						|
			return
 | 
						|
		}
 | 
						|
		dt, _ := json.Marshal(p) // empty on error
 | 
						|
		li.ExcludePatterns = string(dt)
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func SharedKeyHint(h string) LocalOption {
 | 
						|
	return localOptionFunc(func(li *LocalInfo) {
 | 
						|
		li.SharedKeyHint = h
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
type LocalInfo struct {
 | 
						|
	constraintsWrapper
 | 
						|
	SessionID       string
 | 
						|
	IncludePatterns string
 | 
						|
	ExcludePatterns string
 | 
						|
	FollowPaths     string
 | 
						|
	SharedKeyHint   string
 | 
						|
}
 | 
						|
 | 
						|
func HTTP(url string, opts ...HTTPOption) State {
 | 
						|
	hi := &HTTPInfo{}
 | 
						|
	for _, o := range opts {
 | 
						|
		o.SetHTTPOption(hi)
 | 
						|
	}
 | 
						|
	attrs := map[string]string{}
 | 
						|
	if hi.Checksum != "" {
 | 
						|
		attrs[pb.AttrHTTPChecksum] = hi.Checksum.String()
 | 
						|
		addCap(&hi.Constraints, pb.CapSourceHTTPChecksum)
 | 
						|
	}
 | 
						|
	if hi.Filename != "" {
 | 
						|
		attrs[pb.AttrHTTPFilename] = hi.Filename
 | 
						|
	}
 | 
						|
	if hi.Perm != 0 {
 | 
						|
		attrs[pb.AttrHTTPPerm] = "0" + strconv.FormatInt(int64(hi.Perm), 8)
 | 
						|
		addCap(&hi.Constraints, pb.CapSourceHTTPPerm)
 | 
						|
	}
 | 
						|
	if hi.UID != 0 {
 | 
						|
		attrs[pb.AttrHTTPUID] = strconv.Itoa(hi.UID)
 | 
						|
		addCap(&hi.Constraints, pb.CapSourceHTTPUIDGID)
 | 
						|
	}
 | 
						|
	if hi.GID != 0 {
 | 
						|
		attrs[pb.AttrHTTPGID] = strconv.Itoa(hi.GID)
 | 
						|
		addCap(&hi.Constraints, pb.CapSourceHTTPUIDGID)
 | 
						|
	}
 | 
						|
 | 
						|
	addCap(&hi.Constraints, pb.CapSourceHTTP)
 | 
						|
	source := NewSource(url, attrs, hi.Constraints)
 | 
						|
	return NewState(source.Output())
 | 
						|
}
 | 
						|
 | 
						|
type HTTPInfo struct {
 | 
						|
	constraintsWrapper
 | 
						|
	Checksum digest.Digest
 | 
						|
	Filename string
 | 
						|
	Perm     int
 | 
						|
	UID      int
 | 
						|
	GID      int
 | 
						|
}
 | 
						|
 | 
						|
type HTTPOption interface {
 | 
						|
	SetHTTPOption(*HTTPInfo)
 | 
						|
}
 | 
						|
 | 
						|
type httpOptionFunc func(*HTTPInfo)
 | 
						|
 | 
						|
func (fn httpOptionFunc) SetHTTPOption(hi *HTTPInfo) {
 | 
						|
	fn(hi)
 | 
						|
}
 | 
						|
 | 
						|
func Checksum(dgst digest.Digest) HTTPOption {
 | 
						|
	return httpOptionFunc(func(hi *HTTPInfo) {
 | 
						|
		hi.Checksum = dgst
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func Chmod(perm os.FileMode) HTTPOption {
 | 
						|
	return httpOptionFunc(func(hi *HTTPInfo) {
 | 
						|
		hi.Perm = int(perm) & 0777
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func Filename(name string) HTTPOption {
 | 
						|
	return httpOptionFunc(func(hi *HTTPInfo) {
 | 
						|
		hi.Filename = name
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func Chown(uid, gid int) HTTPOption {
 | 
						|
	return httpOptionFunc(func(hi *HTTPInfo) {
 | 
						|
		hi.UID = uid
 | 
						|
		hi.GID = gid
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func platformSpecificSource(id string) bool {
 | 
						|
	return strings.HasPrefix(id, "docker-image://")
 | 
						|
}
 | 
						|
 | 
						|
func addCap(c *Constraints, id apicaps.CapID) {
 | 
						|
	if c.Metadata.Caps == nil {
 | 
						|
		c.Metadata.Caps = make(map[apicaps.CapID]bool)
 | 
						|
	}
 | 
						|
	c.Metadata.Caps[id] = true
 | 
						|
}
 |