mirror of
https://gitea.com/Lydanne/buildx.git
synced 2025-07-09 21:17:09 +08:00
vendor: github.com/moby/buildkit v0.21.0-rc1
Signed-off-by: Jonathan A. Sternberg <jonathan.sternberg@docker.com>
This commit is contained in:
2
vendor/github.com/moby/buildkit/client/llb/exec.go
generated
vendored
2
vendor/github.com/moby/buildkit/client/llb/exec.go
generated
vendored
@ -614,7 +614,7 @@ func Shlex(str string) RunOption {
|
||||
})
|
||||
}
|
||||
|
||||
func Shlexf(str string, v ...interface{}) RunOption {
|
||||
func Shlexf(str string, v ...any) RunOption {
|
||||
return runOptionFunc(func(ei *ExecInfo) {
|
||||
ei.State = shlexf(str, true, v...)(ei.State)
|
||||
})
|
||||
|
5
vendor/github.com/moby/buildkit/client/llb/marshal.go
generated
vendored
5
vendor/github.com/moby/buildkit/client/llb/marshal.go
generated
vendored
@ -2,6 +2,7 @@ package llb
|
||||
|
||||
import (
|
||||
"io"
|
||||
"slices"
|
||||
"sync"
|
||||
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
@ -84,7 +85,7 @@ func ReadFrom(r io.Reader) (*Definition, error) {
|
||||
|
||||
func MarshalConstraints(base, override *Constraints) (*pb.Op, *pb.OpMetadata) {
|
||||
c := *base
|
||||
c.WorkerConstraints = append([]string{}, c.WorkerConstraints...)
|
||||
c.WorkerConstraints = slices.Clone(c.WorkerConstraints)
|
||||
|
||||
if p := override.Platform; p != nil {
|
||||
c.Platform = p
|
||||
@ -105,7 +106,7 @@ func MarshalConstraints(base, override *Constraints) (*pb.Op, *pb.OpMetadata) {
|
||||
OSVersion: c.Platform.OSVersion,
|
||||
}
|
||||
if c.Platform.OSFeatures != nil {
|
||||
opPlatform.OSFeatures = append([]string{}, c.Platform.OSFeatures...)
|
||||
opPlatform.OSFeatures = slices.Clone(c.Platform.OSFeatures)
|
||||
}
|
||||
|
||||
return &pb.Op{
|
||||
|
18
vendor/github.com/moby/buildkit/client/llb/meta.go
generated
vendored
18
vendor/github.com/moby/buildkit/client/llb/meta.go
generated
vendored
@ -35,7 +35,7 @@ var (
|
||||
|
||||
// AddEnvf is the same as [AddEnv] but allows for a format string.
|
||||
// This is the equivalent of `[State.AddEnvf]`
|
||||
func AddEnvf(key, value string, v ...interface{}) StateOption {
|
||||
func AddEnvf(key, value string, v ...any) StateOption {
|
||||
return addEnvf(key, value, true, v...)
|
||||
}
|
||||
|
||||
@ -46,12 +46,12 @@ func AddEnv(key, value string) StateOption {
|
||||
return addEnvf(key, value, false)
|
||||
}
|
||||
|
||||
func addEnvf(key, value string, replace bool, v ...interface{}) StateOption {
|
||||
func addEnvf(key, value string, replace bool, v ...any) StateOption {
|
||||
if replace {
|
||||
value = fmt.Sprintf(value, v...)
|
||||
}
|
||||
return func(s State) State {
|
||||
return s.withValue(keyEnv, func(ctx context.Context, c *Constraints) (interface{}, error) {
|
||||
return s.withValue(keyEnv, func(ctx context.Context, c *Constraints) (any, error) {
|
||||
env, err := getEnv(s)(ctx, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -69,16 +69,16 @@ func Dir(str string) StateOption {
|
||||
}
|
||||
|
||||
// Dirf is the same as [Dir] but allows for a format string.
|
||||
func Dirf(str string, v ...interface{}) StateOption {
|
||||
func Dirf(str string, v ...any) StateOption {
|
||||
return dirf(str, true, v...)
|
||||
}
|
||||
|
||||
func dirf(value string, replace bool, v ...interface{}) StateOption {
|
||||
func dirf(value string, replace bool, v ...any) StateOption {
|
||||
if replace {
|
||||
value = fmt.Sprintf(value, v...)
|
||||
}
|
||||
return func(s State) State {
|
||||
return s.withValue(keyDir, func(ctx context.Context, c *Constraints) (interface{}, error) {
|
||||
return s.withValue(keyDir, func(ctx context.Context, c *Constraints) (any, error) {
|
||||
if !path.IsAbs(value) {
|
||||
prev, err := getDir(s)(ctx, c)
|
||||
if err != nil {
|
||||
@ -213,7 +213,7 @@ func args(args ...string) StateOption {
|
||||
}
|
||||
}
|
||||
|
||||
func shlexf(str string, replace bool, v ...interface{}) StateOption {
|
||||
func shlexf(str string, replace bool, v ...any) StateOption {
|
||||
if replace {
|
||||
str = fmt.Sprintf(str, v...)
|
||||
}
|
||||
@ -248,7 +248,7 @@ func getPlatform(s State) func(context.Context, *Constraints) (*ocispecs.Platfor
|
||||
|
||||
func extraHost(host string, ip net.IP) StateOption {
|
||||
return func(s State) State {
|
||||
return s.withValue(keyExtraHost, func(ctx context.Context, c *Constraints) (interface{}, error) {
|
||||
return s.withValue(keyExtraHost, func(ctx context.Context, c *Constraints) (any, error) {
|
||||
v, err := getExtraHosts(s)(ctx, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -278,7 +278,7 @@ type HostIP struct {
|
||||
|
||||
func ulimit(name UlimitName, soft int64, hard int64) StateOption {
|
||||
return func(s State) State {
|
||||
return s.withValue(keyUlimit, func(ctx context.Context, c *Constraints) (interface{}, error) {
|
||||
return s.withValue(keyUlimit, func(ctx context.Context, c *Constraints) (any, error) {
|
||||
v, err := getUlimit(s)(ctx, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
77
vendor/github.com/moby/buildkit/client/llb/source.go
generated
vendored
77
vendor/github.com/moby/buildkit/client/llb/source.go
generated
vendored
@ -360,13 +360,6 @@ func AuthTokenSecret(v string) GitOption {
|
||||
})
|
||||
}
|
||||
|
||||
func AuthHeaderSecret(v string) GitOption {
|
||||
return gitOptionFunc(func(gi *GitInfo) {
|
||||
gi.AuthHeaderSecret = v
|
||||
gi.addAuthCap = true
|
||||
})
|
||||
}
|
||||
|
||||
func KnownSSHHosts(key string) GitOption {
|
||||
key = strings.TrimSuffix(key, "\n")
|
||||
return gitOptionFunc(func(gi *GitInfo) {
|
||||
@ -380,6 +373,29 @@ func MountSSHSock(sshID string) GitOption {
|
||||
})
|
||||
}
|
||||
|
||||
// AuthOption can be used with either HTTP or Git sources.
|
||||
type AuthOption interface {
|
||||
GitOption
|
||||
HTTPOption
|
||||
}
|
||||
|
||||
// AuthHeaderSecret returns an AuthOption that defines the name of a
|
||||
// secret to use for HTTP based authentication.
|
||||
func AuthHeaderSecret(secretName string) AuthOption {
|
||||
return struct {
|
||||
GitOption
|
||||
HTTPOption
|
||||
}{
|
||||
GitOption: gitOptionFunc(func(gi *GitInfo) {
|
||||
gi.AuthHeaderSecret = secretName
|
||||
gi.addAuthCap = true
|
||||
}),
|
||||
HTTPOption: httpOptionFunc(func(hi *HTTPInfo) {
|
||||
hi.AuthHeaderSecret = secretName
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
// Scratch returns a state that represents an empty filesystem.
|
||||
func Scratch() State {
|
||||
return NewState(nil)
|
||||
@ -595,6 +611,14 @@ func HTTP(url string, opts ...HTTPOption) State {
|
||||
attrs[pb.AttrHTTPGID] = strconv.Itoa(hi.GID)
|
||||
addCap(&hi.Constraints, pb.CapSourceHTTPUIDGID)
|
||||
}
|
||||
if hi.AuthHeaderSecret != "" {
|
||||
attrs[pb.AttrHTTPAuthHeaderSecret] = hi.AuthHeaderSecret
|
||||
addCap(&hi.Constraints, pb.CapSourceHTTPAuth)
|
||||
}
|
||||
if hi.Header != nil {
|
||||
hi.Header.setAttrs(attrs)
|
||||
addCap(&hi.Constraints, pb.CapSourceHTTPHeader)
|
||||
}
|
||||
|
||||
addCap(&hi.Constraints, pb.CapSourceHTTP)
|
||||
source := NewSource(url, attrs, hi.Constraints)
|
||||
@ -603,11 +627,13 @@ func HTTP(url string, opts ...HTTPOption) State {
|
||||
|
||||
type HTTPInfo struct {
|
||||
constraintsWrapper
|
||||
Checksum digest.Digest
|
||||
Filename string
|
||||
Perm int
|
||||
UID int
|
||||
GID int
|
||||
Checksum digest.Digest
|
||||
Filename string
|
||||
Perm int
|
||||
UID int
|
||||
GID int
|
||||
AuthHeaderSecret string
|
||||
Header *HTTPHeader
|
||||
}
|
||||
|
||||
type HTTPOption interface {
|
||||
@ -645,6 +671,33 @@ func Chown(uid, gid int) HTTPOption {
|
||||
})
|
||||
}
|
||||
|
||||
// Header returns an [HTTPOption] that ensures additional request headers will
|
||||
// be sent when retrieving the HTTP source.
|
||||
func Header(header HTTPHeader) HTTPOption {
|
||||
return httpOptionFunc(func(hi *HTTPInfo) {
|
||||
hi.Header = &header
|
||||
})
|
||||
}
|
||||
|
||||
type HTTPHeader struct {
|
||||
Accept string
|
||||
UserAgent string
|
||||
}
|
||||
|
||||
func (hh *HTTPHeader) setAttrs(attrs map[string]string) {
|
||||
if hh.Accept != "" {
|
||||
attrs[hh.attr("accept")] = hh.Accept
|
||||
}
|
||||
|
||||
if hh.UserAgent != "" {
|
||||
attrs[hh.attr("user-agent")] = hh.UserAgent
|
||||
}
|
||||
}
|
||||
|
||||
func (hh *HTTPHeader) attr(name string) string {
|
||||
return pb.AttrHTTPHeaderPrefix + name
|
||||
}
|
||||
|
||||
func platformSpecificSource(id string) bool {
|
||||
return strings.HasPrefix(id, "docker-image://") || strings.HasPrefix(id, "oci-layout://")
|
||||
}
|
||||
|
27
vendor/github.com/moby/buildkit/client/llb/state.go
generated
vendored
27
vendor/github.com/moby/buildkit/client/llb/state.go
generated
vendored
@ -6,6 +6,7 @@ import (
|
||||
"fmt"
|
||||
"maps"
|
||||
"net"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/platforms"
|
||||
@ -59,8 +60,8 @@ func NewState(o Output) State {
|
||||
type State struct {
|
||||
out Output
|
||||
prev *State
|
||||
key interface{}
|
||||
value func(context.Context, *Constraints) (interface{}, error)
|
||||
key any
|
||||
value func(context.Context, *Constraints) (any, error)
|
||||
opts []ConstraintsOpt
|
||||
async *asyncState
|
||||
}
|
||||
@ -76,13 +77,13 @@ func (s State) ensurePlatform() State {
|
||||
return s
|
||||
}
|
||||
|
||||
func (s State) WithValue(k, v interface{}) State {
|
||||
return s.withValue(k, func(context.Context, *Constraints) (interface{}, error) {
|
||||
func (s State) WithValue(k, v any) State {
|
||||
return s.withValue(k, func(context.Context, *Constraints) (any, error) {
|
||||
return v, nil
|
||||
})
|
||||
}
|
||||
|
||||
func (s State) withValue(k interface{}, v func(context.Context, *Constraints) (interface{}, error)) State {
|
||||
func (s State) withValue(k any, v func(context.Context, *Constraints) (any, error)) State {
|
||||
return State{
|
||||
out: s.Output(),
|
||||
prev: &s, // doesn't need to be original pointer
|
||||
@ -91,7 +92,7 @@ func (s State) withValue(k interface{}, v func(context.Context, *Constraints) (i
|
||||
}
|
||||
}
|
||||
|
||||
func (s State) Value(ctx context.Context, k interface{}, co ...ConstraintsOpt) (interface{}, error) {
|
||||
func (s State) Value(ctx context.Context, k any, co ...ConstraintsOpt) (any, error) {
|
||||
c := &Constraints{}
|
||||
for _, f := range co {
|
||||
f.SetConstraintsOption(c)
|
||||
@ -99,12 +100,12 @@ func (s State) Value(ctx context.Context, k interface{}, co ...ConstraintsOpt) (
|
||||
return s.getValue(k)(ctx, c)
|
||||
}
|
||||
|
||||
func (s State) getValue(k interface{}) func(context.Context, *Constraints) (interface{}, error) {
|
||||
func (s State) getValue(k any) func(context.Context, *Constraints) (any, error) {
|
||||
if s.key == k {
|
||||
return s.value
|
||||
}
|
||||
if s.async != nil {
|
||||
return func(ctx context.Context, c *Constraints) (interface{}, error) {
|
||||
return func(ctx context.Context, c *Constraints) (any, error) {
|
||||
target, err := s.async.Do(ctx, c)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -271,7 +272,7 @@ func (s State) WithImageConfig(c []byte) (State, error) {
|
||||
OSVersion: img.OSVersion,
|
||||
}
|
||||
if img.OSFeatures != nil {
|
||||
plat.OSFeatures = append([]string{}, img.OSFeatures...)
|
||||
plat.OSFeatures = slices.Clone(img.OSFeatures)
|
||||
}
|
||||
s = s.Platform(plat)
|
||||
}
|
||||
@ -321,7 +322,7 @@ func (s State) AddEnv(key, value string) State {
|
||||
}
|
||||
|
||||
// AddEnvf is the same as [State.AddEnv] but with a format string.
|
||||
func (s State) AddEnvf(key, value string, v ...interface{}) State {
|
||||
func (s State) AddEnvf(key, value string, v ...any) State {
|
||||
return AddEnvf(key, value, v...)(s)
|
||||
}
|
||||
|
||||
@ -332,7 +333,7 @@ func (s State) Dir(str string) State {
|
||||
}
|
||||
|
||||
// Dirf is the same as [State.Dir] but with a format string.
|
||||
func (s State) Dirf(str string, v ...interface{}) State {
|
||||
func (s State) Dirf(str string, v ...any) State {
|
||||
return Dirf(str, v...)(s)
|
||||
}
|
||||
|
||||
@ -608,7 +609,7 @@ func WithCustomName(name string) ConstraintsOpt {
|
||||
})
|
||||
}
|
||||
|
||||
func WithCustomNamef(name string, a ...interface{}) ConstraintsOpt {
|
||||
func WithCustomNamef(name string, a ...any) ConstraintsOpt {
|
||||
return WithCustomName(fmt.Sprintf(name, a...))
|
||||
}
|
||||
|
||||
@ -746,6 +747,6 @@ func Require(filters ...string) ConstraintsOpt {
|
||||
})
|
||||
}
|
||||
|
||||
func nilValue(context.Context, *Constraints) (interface{}, error) {
|
||||
func nilValue(context.Context, *Constraints) (any, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
10
vendor/github.com/moby/buildkit/client/solve.go
generated
vendored
10
vendor/github.com/moby/buildkit/client/solve.go
generated
vendored
@ -142,9 +142,7 @@ func (c *Client) solve(ctx context.Context, def *llb.Definition, runGateway runG
|
||||
}
|
||||
|
||||
contentStores := map[string]content.Store{}
|
||||
for key, store := range cacheOpt.contentStores {
|
||||
contentStores[key] = store
|
||||
}
|
||||
maps.Copy(contentStores, cacheOpt.contentStores)
|
||||
for key, store := range opt.OCIStores {
|
||||
key2 := "oci:" + key
|
||||
if _, ok := contentStores[key2]; ok {
|
||||
@ -361,7 +359,7 @@ func (c *Client) solve(ctx context.Context, def *llb.Definition, runGateway runG
|
||||
}
|
||||
for _, storePath := range storesToUpdate {
|
||||
names := []ociindex.NameOrTag{ociindex.Tag("latest")}
|
||||
if t, ok := res.ExporterResponse["image.name"]; ok {
|
||||
if t, ok := res.ExporterResponse[exptypes.ExporterImageNameKey]; ok {
|
||||
inp := strings.Split(t, ",")
|
||||
names = make([]ociindex.NameOrTag, len(inp))
|
||||
for i, n := range inp {
|
||||
@ -538,9 +536,7 @@ func parseCacheOptions(ctx context.Context, isGateway bool, opt SolveOpt) (*cach
|
||||
func prepareMounts(opt *SolveOpt) (map[string]fsutil.FS, error) {
|
||||
// merge local mounts and fallback local directories together
|
||||
mounts := make(map[string]fsutil.FS)
|
||||
for k, mount := range opt.LocalMounts {
|
||||
mounts[k] = mount
|
||||
}
|
||||
maps.Copy(mounts, opt.LocalMounts)
|
||||
for k, dir := range opt.LocalDirs {
|
||||
mount, err := fsutil.NewFS(dir)
|
||||
if err != nil {
|
||||
|
8
vendor/github.com/moby/buildkit/cmd/buildkitd/config/config.go
generated
vendored
8
vendor/github.com/moby/buildkit/cmd/buildkitd/config/config.go
generated
vendored
@ -121,7 +121,7 @@ type OCIConfig struct {
|
||||
// StargzSnapshotterConfig is configuration for stargz snapshotter.
|
||||
// We use a generic map[string]interface{} in order to remove the dependency
|
||||
// on stargz snapshotter's config pkg from our config.
|
||||
StargzSnapshotterConfig map[string]interface{} `toml:"stargzSnapshotter"`
|
||||
StargzSnapshotterConfig map[string]any `toml:"stargzSnapshotter"`
|
||||
|
||||
// ApparmorProfile is the name of the apparmor profile that should be used to constrain build containers.
|
||||
// The profile should already be loaded (by a higher level system) before creating a worker.
|
||||
@ -160,9 +160,9 @@ type ContainerdConfig struct {
|
||||
}
|
||||
|
||||
type ContainerdRuntime struct {
|
||||
Name string `toml:"name"`
|
||||
Path string `toml:"path"`
|
||||
Options map[string]interface{} `toml:"options"`
|
||||
Name string `toml:"name"`
|
||||
Path string `toml:"path"`
|
||||
Options map[string]any `toml:"options"`
|
||||
}
|
||||
|
||||
type GCPolicy struct {
|
||||
|
10
vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/keys.go
generated
vendored
10
vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/keys.go
generated
vendored
@ -26,11 +26,17 @@ var (
|
||||
// Value: bool <true|false>
|
||||
OptKeyUnpack ImageExporterOptKey = "unpack"
|
||||
|
||||
// Fallback image name prefix if image name isn't provided.
|
||||
// If used, image will be named as <value>@<digest>
|
||||
// Image name prefix to be used for tagging a dangling image.
|
||||
// If used, image will be named as <value>@<digest> in addition
|
||||
// to any other specified names.
|
||||
// Value: string
|
||||
OptKeyDanglingPrefix ImageExporterOptKey = "dangling-name-prefix"
|
||||
|
||||
// Only use the dangling image name as a fallback if image name isn't provided.
|
||||
// Ignored if dangling-name-prefix is not set.
|
||||
// Value: bool <true|false>
|
||||
OptKeyDanglingEmptyOnly ImageExporterOptKey = "danging-name-empty-only"
|
||||
|
||||
// Creates additional image name with format <name>@<digest>
|
||||
// Value: bool <true|false>
|
||||
OptKeyNameCanonical ImageExporterOptKey = "name-canonical"
|
||||
|
4
vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/parse.go
generated
vendored
4
vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/parse.go
generated
vendored
@ -32,7 +32,7 @@ func ParsePlatforms(meta map[string][]byte) (Platforms, error) {
|
||||
return ps, nil
|
||||
}
|
||||
|
||||
p := platforms.DefaultSpec()
|
||||
var p ocispecs.Platform
|
||||
if imgConfig, ok := meta[ExporterImageConfigKey]; ok {
|
||||
var img ocispecs.Image
|
||||
err := json.Unmarshal(imgConfig, &img)
|
||||
@ -51,6 +51,8 @@ func ParsePlatforms(meta map[string][]byte) (Platforms, error) {
|
||||
} else if img.OS != "" || img.Architecture != "" {
|
||||
return Platforms{}, errors.Errorf("invalid image config: os and architecture must be specified together")
|
||||
}
|
||||
} else {
|
||||
p = platforms.DefaultSpec()
|
||||
}
|
||||
p = platforms.Normalize(p)
|
||||
pk := platforms.FormatAll(p)
|
||||
|
1
vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/types.go
generated
vendored
1
vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/types.go
generated
vendored
@ -9,6 +9,7 @@ import (
|
||||
|
||||
const (
|
||||
ExporterConfigDigestKey = "config.digest"
|
||||
ExporterImageNameKey = "image.name"
|
||||
ExporterImageDigestKey = "containerimage.digest"
|
||||
ExporterImageConfigKey = "containerimage.config"
|
||||
ExporterImageConfigDigestKey = "containerimage.config.digest"
|
||||
|
16
vendor/github.com/moby/buildkit/frontend/dockerfile/parser/directives.go
generated
vendored
16
vendor/github.com/moby/buildkit/frontend/dockerfile/parser/directives.go
generated
vendored
@ -148,14 +148,16 @@ func parseDirective(key string, dt []byte, anyFormat bool) (string, string, []Ra
|
||||
}
|
||||
|
||||
// use json directive, and search for { "key": "..." }
|
||||
jsonDirective := map[string]string{}
|
||||
jsonDirective := map[string]any{}
|
||||
if err := json.Unmarshal(dt, &jsonDirective); err == nil {
|
||||
if v, ok := jsonDirective[key]; ok {
|
||||
loc := []Range{{
|
||||
Start: Position{Line: line},
|
||||
End: Position{Line: line},
|
||||
}}
|
||||
return v, v, loc, true
|
||||
if vAny, ok := jsonDirective[key]; ok {
|
||||
if v, ok := vAny.(string); ok {
|
||||
loc := []Range{{
|
||||
Start: Position{Line: line},
|
||||
End: Position{Line: line},
|
||||
}}
|
||||
return v, v, loc, true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
2
vendor/github.com/moby/buildkit/frontend/dockerfile/parser/line_parsers.go
generated
vendored
2
vendor/github.com/moby/buildkit/frontend/dockerfile/parser/line_parsers.go
generated
vendored
@ -281,7 +281,7 @@ func parseJSON(rest string) (*Node, map[string]bool, error) {
|
||||
return nil, nil, errDockerfileNotJSONArray
|
||||
}
|
||||
|
||||
var myJSON []interface{}
|
||||
var myJSON []any
|
||||
if err := json.Unmarshal([]byte(rest), &myJSON); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
2
vendor/github.com/moby/buildkit/frontend/dockerfile/parser/parser.go
generated
vendored
2
vendor/github.com/moby/buildkit/frontend/dockerfile/parser/parser.go
generated
vendored
@ -220,7 +220,7 @@ func init() {
|
||||
// based on the command and command arguments. A Node is created from the
|
||||
// result of the dispatch.
|
||||
func newNodeFromLine(line string, d *directives, comments []string) (*Node, error) {
|
||||
cmd, flags, args, err := splitCommand(line)
|
||||
cmd, flags, args, err := splitCommand(line, d)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
10
vendor/github.com/moby/buildkit/frontend/dockerfile/parser/split_command.go
generated
vendored
10
vendor/github.com/moby/buildkit/frontend/dockerfile/parser/split_command.go
generated
vendored
@ -7,7 +7,7 @@ import (
|
||||
|
||||
// splitCommand takes a single line of text and parses out the cmd and args,
|
||||
// which are used for dispatching to more exact parsing functions.
|
||||
func splitCommand(line string) (string, []string, string, error) {
|
||||
func splitCommand(line string, d *directives) (string, []string, string, error) {
|
||||
var args string
|
||||
var flags []string
|
||||
|
||||
@ -16,7 +16,7 @@ func splitCommand(line string) (string, []string, string, error) {
|
||||
|
||||
if len(cmdline) == 2 {
|
||||
var err error
|
||||
args, flags, err = extractBuilderFlags(cmdline[1])
|
||||
args, flags, err = extractBuilderFlags(cmdline[1], d)
|
||||
if err != nil {
|
||||
return "", nil, "", err
|
||||
}
|
||||
@ -25,7 +25,7 @@ func splitCommand(line string) (string, []string, string, error) {
|
||||
return cmdline[0], flags, strings.TrimSpace(args), nil
|
||||
}
|
||||
|
||||
func extractBuilderFlags(line string) (string, []string, error) {
|
||||
func extractBuilderFlags(line string, d *directives) (string, []string, error) {
|
||||
// Parses the BuilderFlags and returns the remaining part of the line
|
||||
|
||||
const (
|
||||
@ -87,7 +87,7 @@ func extractBuilderFlags(line string) (string, []string, error) {
|
||||
phase = inQuote
|
||||
continue
|
||||
}
|
||||
if ch == '\\' {
|
||||
if ch == d.escapeToken {
|
||||
if pos+1 == len(line) {
|
||||
continue // just skip \ at end
|
||||
}
|
||||
@ -104,7 +104,7 @@ func extractBuilderFlags(line string) (string, []string, error) {
|
||||
phase = inWord
|
||||
continue
|
||||
}
|
||||
if ch == '\\' {
|
||||
if ch == d.escapeToken {
|
||||
if pos+1 == len(line) {
|
||||
phase = inWord
|
||||
continue // just skip \ at end
|
||||
|
31
vendor/github.com/moby/buildkit/frontend/dockerui/build.go
generated
vendored
31
vendor/github.com/moby/buildkit/frontend/dockerui/build.go
generated
vendored
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"slices"
|
||||
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/moby/buildkit/exporter/containerimage/exptypes"
|
||||
@ -54,23 +55,16 @@ func (bc *Client) Build(ctx context.Context, fn BuildFunc) (*ResultBuilder, erro
|
||||
}
|
||||
}
|
||||
|
||||
p := platforms.DefaultSpec()
|
||||
var p ocispecs.Platform
|
||||
if tp != nil {
|
||||
p = *tp
|
||||
} else {
|
||||
p = platforms.DefaultSpec()
|
||||
}
|
||||
|
||||
// in certain conditions we allow input platform to be extended from base image
|
||||
if p.OS == "windows" && img.OS == p.OS {
|
||||
if p.OSVersion == "" && img.OSVersion != "" {
|
||||
p.OSVersion = img.OSVersion
|
||||
}
|
||||
if p.OSFeatures == nil && len(img.OSFeatures) > 0 {
|
||||
p.OSFeatures = append([]string{}, img.OSFeatures...)
|
||||
}
|
||||
}
|
||||
|
||||
p = platforms.Normalize(p)
|
||||
k := platforms.FormatAll(p)
|
||||
p = extendWindowsPlatform(p, img.Platform)
|
||||
p = platforms.Normalize(p)
|
||||
|
||||
if bc.MultiPlatformRequested {
|
||||
res.AddRef(k, ref)
|
||||
@ -126,3 +120,16 @@ func (rb *ResultBuilder) EachPlatform(ctx context.Context, fn func(ctx context.C
|
||||
}
|
||||
return eg.Wait()
|
||||
}
|
||||
|
||||
func extendWindowsPlatform(p, imgP ocispecs.Platform) ocispecs.Platform {
|
||||
// in certain conditions we allow input platform to be extended from base image
|
||||
if p.OS == "windows" && imgP.OS == p.OS {
|
||||
if p.OSVersion == "" && imgP.OSVersion != "" {
|
||||
p.OSVersion = imgP.OSVersion
|
||||
}
|
||||
if p.OSFeatures == nil && len(imgP.OSFeatures) > 0 {
|
||||
p.OSFeatures = slices.Clone(imgP.OSFeatures)
|
||||
}
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
8
vendor/github.com/moby/buildkit/frontend/dockerui/config.go
generated
vendored
8
vendor/github.com/moby/buildkit/frontend/dockerui/config.go
generated
vendored
@ -148,9 +148,11 @@ func (bc *Client) BuildOpts() client.BuildOpts {
|
||||
func (bc *Client) init() error {
|
||||
opts := bc.bopts.Opts
|
||||
|
||||
defaultBuildPlatform := platforms.Normalize(platforms.DefaultSpec())
|
||||
var defaultBuildPlatform ocispecs.Platform
|
||||
if workers := bc.bopts.Workers; len(workers) > 0 && len(workers[0].Platforms) > 0 {
|
||||
defaultBuildPlatform = workers[0].Platforms[0]
|
||||
} else {
|
||||
defaultBuildPlatform = platforms.Normalize(platforms.DefaultSpec())
|
||||
}
|
||||
buildPlatforms := []ocispecs.Platform{defaultBuildPlatform}
|
||||
targetPlatforms := []ocispecs.Platform{}
|
||||
@ -459,9 +461,11 @@ func (bc *Client) NamedContext(name string, opt ContextOpt) (*NamedContext, erro
|
||||
}
|
||||
name = strings.TrimSuffix(reference.FamiliarString(named), ":latest")
|
||||
|
||||
pp := platforms.DefaultSpec()
|
||||
var pp ocispecs.Platform
|
||||
if opt.Platform != nil {
|
||||
pp = *opt.Platform
|
||||
} else {
|
||||
pp = platforms.DefaultSpec()
|
||||
}
|
||||
pname := name + "::" + platforms.FormatAll(platforms.Normalize(pp))
|
||||
nc, err := bc.namedContext(name, pname, opt)
|
||||
|
2
vendor/github.com/moby/buildkit/frontend/subrequests/lint/lint.go
generated
vendored
2
vendor/github.com/moby/buildkit/frontend/subrequests/lint/lint.go
generated
vendored
@ -134,7 +134,7 @@ func (results *LintResults) ToResult(scb SourceInfoMap) (*client.Result, error)
|
||||
if len(results.Warnings) > 0 || results.Error != nil {
|
||||
status = 1
|
||||
}
|
||||
res.AddMeta("result.statuscode", []byte(fmt.Sprintf("%d", status)))
|
||||
res.AddMeta("result.statuscode", fmt.Appendf(nil, "%d", status))
|
||||
|
||||
res.AddMeta("version", []byte(SubrequestLintDefinition.Version))
|
||||
return res, nil
|
||||
|
5
vendor/github.com/moby/buildkit/session/auth/authprovider/authprovider.go
generated
vendored
5
vendor/github.com/moby/buildkit/session/auth/authprovider/authprovider.go
generated
vendored
@ -45,7 +45,7 @@ type DockerAuthProviderConfig struct {
|
||||
TLSConfigs map[string]*AuthTLSConfig
|
||||
// ExpireCachedAuth is a function that returns true auth config should be refreshed
|
||||
// instead of using a pre-cached result.
|
||||
// If nil then the cached result will expire after 10 minutes.
|
||||
// If nil then the cached result will expire after 4 minutes and 50 seconds.
|
||||
// The function is called with the time the cached auth config was created
|
||||
// and the server URL the auth config is for.
|
||||
ExpireCachedAuth func(created time.Time, serverURL string) bool
|
||||
@ -59,7 +59,8 @@ type authConfigCacheEntry struct {
|
||||
func NewDockerAuthProvider(cfg DockerAuthProviderConfig) session.Attachable {
|
||||
if cfg.ExpireCachedAuth == nil {
|
||||
cfg.ExpireCachedAuth = func(created time.Time, _ string) bool {
|
||||
return time.Since(created) > 10*time.Minute
|
||||
// Tokens for Google Artifact Registry via Workload Identity expire after 5 minutes.
|
||||
return time.Since(created) > 4*time.Minute+50*time.Second
|
||||
}
|
||||
}
|
||||
return &authProvider{
|
||||
|
4
vendor/github.com/moby/buildkit/session/filesync/diffcopy.go
generated
vendored
4
vendor/github.com/moby/buildkit/session/filesync/diffcopy.go
generated
vendored
@ -17,8 +17,8 @@ import (
|
||||
|
||||
type Stream interface {
|
||||
Context() context.Context
|
||||
SendMsg(m interface{}) error
|
||||
RecvMsg(m interface{}) error
|
||||
SendMsg(m any) error
|
||||
RecvMsg(m any) error
|
||||
}
|
||||
|
||||
func newStreamWriter(stream grpc.ClientStream) io.WriteCloser {
|
||||
|
4
vendor/github.com/moby/buildkit/session/grpchijack/dial.go
generated
vendored
4
vendor/github.com/moby/buildkit/session/grpchijack/dial.go
generated
vendored
@ -32,8 +32,8 @@ func Dialer(api controlapi.ControlClient) session.Dialer {
|
||||
|
||||
type stream interface {
|
||||
Context() context.Context
|
||||
SendMsg(m interface{}) error
|
||||
RecvMsg(m interface{}) error
|
||||
SendMsg(m any) error
|
||||
RecvMsg(m any) error
|
||||
}
|
||||
|
||||
func streamToConn(stream stream) (net.Conn, <-chan struct{}) {
|
||||
|
4
vendor/github.com/moby/buildkit/session/sshforward/copy.go
generated
vendored
4
vendor/github.com/moby/buildkit/session/sshforward/copy.go
generated
vendored
@ -9,8 +9,8 @@ import (
|
||||
)
|
||||
|
||||
type Stream interface {
|
||||
SendMsg(m interface{}) error
|
||||
RecvMsg(m interface{}) error
|
||||
SendMsg(m any) error
|
||||
RecvMsg(m any) error
|
||||
}
|
||||
|
||||
func Copy(ctx context.Context, conn io.ReadWriteCloser, stream Stream, closeStream func() error) error {
|
||||
|
27
vendor/github.com/moby/buildkit/session/upload/uploadprovider/provider.go
generated
vendored
27
vendor/github.com/moby/buildkit/session/upload/uploadprovider/provider.go
generated
vendored
@ -63,23 +63,20 @@ type writer struct {
|
||||
grpc.ServerStream
|
||||
}
|
||||
|
||||
func (w *writer) Write(dt []byte) (int, error) {
|
||||
// avoid sending too big messages on grpc stream
|
||||
func (w *writer) Write(dt []byte) (n int, err error) {
|
||||
const maxChunkSize = 3 * 1024 * 1024
|
||||
if len(dt) > maxChunkSize {
|
||||
n1, err := w.Write(dt[:maxChunkSize])
|
||||
if err != nil {
|
||||
return n1, err
|
||||
for len(dt) > 0 {
|
||||
data := dt
|
||||
if len(data) > maxChunkSize {
|
||||
data = data[:maxChunkSize]
|
||||
}
|
||||
dt = dt[maxChunkSize:]
|
||||
var n2 int
|
||||
if n2, err := w.Write(dt); err != nil {
|
||||
return n1 + n2, err
|
||||
|
||||
msg := &upload.BytesMessage{Data: data}
|
||||
if err := w.SendMsg(msg); err != nil {
|
||||
return n, err
|
||||
}
|
||||
return n1 + n2, nil
|
||||
n += len(data)
|
||||
dt = dt[len(data):]
|
||||
}
|
||||
if err := w.SendMsg(&upload.BytesMessage{Data: dt}); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return len(dt), nil
|
||||
return n, nil
|
||||
}
|
||||
|
2
vendor/github.com/moby/buildkit/solver/errdefs/op.go
generated
vendored
2
vendor/github.com/moby/buildkit/solver/errdefs/op.go
generated
vendored
@ -12,7 +12,7 @@ func (e *OpError) Unwrap() error {
|
||||
return e.error
|
||||
}
|
||||
|
||||
func WithOp(err error, anyOp interface{}, opDesc map[string]string) error {
|
||||
func WithOp(err error, anyOp any, opDesc map[string]string) error {
|
||||
op, ok := anyOp.(*pb.Op)
|
||||
if err == nil || !ok {
|
||||
return err
|
||||
|
10
vendor/github.com/moby/buildkit/solver/errdefs/source.go
generated
vendored
10
vendor/github.com/moby/buildkit/solver/errdefs/source.go
generated
vendored
@ -98,10 +98,7 @@ func (s *Source) Print(w io.Writer) error {
|
||||
|
||||
func containsLine(rr []*pb.Range, l int) bool {
|
||||
for _, r := range rr {
|
||||
e := r.End.Line
|
||||
if e < r.Start.Line {
|
||||
e = r.Start.Line
|
||||
}
|
||||
e := max(r.End.Line, r.Start.Line)
|
||||
if r.Start.Line <= int32(l) && e >= int32(l) {
|
||||
return true
|
||||
}
|
||||
@ -112,10 +109,7 @@ func containsLine(rr []*pb.Range, l int) bool {
|
||||
func getStartEndLine(rr []*pb.Range) (start int, end int, ok bool) {
|
||||
first := true
|
||||
for _, r := range rr {
|
||||
e := r.End.Line
|
||||
if e < r.Start.Line {
|
||||
e = r.Start.Line
|
||||
}
|
||||
e := max(r.End.Line, r.Start.Line)
|
||||
if first || int(r.Start.Line) < start {
|
||||
start = int(r.Start.Line)
|
||||
}
|
||||
|
2
vendor/github.com/moby/buildkit/solver/pb/attr.go
generated
vendored
2
vendor/github.com/moby/buildkit/solver/pb/attr.go
generated
vendored
@ -20,6 +20,8 @@ const AttrHTTPFilename = "http.filename"
|
||||
const AttrHTTPPerm = "http.perm"
|
||||
const AttrHTTPUID = "http.uid"
|
||||
const AttrHTTPGID = "http.gid"
|
||||
const AttrHTTPAuthHeaderSecret = "http.authheadersecret"
|
||||
const AttrHTTPHeaderPrefix = "http.header."
|
||||
|
||||
const AttrImageResolveMode = "image.resolvemode"
|
||||
const AttrImageResolveModeDefault = "default"
|
||||
|
19
vendor/github.com/moby/buildkit/solver/pb/caps.go
generated
vendored
19
vendor/github.com/moby/buildkit/solver/pb/caps.go
generated
vendored
@ -31,9 +31,12 @@ const (
|
||||
CapSourceGitSubdir apicaps.CapID = "source.git.subdir"
|
||||
|
||||
CapSourceHTTP apicaps.CapID = "source.http"
|
||||
CapSourceHTTPAuth apicaps.CapID = "source.http.auth"
|
||||
CapSourceHTTPChecksum apicaps.CapID = "source.http.checksum"
|
||||
CapSourceHTTPPerm apicaps.CapID = "source.http.perm"
|
||||
CapSourceHTTPUIDGID apicaps.CapID = "soruce.http.uidgid"
|
||||
// NOTE the historical typo
|
||||
CapSourceHTTPUIDGID apicaps.CapID = "soruce.http.uidgid"
|
||||
CapSourceHTTPHeader apicaps.CapID = "source.http.header"
|
||||
|
||||
CapSourceOCILayout apicaps.CapID = "source.ocilayout"
|
||||
|
||||
@ -230,7 +233,7 @@ func init() {
|
||||
})
|
||||
|
||||
Caps.Init(apicaps.Cap{
|
||||
ID: CapSourceOCILayout,
|
||||
ID: CapSourceHTTPAuth,
|
||||
Enabled: true,
|
||||
Status: apicaps.CapStatusExperimental,
|
||||
})
|
||||
@ -241,6 +244,18 @@ func init() {
|
||||
Status: apicaps.CapStatusExperimental,
|
||||
})
|
||||
|
||||
Caps.Init(apicaps.Cap{
|
||||
ID: CapSourceHTTPHeader,
|
||||
Enabled: true,
|
||||
Status: apicaps.CapStatusExperimental,
|
||||
})
|
||||
|
||||
Caps.Init(apicaps.Cap{
|
||||
ID: CapSourceOCILayout,
|
||||
Enabled: true,
|
||||
Status: apicaps.CapStatusExperimental,
|
||||
})
|
||||
|
||||
Caps.Init(apicaps.Cap{
|
||||
ID: CapBuildOpLLBFileName,
|
||||
Enabled: true,
|
||||
|
6
vendor/github.com/moby/buildkit/solver/pb/platform.go
generated
vendored
6
vendor/github.com/moby/buildkit/solver/pb/platform.go
generated
vendored
@ -1,6 +1,8 @@
|
||||
package pb
|
||||
|
||||
import (
|
||||
"slices"
|
||||
|
||||
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
@ -12,7 +14,7 @@ func (p *Platform) Spec() ocispecs.Platform {
|
||||
OSVersion: p.OSVersion,
|
||||
}
|
||||
if p.OSFeatures != nil {
|
||||
result.OSFeatures = append([]string{}, p.OSFeatures...)
|
||||
result.OSFeatures = slices.Clone(p.OSFeatures)
|
||||
}
|
||||
return result
|
||||
}
|
||||
@ -25,7 +27,7 @@ func PlatformFromSpec(p ocispecs.Platform) *Platform {
|
||||
OSVersion: p.OSVersion,
|
||||
}
|
||||
if p.OSFeatures != nil {
|
||||
result.OSFeatures = append([]string{}, p.OSFeatures...)
|
||||
result.OSFeatures = slices.Clone(p.OSFeatures)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
8
vendor/github.com/moby/buildkit/util/contentutil/source.go
generated
vendored
8
vendor/github.com/moby/buildkit/util/contentutil/source.go
generated
vendored
@ -2,6 +2,7 @@ package contentutil
|
||||
|
||||
import (
|
||||
"net/url"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/containerd/v2/core/content"
|
||||
@ -24,11 +25,8 @@ func HasSource(info content.Info, refspec reference.Spec) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
for _, repo := range strings.Split(repoLabel, ",") {
|
||||
// the target repo is not a candidate
|
||||
if repo == target {
|
||||
return true, nil
|
||||
}
|
||||
if slices.Contains(strings.Split(repoLabel, ","), target) {
|
||||
return true, nil
|
||||
}
|
||||
return false, nil
|
||||
}
|
||||
|
5
vendor/github.com/moby/buildkit/util/flightcontrol/flightcontrol.go
generated
vendored
5
vendor/github.com/moby/buildkit/util/flightcontrol/flightcontrol.go
generated
vendored
@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"io"
|
||||
"math/rand"
|
||||
"slices"
|
||||
"sort"
|
||||
"sync"
|
||||
"time"
|
||||
@ -211,7 +212,7 @@ func (c *call[T]) Err() error {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *call[T]) Value(key interface{}) interface{} {
|
||||
func (c *call[T]) Value(key any) any {
|
||||
if key == contextKey {
|
||||
return c.progressState
|
||||
}
|
||||
@ -353,7 +354,7 @@ func (ps *progressState) close(pw progress.Writer) {
|
||||
for i, w := range ps.writers {
|
||||
if w == rw {
|
||||
w.Close()
|
||||
ps.writers = append(ps.writers[:i], ps.writers[i+1:]...)
|
||||
ps.writers = slices.Delete(ps.writers, i, i+1)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
3
vendor/github.com/moby/buildkit/util/gitutil/git_cli.go
generated
vendored
3
vendor/github.com/moby/buildkit/util/gitutil/git_cli.go
generated
vendored
@ -6,6 +6,7 @@ import (
|
||||
"io"
|
||||
"os"
|
||||
"os/exec"
|
||||
"slices"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@ -120,7 +121,7 @@ func NewGitCLI(opts ...Option) *GitCLI {
|
||||
// with the given options applied on top.
|
||||
func (cli *GitCLI) New(opts ...Option) *GitCLI {
|
||||
clone := *cli
|
||||
clone.args = append([]string{}, cli.args...)
|
||||
clone.args = slices.Clone(cli.args)
|
||||
|
||||
for _, opt := range opts {
|
||||
opt(&clone)
|
||||
|
6
vendor/github.com/moby/buildkit/util/grpcerrors/intercept.go
generated
vendored
6
vendor/github.com/moby/buildkit/util/grpcerrors/intercept.go
generated
vendored
@ -10,7 +10,7 @@ import (
|
||||
"google.golang.org/grpc"
|
||||
)
|
||||
|
||||
func UnaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp interface{}, err error) {
|
||||
func UnaryServerInterceptor(ctx context.Context, req any, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (resp any, err error) {
|
||||
resp, err = handler(ctx, req)
|
||||
oldErr := err
|
||||
if err != nil {
|
||||
@ -29,7 +29,7 @@ func UnaryServerInterceptor(ctx context.Context, req interface{}, info *grpc.Una
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func StreamServerInterceptor(srv interface{}, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||
func StreamServerInterceptor(srv any, ss grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
|
||||
err := ToGRPC(ss.Context(), handler(srv, ss))
|
||||
if err != nil {
|
||||
stack.Helper()
|
||||
@ -37,7 +37,7 @@ func StreamServerInterceptor(srv interface{}, ss grpc.ServerStream, info *grpc.S
|
||||
return err
|
||||
}
|
||||
|
||||
func UnaryClientInterceptor(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
|
||||
func UnaryClientInterceptor(ctx context.Context, method string, req, reply any, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {
|
||||
err := FromGRPC(invoker(ctx, method, req, reply, cc, opts...))
|
||||
if err != nil {
|
||||
stack.Helper()
|
||||
|
8
vendor/github.com/moby/buildkit/util/progress/multiwriter.go
generated
vendored
8
vendor/github.com/moby/buildkit/util/progress/multiwriter.go
generated
vendored
@ -16,7 +16,7 @@ type MultiWriter struct {
|
||||
mu sync.Mutex
|
||||
items []*Progress
|
||||
writers map[rawProgressWriter]struct{}
|
||||
meta map[string]interface{}
|
||||
meta map[string]any
|
||||
}
|
||||
|
||||
var _ rawProgressWriter = &MultiWriter{}
|
||||
@ -24,7 +24,7 @@ var _ rawProgressWriter = &MultiWriter{}
|
||||
func NewMultiWriter(opts ...WriterOption) *MultiWriter {
|
||||
mw := &MultiWriter{
|
||||
writers: map[rawProgressWriter]struct{}{},
|
||||
meta: map[string]interface{}{},
|
||||
meta: map[string]any{},
|
||||
}
|
||||
for _, o := range opts {
|
||||
o(mw)
|
||||
@ -70,7 +70,7 @@ func (ps *MultiWriter) Delete(pw Writer) {
|
||||
ps.mu.Unlock()
|
||||
}
|
||||
|
||||
func (ps *MultiWriter) Write(id string, v interface{}) error {
|
||||
func (ps *MultiWriter) Write(id string, v any) error {
|
||||
p := &Progress{
|
||||
ID: id,
|
||||
Timestamp: time.Now(),
|
||||
@ -83,7 +83,7 @@ func (ps *MultiWriter) Write(id string, v interface{}) error {
|
||||
func (ps *MultiWriter) WriteRawProgress(p *Progress) error {
|
||||
meta := p.meta
|
||||
if len(ps.meta) > 0 {
|
||||
meta = map[string]interface{}{}
|
||||
meta = map[string]any{}
|
||||
maps.Copy(meta, p.meta)
|
||||
for k, v := range ps.meta {
|
||||
if _, ok := meta[k]; !ok {
|
||||
|
20
vendor/github.com/moby/buildkit/util/progress/progress.go
generated
vendored
20
vendor/github.com/moby/buildkit/util/progress/progress.go
generated
vendored
@ -67,7 +67,7 @@ func WithProgress(ctx context.Context, pw Writer) context.Context {
|
||||
return context.WithValue(ctx, contextKey, pw)
|
||||
}
|
||||
|
||||
func WithMetadata(key string, val interface{}) WriterOption {
|
||||
func WithMetadata(key string, val any) WriterOption {
|
||||
return func(w Writer) {
|
||||
if pw, ok := w.(*progressWriter); ok {
|
||||
pw.meta[key] = val
|
||||
@ -84,7 +84,7 @@ type Controller interface {
|
||||
}
|
||||
|
||||
type Writer interface {
|
||||
Write(id string, value interface{}) error
|
||||
Write(id string, value any) error
|
||||
Close() error
|
||||
}
|
||||
|
||||
@ -95,8 +95,8 @@ type Reader interface {
|
||||
type Progress struct {
|
||||
ID string
|
||||
Timestamp time.Time
|
||||
Sys interface{}
|
||||
meta map[string]interface{}
|
||||
Sys any
|
||||
meta map[string]any
|
||||
}
|
||||
|
||||
type Status struct {
|
||||
@ -207,7 +207,7 @@ func pipe() (*progressReader, *progressWriter, func(error)) {
|
||||
}
|
||||
|
||||
func newWriter(pw *progressWriter) *progressWriter {
|
||||
meta := make(map[string]interface{})
|
||||
meta := make(map[string]any)
|
||||
maps.Copy(meta, pw.meta)
|
||||
pw = &progressWriter{
|
||||
reader: pw.reader,
|
||||
@ -220,10 +220,10 @@ func newWriter(pw *progressWriter) *progressWriter {
|
||||
type progressWriter struct {
|
||||
done bool
|
||||
reader *progressReader
|
||||
meta map[string]interface{}
|
||||
meta map[string]any
|
||||
}
|
||||
|
||||
func (pw *progressWriter) Write(id string, v interface{}) error {
|
||||
func (pw *progressWriter) Write(id string, v any) error {
|
||||
if pw.done {
|
||||
return errors.Errorf("writing %s to closed progress writer", id)
|
||||
}
|
||||
@ -238,7 +238,7 @@ func (pw *progressWriter) Write(id string, v interface{}) error {
|
||||
func (pw *progressWriter) WriteRawProgress(p *Progress) error {
|
||||
meta := p.meta
|
||||
if len(pw.meta) > 0 {
|
||||
meta = map[string]interface{}{}
|
||||
meta = map[string]any{}
|
||||
maps.Copy(meta, p.meta)
|
||||
for k, v := range pw.meta {
|
||||
if _, ok := meta[k]; !ok {
|
||||
@ -267,14 +267,14 @@ func (pw *progressWriter) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *Progress) Meta(key string) (interface{}, bool) {
|
||||
func (p *Progress) Meta(key string) (any, bool) {
|
||||
v, ok := p.meta[key]
|
||||
return v, ok
|
||||
}
|
||||
|
||||
type noOpWriter struct{}
|
||||
|
||||
func (pw *noOpWriter) Write(_ string, _ interface{}) error {
|
||||
func (pw *noOpWriter) Write(_ string, _ any) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
|
6
vendor/github.com/moby/buildkit/util/progress/progressui/display.go
generated
vendored
6
vendor/github.com/moby/buildkit/util/progress/progressui/display.go
generated
vendored
@ -765,7 +765,7 @@ func (t *trace) update(s *client.SolveStatus, termWidth int) {
|
||||
} else if sec < 100 {
|
||||
prec = 2
|
||||
}
|
||||
v.logs = append(v.logs, []byte(fmt.Sprintf("%s %s", fmt.Sprintf("%.[2]*[1]f", sec, prec), dt)))
|
||||
v.logs = append(v.logs, fmt.Appendf(nil, "%s %s", fmt.Sprintf("%.[2]*[1]f", sec, prec), dt))
|
||||
}
|
||||
i++
|
||||
})
|
||||
@ -787,7 +787,7 @@ func (t *trace) printErrorLogs(f io.Writer) {
|
||||
}
|
||||
// printer keeps last logs buffer
|
||||
if v.logsBuffer != nil {
|
||||
for i := 0; i < v.logsBuffer.Len(); i++ {
|
||||
for range v.logsBuffer.Len() {
|
||||
if v.logsBuffer.Value != nil {
|
||||
fmt.Fprintln(f, string(v.logsBuffer.Value.([]byte)))
|
||||
}
|
||||
@ -1071,7 +1071,7 @@ func (disp *ttyDisplay) print(d displayInfo, width, height int, all bool) {
|
||||
}
|
||||
// override previous content
|
||||
if diff := disp.lineCount - lineCount; diff > 0 {
|
||||
for i := 0; i < diff; i++ {
|
||||
for range diff {
|
||||
fmt.Fprintln(disp.c, strings.Repeat(" ", width))
|
||||
}
|
||||
fmt.Fprint(disp.c, aec.EmptyBuilder.Up(uint(diff)).Column(0).ANSI)
|
||||
|
4
vendor/github.com/moby/buildkit/util/resolver/retryhandler/retry.go
generated
vendored
4
vendor/github.com/moby/buildkit/util/resolver/retryhandler/retry.go
generated
vendored
@ -33,7 +33,7 @@ func New(f images.HandlerFunc, logger func([]byte)) images.HandlerFunc {
|
||||
}
|
||||
}
|
||||
if logger != nil {
|
||||
logger([]byte(fmt.Sprintf("error: %v\n", err.Error())))
|
||||
logger(fmt.Appendf(nil, "error: %v\n", err.Error()))
|
||||
}
|
||||
} else {
|
||||
return descs, nil
|
||||
@ -43,7 +43,7 @@ func New(f images.HandlerFunc, logger func([]byte)) images.HandlerFunc {
|
||||
return nil, err
|
||||
}
|
||||
if logger != nil {
|
||||
logger([]byte(fmt.Sprintf("retrying in %v\n", backoff)))
|
||||
logger(fmt.Appendf(nil, "retrying in %v\n", backoff))
|
||||
}
|
||||
time.Sleep(backoff)
|
||||
backoff *= 2
|
||||
|
39
vendor/github.com/moby/buildkit/util/system/path.go
generated
vendored
39
vendor/github.com/moby/buildkit/util/system/path.go
generated
vendored
@ -2,7 +2,6 @@ package system
|
||||
|
||||
import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
@ -46,7 +45,7 @@ func NormalizePath(parent, newPath, inputOS string, keepSlash bool) (string, err
|
||||
}
|
||||
|
||||
var err error
|
||||
parent, err = CheckSystemDriveAndRemoveDriveLetter(parent, inputOS)
|
||||
parent, err = CheckSystemDriveAndRemoveDriveLetter(parent, inputOS, keepSlash)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "removing drive letter")
|
||||
}
|
||||
@ -61,7 +60,7 @@ func NormalizePath(parent, newPath, inputOS string, keepSlash bool) (string, err
|
||||
newPath = parent
|
||||
}
|
||||
|
||||
newPath, err = CheckSystemDriveAndRemoveDriveLetter(newPath, inputOS)
|
||||
newPath, err = CheckSystemDriveAndRemoveDriveLetter(newPath, inputOS, keepSlash)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "removing drive letter")
|
||||
}
|
||||
@ -137,7 +136,7 @@ func IsAbs(pth, inputOS string) bool {
|
||||
if inputOS == "" {
|
||||
inputOS = "linux"
|
||||
}
|
||||
cleanedPath, err := CheckSystemDriveAndRemoveDriveLetter(pth, inputOS)
|
||||
cleanedPath, err := CheckSystemDriveAndRemoveDriveLetter(pth, inputOS, false)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
@ -174,7 +173,7 @@ func IsAbs(pth, inputOS string) bool {
|
||||
// There is no sane way to support this without adding a lot of complexity
|
||||
// which I am not sure is worth it.
|
||||
// \\.\C$\a --> Fail
|
||||
func CheckSystemDriveAndRemoveDriveLetter(path string, inputOS string) (string, error) {
|
||||
func CheckSystemDriveAndRemoveDriveLetter(path string, inputOS string, keepSlash bool) (string, error) {
|
||||
if inputOS == "" {
|
||||
inputOS = "linux"
|
||||
}
|
||||
@ -193,9 +192,10 @@ func CheckSystemDriveAndRemoveDriveLetter(path string, inputOS string) (string,
|
||||
}
|
||||
|
||||
parts := strings.SplitN(path, ":", 2)
|
||||
|
||||
// Path does not have a drive letter. Just return it.
|
||||
if len(parts) < 2 {
|
||||
return ToSlash(filepath.Clean(path), inputOS), nil
|
||||
return ToSlash(cleanPath(path, inputOS, keepSlash), inputOS), nil
|
||||
}
|
||||
|
||||
// We expect all paths to be in C:
|
||||
@ -220,5 +220,30 @@ func CheckSystemDriveAndRemoveDriveLetter(path string, inputOS string) (string,
|
||||
//
|
||||
// We must return the second element of the split path, as is, without attempting to convert
|
||||
// it to an absolute path. We have no knowledge of the CWD; that is treated elsewhere.
|
||||
return ToSlash(filepath.Clean(parts[1]), inputOS), nil
|
||||
return ToSlash(cleanPath(parts[1], inputOS, keepSlash), inputOS), nil
|
||||
}
|
||||
|
||||
// An adaptation of filepath.Clean to allow an option to
|
||||
// retain the trailing slash, on either of the platforms.
|
||||
// See https://github.com/moby/buildkit/issues/5249
|
||||
func cleanPath(origPath, inputOS string, keepSlash bool) string {
|
||||
// so as to handle cases like \\a\\b\\..\\c\\
|
||||
// on Linux, when inputOS is Windows
|
||||
origPath = ToSlash(origPath, inputOS)
|
||||
|
||||
if !keepSlash {
|
||||
return path.Clean(origPath)
|
||||
}
|
||||
|
||||
cleanedPath := path.Clean(origPath)
|
||||
// Windows supports both \\ and / as path separator.
|
||||
hasTrailingSlash := strings.HasSuffix(origPath, "/")
|
||||
if inputOS == "windows" {
|
||||
hasTrailingSlash = hasTrailingSlash || strings.HasSuffix(origPath, "\\")
|
||||
}
|
||||
|
||||
if len(cleanedPath) > 1 && hasTrailingSlash {
|
||||
return cleanedPath + "/"
|
||||
}
|
||||
return cleanedPath
|
||||
}
|
||||
|
17
vendor/github.com/moby/buildkit/util/system/path_unix.go
generated
vendored
Normal file
17
vendor/github.com/moby/buildkit/util/system/path_unix.go
generated
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
//go:build !windows
|
||||
|
||||
package system
|
||||
|
||||
import "path/filepath"
|
||||
|
||||
// IsAbsolutePath is just a wrapper that calls filepath.IsAbs.
|
||||
// Has been added here just for symmetry with Windows.
|
||||
func IsAbsolutePath(path string) bool {
|
||||
return filepath.IsAbs(path)
|
||||
}
|
||||
|
||||
// GetAbsolutePath does nothing on non-Windows, just returns
|
||||
// the same path.
|
||||
func GetAbsolutePath(path string) string {
|
||||
return path
|
||||
}
|
29
vendor/github.com/moby/buildkit/util/system/path_windows.go
generated
vendored
Normal file
29
vendor/github.com/moby/buildkit/util/system/path_windows.go
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// DefaultSystemVolumeName is the default system volume label on Windows
|
||||
const DefaultSystemVolumeName = "C:"
|
||||
|
||||
// IsAbsolutePath prepends the default system volume label
|
||||
// to the path that is presumed absolute, and then calls filepath.IsAbs
|
||||
func IsAbsolutePath(path string) bool {
|
||||
path = filepath.Clean(path)
|
||||
if strings.HasPrefix(path, "\\") {
|
||||
path = DefaultSystemVolumeName + path
|
||||
}
|
||||
return filepath.IsAbs(path)
|
||||
}
|
||||
|
||||
// GetAbsolutePath returns an absolute path rooted
|
||||
// to C:\\ on Windows.
|
||||
func GetAbsolutePath(path string) string {
|
||||
path = filepath.Clean(path)
|
||||
if len(path) >= 2 && strings.EqualFold(path[:2], DefaultSystemVolumeName) {
|
||||
return path
|
||||
}
|
||||
return DefaultSystemVolumeName + path
|
||||
}
|
248
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/client.go
generated
vendored
Normal file
248
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/client.go
generated
vendored
Normal file
@ -0,0 +1,248 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// DummyHost is a hostname used for local communication.
|
||||
//
|
||||
// It acts as a valid formatted hostname for local connections (such as "unix://"
|
||||
// or "npipe://") which do not require a hostname. It should never be resolved,
|
||||
// but uses the special-purpose ".localhost" TLD (as defined in [RFC 2606, Section 2]
|
||||
// and [RFC 6761, Section 6.3]).
|
||||
//
|
||||
// [RFC 7230, Section 5.4] defines that an empty header must be used for such
|
||||
// cases:
|
||||
//
|
||||
// If the authority component is missing or undefined for the target URI,
|
||||
// then a client MUST send a Host header field with an empty field-value.
|
||||
//
|
||||
// However, [Go stdlib] enforces the semantics of HTTP(S) over TCP, does not
|
||||
// allow an empty header to be used, and requires req.URL.Scheme to be either
|
||||
// "http" or "https".
|
||||
//
|
||||
// For further details, refer to:
|
||||
//
|
||||
// - https://github.com/docker/engine-api/issues/189
|
||||
// - https://github.com/golang/go/issues/13624
|
||||
// - https://github.com/golang/go/issues/61076
|
||||
// - https://github.com/moby/moby/issues/45935
|
||||
//
|
||||
// [RFC 2606, Section 2]: https://www.rfc-editor.org/rfc/rfc2606.html#section-2
|
||||
// [RFC 6761, Section 6.3]: https://www.rfc-editor.org/rfc/rfc6761#section-6.3
|
||||
// [RFC 7230, Section 5.4]: https://datatracker.ietf.org/doc/html/rfc7230#section-5.4
|
||||
// [Go stdlib]: https://github.com/golang/go/blob/6244b1946bc2101b01955468f1be502dbadd6807/src/net/http/transport.go#L558-L569
|
||||
const DummyHost = "api.moby.localhost"
|
||||
|
||||
// DefaultVersion is the pinned version of the docker API we utilize.
|
||||
const DefaultVersion = "1.47"
|
||||
|
||||
// Client is the API client that performs all operations
|
||||
// against a docker server.
|
||||
type Client struct {
|
||||
// scheme sets the scheme for the client
|
||||
scheme string
|
||||
// host holds the server address to connect to
|
||||
host string
|
||||
// proto holds the client protocol i.e. unix.
|
||||
proto string
|
||||
// addr holds the client address.
|
||||
addr string
|
||||
// basePath holds the path to prepend to the requests.
|
||||
basePath string
|
||||
// client used to send and receive http requests.
|
||||
client *http.Client
|
||||
// version of the server to talk to.
|
||||
version string
|
||||
|
||||
// When the client transport is an *http.Transport (default) we need to do some extra things (like closing idle connections).
|
||||
// Store the original transport as the http.Client transport will be wrapped with tracing libs.
|
||||
baseTransport *http.Transport
|
||||
}
|
||||
|
||||
// ErrRedirect is the error returned by checkRedirect when the request is non-GET.
|
||||
var ErrRedirect = errors.New("unexpected redirect in response")
|
||||
|
||||
// CheckRedirect specifies the policy for dealing with redirect responses. It
|
||||
// can be set on [http.Client.CheckRedirect] to prevent HTTP redirects for
|
||||
// non-GET requests. It returns an [ErrRedirect] for non-GET request, otherwise
|
||||
// returns a [http.ErrUseLastResponse], which is special-cased by http.Client
|
||||
// to use the last response.
|
||||
//
|
||||
// Go 1.8 changed behavior for HTTP redirects (specifically 301, 307, and 308)
|
||||
// in the client. The client (and by extension API client) can be made to send
|
||||
// a request like "POST /containers//start" where what would normally be in the
|
||||
// name section of the URL is empty. This triggers an HTTP 301 from the daemon.
|
||||
//
|
||||
// In go 1.8 this 301 is converted to a GET request, and ends up getting
|
||||
// a 404 from the daemon. This behavior change manifests in the client in that
|
||||
// before, the 301 was not followed and the client did not generate an error,
|
||||
// but now results in a message like "Error response from daemon: page not found".
|
||||
func CheckRedirect(_ *http.Request, via []*http.Request) error {
|
||||
if via[0].Method == http.MethodGet {
|
||||
return http.ErrUseLastResponse
|
||||
}
|
||||
return ErrRedirect
|
||||
}
|
||||
|
||||
// NewClientWithOpts initializes a new API client with a default HTTPClient, and
|
||||
// default API host and version. It also initializes the custom HTTP headers to
|
||||
// add to each request.
|
||||
//
|
||||
// It takes an optional list of [Opt] functional arguments, which are applied in
|
||||
// the order they're provided, which allows modifying the defaults when creating
|
||||
// the client. For example, the following initializes a client that configures
|
||||
// itself with values from environment variables ([FromEnv]), and has automatic
|
||||
// API version negotiation enabled ([WithAPIVersionNegotiation]).
|
||||
//
|
||||
// cli, err := client.NewClientWithOpts(
|
||||
// client.FromEnv,
|
||||
// client.WithAPIVersionNegotiation(),
|
||||
// )
|
||||
func NewClientWithOpts(ops ...Opt) (*Client, error) {
|
||||
hostURL, err := ParseHostURL(DefaultDockerHost)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
client, err := defaultHTTPClient(hostURL)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
c := &Client{
|
||||
host: DefaultDockerHost,
|
||||
version: DefaultVersion,
|
||||
client: client,
|
||||
proto: hostURL.Scheme,
|
||||
addr: hostURL.Host,
|
||||
}
|
||||
|
||||
for _, op := range ops {
|
||||
if err := op(c); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if tr, ok := c.client.Transport.(*http.Transport); ok {
|
||||
// Store the base transport before we wrap it in tracing libs below
|
||||
// This is used, as an example, to close idle connections when the client is closed
|
||||
c.baseTransport = tr
|
||||
}
|
||||
|
||||
if c.scheme == "" {
|
||||
// TODO(stevvooe): This isn't really the right way to write clients in Go.
|
||||
// `NewClient` should probably only take an `*http.Client` and work from there.
|
||||
// Unfortunately, the model of having a host-ish/url-thingy as the connection
|
||||
// string has us confusing protocol and transport layers. We continue doing
|
||||
// this to avoid breaking existing clients but this should be addressed.
|
||||
if c.tlsConfig() != nil {
|
||||
c.scheme = "https"
|
||||
} else {
|
||||
c.scheme = "http"
|
||||
}
|
||||
}
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (cli *Client) tlsConfig() *tls.Config {
|
||||
if cli.baseTransport == nil {
|
||||
return nil
|
||||
}
|
||||
return cli.baseTransport.TLSClientConfig
|
||||
}
|
||||
|
||||
func defaultHTTPClient(hostURL *url.URL) (*http.Client, error) {
|
||||
// Necessary to prevent long-lived processes using the
|
||||
// client from leaking connections due to idle connections
|
||||
// not being released.
|
||||
transport := &http.Transport{
|
||||
MaxIdleConns: 6,
|
||||
IdleConnTimeout: 30 * time.Second,
|
||||
}
|
||||
if err := configureTransport(transport, hostURL.Scheme, hostURL.Host); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &http.Client{
|
||||
Transport: transport,
|
||||
CheckRedirect: CheckRedirect,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Close the transport used by the client
|
||||
func (cli *Client) Close() error {
|
||||
if cli.baseTransport != nil {
|
||||
cli.baseTransport.CloseIdleConnections()
|
||||
return nil
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// ParseHostURL parses a url string, validates the string is a host url, and
|
||||
// returns the parsed URL
|
||||
func ParseHostURL(host string) (*url.URL, error) {
|
||||
proto, addr, ok := strings.Cut(host, "://")
|
||||
if !ok || addr == "" {
|
||||
return nil, errors.Errorf("unable to parse docker host `%s`", host)
|
||||
}
|
||||
|
||||
var basePath string
|
||||
if proto == "tcp" {
|
||||
parsed, err := url.Parse("tcp://" + addr)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
addr = parsed.Host
|
||||
basePath = parsed.Path
|
||||
}
|
||||
return &url.URL{
|
||||
Scheme: proto,
|
||||
Host: addr,
|
||||
Path: basePath,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (cli *Client) dialerFromTransport() func(context.Context, string, string) (net.Conn, error) {
|
||||
if cli.baseTransport == nil || cli.baseTransport.DialContext == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if cli.baseTransport.TLSClientConfig != nil {
|
||||
// When using a tls config we don't use the configured dialer but instead a fallback dialer...
|
||||
// Note: It seems like this should use the normal dialer and wrap the returned net.Conn in a tls.Conn
|
||||
// I honestly don't know why it doesn't do that, but it doesn't and such a change is entirely unrelated to the change in this commit.
|
||||
return nil
|
||||
}
|
||||
return cli.baseTransport.DialContext
|
||||
}
|
||||
|
||||
// Dialer returns a dialer for a raw stream connection, with an HTTP/1.1 header,
|
||||
// that can be used for proxying the daemon connection. It is used by
|
||||
// ["docker dial-stdio"].
|
||||
//
|
||||
// ["docker dial-stdio"]: https://github.com/docker/cli/pull/1014
|
||||
func (cli *Client) Dialer() func(context.Context) (net.Conn, error) {
|
||||
return func(ctx context.Context) (net.Conn, error) {
|
||||
if dialFn := cli.dialerFromTransport(); dialFn != nil {
|
||||
return dialFn(ctx, cli.proto, cli.addr)
|
||||
}
|
||||
switch cli.proto {
|
||||
case "unix":
|
||||
return net.Dial(cli.proto, cli.addr)
|
||||
case "npipe":
|
||||
return DialPipe(cli.addr, 32*time.Second)
|
||||
default:
|
||||
if tlsConfig := cli.tlsConfig(); tlsConfig != nil {
|
||||
return tls.Dial(cli.proto, cli.addr, tlsConfig)
|
||||
}
|
||||
return net.Dial(cli.proto, cli.addr)
|
||||
}
|
||||
}
|
||||
}
|
7
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/client_unix.go
generated
vendored
Normal file
7
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/client_unix.go
generated
vendored
Normal file
@ -0,0 +1,7 @@
|
||||
//go:build !windows
|
||||
|
||||
package client
|
||||
|
||||
// DefaultDockerHost defines OS-specific default host if the DOCKER_HOST
|
||||
// (EnvOverrideHost) environment variable is unset or empty.
|
||||
const DefaultDockerHost = "unix:///var/run/docker.sock"
|
5
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/client_windows.go
generated
vendored
Normal file
5
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/client_windows.go
generated
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
package client
|
||||
|
||||
// DefaultDockerHost defines OS-specific default host if the DOCKER_HOST
|
||||
// (EnvOverrideHost) environment variable is unset or empty.
|
||||
const DefaultDockerHost = "npipe:////./pipe/docker_engine"
|
13
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/errors.go
generated
vendored
Normal file
13
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/errors.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ErrorConnectionFailed returns an error with host in the error message when connection to docker daemon failed.
|
||||
func ErrorConnectionFailed(host string) error {
|
||||
if host == "" {
|
||||
return errors.New("Cannot connect to the Docker daemon. Is the docker daemon running on this host?")
|
||||
}
|
||||
return errors.Errorf("Cannot connect to the Docker daemon at %s. Is the docker daemon running?", host)
|
||||
}
|
118
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/hijack.go
generated
vendored
Normal file
118
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/hijack.go
generated
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// DialHijack returns a hijacked connection with negotiated protocol proto.
|
||||
func (cli *Client) DialHijack(ctx context.Context, url, proto string, meta map[string][]string) (net.Conn, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, url, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
conn, _, err := cli.setupHijackConn(req, proto)
|
||||
return conn, err
|
||||
}
|
||||
|
||||
func (cli *Client) setupHijackConn(req *http.Request, proto string) (_ net.Conn, _ string, retErr error) {
|
||||
ctx := req.Context()
|
||||
req.Header.Set("Connection", "Upgrade")
|
||||
req.Header.Set("Upgrade", proto)
|
||||
|
||||
dialer := cli.Dialer()
|
||||
conn, err := dialer(ctx)
|
||||
if err != nil {
|
||||
return nil, "", errors.Wrap(err, "cannot connect to the Docker daemon. Is 'docker daemon' running on this host?")
|
||||
}
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
conn.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
// When we set up a TCP connection for hijack, there could be long periods
|
||||
// of inactivity (a long running command with no output) that in certain
|
||||
// network setups may cause ECONNTIMEOUT, leaving the client in an unknown
|
||||
// state. Setting TCP KeepAlive on the socket connection will prohibit
|
||||
// ECONNTIMEOUT unless the socket connection truly is broken
|
||||
if tcpConn, ok := conn.(*net.TCPConn); ok {
|
||||
_ = tcpConn.SetKeepAlive(true)
|
||||
_ = tcpConn.SetKeepAlivePeriod(30 * time.Second)
|
||||
}
|
||||
|
||||
hc := &hijackedConn{conn, bufio.NewReader(conn)}
|
||||
|
||||
// Server hijacks the connection, error 'connection closed' expected
|
||||
resp, err := hc.RoundTrip(req)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
if resp.StatusCode != http.StatusSwitchingProtocols {
|
||||
_ = resp.Body.Close()
|
||||
return nil, "", errors.Errorf("unable to upgrade to %s, received %d", proto, resp.StatusCode)
|
||||
}
|
||||
|
||||
if hc.r.Buffered() > 0 {
|
||||
// If there is buffered content, wrap the connection. We return an
|
||||
// object that implements CloseWrite if the underlying connection
|
||||
// implements it.
|
||||
if _, ok := hc.Conn.(CloseWriter); ok {
|
||||
conn = &hijackedConnCloseWriter{hc}
|
||||
} else {
|
||||
conn = hc
|
||||
}
|
||||
} else {
|
||||
hc.r.Reset(nil)
|
||||
}
|
||||
|
||||
mediaType := resp.Header.Get("Content-Type")
|
||||
return conn, mediaType, nil
|
||||
}
|
||||
|
||||
// CloseWriter is an interface that implements structs
|
||||
// that close input streams to prevent from writing.
|
||||
type CloseWriter interface {
|
||||
CloseWrite() error
|
||||
}
|
||||
|
||||
// hijackedConn wraps a net.Conn and is returned by setupHijackConn in the case
|
||||
// that a) there was already buffered data in the http layer when Hijack() was
|
||||
// called, and b) the underlying net.Conn does *not* implement CloseWrite().
|
||||
// hijackedConn does not implement CloseWrite() either.
|
||||
type hijackedConn struct {
|
||||
net.Conn
|
||||
r *bufio.Reader
|
||||
}
|
||||
|
||||
func (c *hijackedConn) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
if err := req.Write(c.Conn); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return http.ReadResponse(c.r, req)
|
||||
}
|
||||
|
||||
func (c *hijackedConn) Read(b []byte) (int, error) {
|
||||
return c.r.Read(b)
|
||||
}
|
||||
|
||||
// hijackedConnCloseWriter is a hijackedConn which additionally implements
|
||||
// CloseWrite(). It is returned by setupHijackConn in the case that a) there
|
||||
// was already buffered data in the http layer when Hijack() was called, and b)
|
||||
// the underlying net.Conn *does* implement CloseWrite().
|
||||
type hijackedConnCloseWriter struct {
|
||||
*hijackedConn
|
||||
}
|
||||
|
||||
var _ CloseWriter = &hijackedConnCloseWriter{}
|
||||
|
||||
func (c *hijackedConnCloseWriter) CloseWrite() error {
|
||||
conn := c.Conn.(CloseWriter)
|
||||
return conn.CloseWrite()
|
||||
}
|
28
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/options.go
generated
vendored
Normal file
28
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/options.go
generated
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// Opt is a configuration option to initialize a [Client].
|
||||
type Opt func(*Client) error
|
||||
|
||||
// WithHost overrides the client host with the specified one.
|
||||
func WithHost(host string) Opt {
|
||||
return func(c *Client) error {
|
||||
hostURL, err := ParseHostURL(host)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.host = host
|
||||
c.proto = hostURL.Scheme
|
||||
c.addr = hostURL.Host
|
||||
c.basePath = hostURL.Path
|
||||
if transport, ok := c.client.Transport.(*http.Transport); ok {
|
||||
return configureTransport(transport, c.proto, c.addr)
|
||||
}
|
||||
return errors.Errorf("cannot apply host to transport: %T", c.client.Transport)
|
||||
}
|
||||
}
|
25
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/ping.go
generated
vendored
Normal file
25
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/ping.go
generated
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"path"
|
||||
)
|
||||
|
||||
type PingResponse struct{}
|
||||
|
||||
func (cli *Client) Ping(ctx context.Context) error {
|
||||
// Using cli.buildRequest() + cli.doRequest() instead of cli.sendRequest()
|
||||
// because ping requests are used during API version negotiation, so we want
|
||||
// to hit the non-versioned /_ping endpoint, not /v1.xx/_ping
|
||||
req, err := cli.buildRequest(ctx, http.MethodHead, path.Join(cli.basePath, "/_ping"), nil, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
serverResp, err := cli.doRequest(req)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer ensureReaderClosed(serverResp)
|
||||
return cli.checkResponseErr(serverResp)
|
||||
}
|
162
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/request.go
generated
vendored
Normal file
162
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/request.go
generated
vendored
Normal file
@ -0,0 +1,162 @@
|
||||
//nolint:forbidigo
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func (cli *Client) buildRequest(ctx context.Context, method, path string, body io.Reader, headers http.Header) (*http.Request, error) {
|
||||
req, err := http.NewRequestWithContext(ctx, method, path, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req = cli.addHeaders(req, headers)
|
||||
req.URL.Scheme = cli.scheme
|
||||
req.URL.Host = cli.addr
|
||||
|
||||
if cli.proto == "unix" || cli.proto == "npipe" {
|
||||
// Override host header for non-tcp connections.
|
||||
req.Host = DummyHost
|
||||
}
|
||||
|
||||
if body != nil && req.Header.Get("Content-Type") == "" {
|
||||
req.Header.Set("Content-Type", "text/plain")
|
||||
}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func (cli *Client) doRequest(req *http.Request) (*http.Response, error) {
|
||||
resp, err := cli.client.Do(req)
|
||||
if err != nil {
|
||||
if cli.scheme != "https" && strings.Contains(err.Error(), "malformed HTTP response") {
|
||||
return nil, errors.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err)
|
||||
}
|
||||
|
||||
if cli.scheme == "https" && strings.Contains(err.Error(), "bad certificate") {
|
||||
return nil, errors.Wrap(err, "the server probably has client authentication (--tlsverify) enabled; check your TLS client certification settings")
|
||||
}
|
||||
|
||||
// Don't decorate context sentinel errors; users may be comparing to
|
||||
// them directly.
|
||||
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if uErr, ok := err.(*url.Error); ok {
|
||||
if nErr, ok := uErr.Err.(*net.OpError); ok {
|
||||
if os.IsPermission(nErr.Err) {
|
||||
return nil, errors.Wrapf(err, "permission denied while trying to connect to the Docker daemon socket at %v", cli.host)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if nErr, ok := err.(net.Error); ok {
|
||||
// FIXME(thaJeztah): any net.Error should be considered a connection error (but we should include the original error)?
|
||||
if nErr.Timeout() {
|
||||
return nil, ErrorConnectionFailed(cli.host)
|
||||
}
|
||||
if strings.Contains(nErr.Error(), "connection refused") || strings.Contains(nErr.Error(), "dial unix") {
|
||||
return nil, ErrorConnectionFailed(cli.host)
|
||||
}
|
||||
}
|
||||
|
||||
// Although there's not a strongly typed error for this in go-winio,
|
||||
// lots of people are using the default configuration for the docker
|
||||
// daemon on Windows where the daemon is listening on a named pipe
|
||||
// `//./pipe/docker_engine, and the client must be running elevated.
|
||||
// Give users a clue rather than the not-overly useful message
|
||||
// such as `error during connect: Get http://%2F%2F.%2Fpipe%2Fdocker_engine/v1.26/info:
|
||||
// open //./pipe/docker_engine: The system cannot find the file specified.`.
|
||||
// Note we can't string compare "The system cannot find the file specified" as
|
||||
// this is localised - for example in French the error would be
|
||||
// `open //./pipe/docker_engine: Le fichier spécifié est introuvable.`
|
||||
if strings.Contains(err.Error(), `open //./pipe/docker_engine`) {
|
||||
// Checks if client is running with elevated privileges
|
||||
if f, elevatedErr := os.Open(`\\.\PHYSICALDRIVE0`); elevatedErr != nil {
|
||||
err = errors.Wrap(err, "in the default daemon configuration on Windows, the docker client must be run with elevated privileges to connect")
|
||||
} else {
|
||||
_ = f.Close()
|
||||
err = errors.Wrap(err, "this error may indicate that the docker daemon is not running")
|
||||
}
|
||||
}
|
||||
|
||||
return nil, errors.Wrap(err, "error during connect")
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
func (cli *Client) checkResponseErr(serverResp *http.Response) error {
|
||||
if serverResp == nil {
|
||||
return nil
|
||||
}
|
||||
if serverResp.StatusCode >= 200 && serverResp.StatusCode < 400 {
|
||||
return nil
|
||||
}
|
||||
|
||||
var body []byte
|
||||
var err error
|
||||
var reqURL string
|
||||
if serverResp.Request != nil {
|
||||
reqURL = serverResp.Request.URL.String()
|
||||
}
|
||||
statusMsg := serverResp.Status
|
||||
if statusMsg == "" {
|
||||
statusMsg = http.StatusText(serverResp.StatusCode)
|
||||
}
|
||||
if serverResp.Body != nil {
|
||||
bodyMax := 1 * 1024 * 1024 // 1 MiB
|
||||
bodyR := &io.LimitedReader{
|
||||
R: serverResp.Body,
|
||||
N: int64(bodyMax),
|
||||
}
|
||||
body, err = io.ReadAll(bodyR)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if bodyR.N == 0 {
|
||||
return fmt.Errorf("request returned %s with a message (> %d bytes) for API route and version %s, check if the server supports the requested API version", statusMsg, bodyMax, reqURL)
|
||||
}
|
||||
}
|
||||
if len(body) == 0 {
|
||||
return fmt.Errorf("request returned %s for API route and version %s, check if the server supports the requested API version", statusMsg, reqURL)
|
||||
}
|
||||
|
||||
var daemonErr error
|
||||
if serverResp.Header.Get("Content-Type") == "application/json" {
|
||||
var errorResponse struct {
|
||||
Message string `json:"message"`
|
||||
}
|
||||
if err := json.Unmarshal(body, &errorResponse); err != nil {
|
||||
return errors.Wrap(err, "Error reading JSON")
|
||||
}
|
||||
daemonErr = errors.New(strings.TrimSpace(errorResponse.Message))
|
||||
} else {
|
||||
daemonErr = errors.New(strings.TrimSpace(string(body)))
|
||||
}
|
||||
return errors.Wrap(daemonErr, "Error response from daemon")
|
||||
}
|
||||
|
||||
func (cli *Client) addHeaders(req *http.Request, headers http.Header) *http.Request {
|
||||
for k, v := range headers {
|
||||
req.Header[http.CanonicalHeaderKey(k)] = v
|
||||
}
|
||||
return req
|
||||
}
|
||||
|
||||
func ensureReaderClosed(response *http.Response) {
|
||||
if response.Body != nil {
|
||||
// Drain up to 512 bytes and close the body to let the Transport reuse the connection
|
||||
_, _ = io.CopyN(io.Discard, response.Body, 512)
|
||||
_ = response.Body.Close()
|
||||
}
|
||||
}
|
32
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/sockets.go
generated
vendored
Normal file
32
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/sockets.go
generated
vendored
Normal file
@ -0,0 +1,32 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
)
|
||||
|
||||
const defaultTimeout = 10 * time.Second
|
||||
|
||||
// configureTransport configures the specified [http.Transport] according to the specified proto
|
||||
// and addr.
|
||||
//
|
||||
// If the proto is unix (using a unix socket to communicate) or npipe the compression is disabled.
|
||||
// For other protos, compression is enabled. If you want to manually enable/disable compression,
|
||||
// make sure you do it _after_ any subsequent calls to ConfigureTransport is made against the same
|
||||
// [http.Transport].
|
||||
func configureTransport(tr *http.Transport, proto, addr string) error {
|
||||
switch proto {
|
||||
case "unix":
|
||||
return configureUnixTransport(tr, proto, addr)
|
||||
case "npipe":
|
||||
return configureNpipeTransport(tr, proto, addr)
|
||||
default:
|
||||
tr.Proxy = http.ProxyFromEnvironment
|
||||
tr.DisableCompression = false
|
||||
tr.DialContext = (&net.Dialer{
|
||||
Timeout: defaultTimeout,
|
||||
}).DialContext
|
||||
}
|
||||
return nil
|
||||
}
|
40
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/sockets_unix.go
generated
vendored
Normal file
40
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/sockets_unix.go
generated
vendored
Normal file
@ -0,0 +1,40 @@
|
||||
//go:build !windows
|
||||
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
const maxUnixSocketPathSize = len(syscall.RawSockaddrUnix{}.Path)
|
||||
|
||||
func configureUnixTransport(tr *http.Transport, proto, addr string) error {
|
||||
if len(addr) > maxUnixSocketPathSize {
|
||||
return errors.Errorf("unix socket path %q is too long", addr)
|
||||
}
|
||||
// No need for compression in local communications.
|
||||
tr.DisableCompression = true
|
||||
dialer := &net.Dialer{
|
||||
Timeout: defaultTimeout,
|
||||
}
|
||||
tr.DialContext = func(ctx context.Context, _, _ string) (net.Conn, error) {
|
||||
return dialer.DialContext(ctx, proto, addr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func configureNpipeTransport(_ *http.Transport, _, _ string) error {
|
||||
return errors.New("protocol not available")
|
||||
}
|
||||
|
||||
// DialPipe connects to a Windows named pipe.
|
||||
// This is not supported on other OSes.
|
||||
func DialPipe(_ string, _ time.Duration) (net.Conn, error) {
|
||||
return nil, syscall.EAFNOSUPPORT
|
||||
}
|
29
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/sockets_windows.go
generated
vendored
Normal file
29
vendor/github.com/moby/buildkit/util/testutil/dockerd/client/sockets_windows.go
generated
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/Microsoft/go-winio"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func configureUnixTransport(_ *http.Transport, _, _ string) error {
|
||||
return errors.New("protocol not available")
|
||||
}
|
||||
|
||||
func configureNpipeTransport(tr *http.Transport, _, addr string) error {
|
||||
// No need for compression in local communications.
|
||||
tr.DisableCompression = true
|
||||
tr.DialContext = func(ctx context.Context, _, _ string) (net.Conn, error) {
|
||||
return winio.DialPipeContext(ctx, addr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DialPipe connects to a Windows named pipe.
|
||||
func DialPipe(addr string, timeout time.Duration) (net.Conn, error) {
|
||||
return winio.DialPipe(addr, &timeout)
|
||||
}
|
6
vendor/github.com/moby/buildkit/util/testutil/dockerd/daemon.go
generated
vendored
6
vendor/github.com/moby/buildkit/util/testutil/dockerd/daemon.go
generated
vendored
@ -16,12 +16,12 @@ import (
|
||||
)
|
||||
|
||||
type LogT interface {
|
||||
Logf(string, ...interface{})
|
||||
Logf(string, ...any)
|
||||
}
|
||||
|
||||
type nopLog struct{}
|
||||
|
||||
func (nopLog) Logf(string, ...interface{}) {}
|
||||
func (nopLog) Logf(string, ...any) {}
|
||||
|
||||
const (
|
||||
shortLen = 12
|
||||
@ -73,7 +73,7 @@ func NewDaemon(workingDir string, ops ...Option) (*Daemon, error) {
|
||||
dockerdBinary: DefaultDockerdBinary,
|
||||
Log: nopLog{},
|
||||
sockPath: filepath.Join(sockRoot, id+".sock"),
|
||||
envs: append([]string{}, os.Environ()...),
|
||||
envs: os.Environ(),
|
||||
}
|
||||
|
||||
for _, op := range ops {
|
||||
|
150
vendor/github.com/moby/buildkit/util/testutil/integration/run.go
generated
vendored
150
vendor/github.com/moby/buildkit/util/testutil/integration/run.go
generated
vendored
@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"maps"
|
||||
"math"
|
||||
"math/rand"
|
||||
"os"
|
||||
"os/exec"
|
||||
@ -12,6 +13,7 @@ import (
|
||||
"reflect"
|
||||
"runtime"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
@ -58,7 +60,7 @@ type Sandbox interface {
|
||||
PrintLogs(*testing.T)
|
||||
ClearLogs()
|
||||
NewRegistry() (string, error)
|
||||
Value(string) interface{} // chosen matrix value
|
||||
Value(string) any // chosen matrix value
|
||||
Name() string
|
||||
CDISpecDir() string
|
||||
}
|
||||
@ -129,10 +131,10 @@ func List() []Worker {
|
||||
// tests.
|
||||
type TestOpt func(*testConf)
|
||||
|
||||
func WithMatrix(key string, m map[string]interface{}) TestOpt {
|
||||
func WithMatrix(key string, m map[string]any) TestOpt {
|
||||
return func(tc *testConf) {
|
||||
if tc.matrix == nil {
|
||||
tc.matrix = map[string]map[string]interface{}{}
|
||||
tc.matrix = map[string]map[string]any{}
|
||||
}
|
||||
tc.matrix[key] = m
|
||||
}
|
||||
@ -148,7 +150,7 @@ func WithMirroredImages(m map[string]string) TestOpt {
|
||||
}
|
||||
|
||||
type testConf struct {
|
||||
matrix map[string]map[string]interface{}
|
||||
matrix map[string]map[string]any
|
||||
mirroredImages map[string]string
|
||||
}
|
||||
|
||||
@ -161,6 +163,29 @@ func Run(t *testing.T, testCases []Test, opt ...TestOpt) {
|
||||
t.Skip("skipping integration tests")
|
||||
}
|
||||
|
||||
var sliceSplit int
|
||||
if filter, ok := lookupTestFilter(); ok {
|
||||
parts := strings.Split(filter, "/")
|
||||
if len(parts) >= 2 {
|
||||
const prefix = "slice="
|
||||
if strings.HasPrefix(parts[1], prefix) {
|
||||
conf := strings.TrimPrefix(parts[1], prefix)
|
||||
offsetS, totalS, ok := strings.Cut(conf, "-")
|
||||
if !ok {
|
||||
t.Fatalf("invalid slice=%q", conf)
|
||||
}
|
||||
offset, err := strconv.Atoi(offsetS)
|
||||
require.NoError(t, err)
|
||||
total, err := strconv.Atoi(totalS)
|
||||
require.NoError(t, err)
|
||||
if offset < 1 || total < 1 || offset > total {
|
||||
t.Fatalf("invalid slice=%q", conf)
|
||||
}
|
||||
sliceSplit = total
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var tc testConf
|
||||
for _, o := range opt {
|
||||
o(&tc)
|
||||
@ -182,9 +207,14 @@ func Run(t *testing.T, testCases []Test, opt ...TestOpt) {
|
||||
})
|
||||
|
||||
for _, br := range list {
|
||||
for _, tc := range testCases {
|
||||
for i, tc := range testCases {
|
||||
for _, mv := range matrix {
|
||||
fn := tc.Name()
|
||||
if sliceSplit > 0 {
|
||||
pageLimit := int(math.Ceil(float64(len(testCases)) / float64(sliceSplit)))
|
||||
sliceName := fmt.Sprintf("slice=%d-%d/", i/pageLimit+1, sliceSplit)
|
||||
fn = sliceName + fn
|
||||
}
|
||||
name := fn + "/worker=" + br.Name() + mv.functionSuffix()
|
||||
func(fn, testName string, br Worker, tc Test, mv matrixValue) {
|
||||
ok := t.Run(testName, func(t *testing.T) {
|
||||
@ -221,7 +251,7 @@ func Run(t *testing.T, testCases []Test, opt ...TestOpt) {
|
||||
}
|
||||
}
|
||||
|
||||
func getFunctionName(i interface{}) string {
|
||||
func getFunctionName(i any) string {
|
||||
fullname := runtime.FuncForPC(reflect.ValueOf(i).Pointer()).Name()
|
||||
dot := strings.LastIndex(fullname, ".") + 1
|
||||
return strings.Title(fullname[dot:]) //nolint:staticcheck // ignoring "SA1019: strings.Title is deprecated", as for our use we don't need full unicode support
|
||||
@ -330,37 +360,80 @@ func lazyMirrorRunnerFunc(t *testing.T, images map[string]string) func() string
|
||||
var mirror string
|
||||
return func() string {
|
||||
once.Do(func() {
|
||||
host, cleanup, err := runMirror(t, images)
|
||||
m, err := RunMirror()
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() { _ = cleanup() })
|
||||
mirror = host
|
||||
require.NoError(t, m.AddImages(t, images))
|
||||
t.Cleanup(func() { _ = m.Close() })
|
||||
mirror = m.Host
|
||||
})
|
||||
return mirror
|
||||
}
|
||||
}
|
||||
|
||||
func runMirror(t *testing.T, mirroredImages map[string]string) (host string, _ func() error, err error) {
|
||||
type Mirror struct {
|
||||
Host string
|
||||
dir string
|
||||
cleanup func() error
|
||||
}
|
||||
|
||||
func (m *Mirror) lock() (*flock.Flock, error) {
|
||||
if m.dir == "" {
|
||||
return nil, nil
|
||||
}
|
||||
if err := os.MkdirAll(m.dir, 0700); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
lock := flock.New(filepath.Join(m.dir, "lock"))
|
||||
if err := lock.Lock(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return lock, nil
|
||||
}
|
||||
|
||||
func (m *Mirror) Close() error {
|
||||
if m.cleanup != nil {
|
||||
return m.cleanup()
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Mirror) AddImages(t *testing.T, images map[string]string) (err error) {
|
||||
lock, err := m.lock()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func() {
|
||||
if lock != nil {
|
||||
lock.Unlock()
|
||||
}
|
||||
}()
|
||||
|
||||
if err := copyImagesLocal(t, m.Host, images); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func RunMirror() (_ *Mirror, err error) {
|
||||
mirrorDir := os.Getenv("BUILDKIT_REGISTRY_MIRROR_DIR")
|
||||
|
||||
var lock *flock.Flock
|
||||
if mirrorDir != "" {
|
||||
if err := os.MkdirAll(mirrorDir, 0700); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
lock = flock.New(filepath.Join(mirrorDir, "lock"))
|
||||
if err := lock.Lock(); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
lock.Unlock()
|
||||
}
|
||||
}()
|
||||
m := &Mirror{
|
||||
dir: mirrorDir,
|
||||
}
|
||||
|
||||
mirror, cleanup, err := NewRegistry(mirrorDir)
|
||||
lock, err := m.lock()
|
||||
if err != nil {
|
||||
return "", nil, err
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
lock.Unlock()
|
||||
}
|
||||
}()
|
||||
|
||||
host, cleanup, err := NewRegistry(mirrorDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err != nil {
|
||||
@ -368,17 +441,16 @@ func runMirror(t *testing.T, mirroredImages map[string]string) (host string, _ f
|
||||
}
|
||||
}()
|
||||
|
||||
if err := copyImagesLocal(t, mirror, mirroredImages); err != nil {
|
||||
return "", nil, err
|
||||
}
|
||||
m.Host = host
|
||||
m.cleanup = cleanup
|
||||
|
||||
if mirrorDir != "" {
|
||||
if lock != nil {
|
||||
if err := lock.Unlock(); err != nil {
|
||||
return "", nil, err
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return mirror, cleanup, err
|
||||
return m, err
|
||||
}
|
||||
|
||||
type matrixValue struct {
|
||||
@ -400,10 +472,10 @@ func (mv matrixValue) functionSuffix() string {
|
||||
|
||||
type matrixValueChoice struct {
|
||||
name string
|
||||
value interface{}
|
||||
value any
|
||||
}
|
||||
|
||||
func newMatrixValue(key, name string, v interface{}) matrixValue {
|
||||
func newMatrixValue(key, name string, v any) matrixValue {
|
||||
return matrixValue{
|
||||
fn: []string{key},
|
||||
values: map[string]matrixValueChoice{
|
||||
@ -463,3 +535,13 @@ func UnixOrWindows[T any](unix, windows T) T {
|
||||
}
|
||||
return unix
|
||||
}
|
||||
|
||||
func lookupTestFilter() (string, bool) {
|
||||
const prefix = "-test.run="
|
||||
for _, arg := range os.Args {
|
||||
if strings.HasPrefix(arg, prefix) {
|
||||
return strings.TrimPrefix(arg, prefix), true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
4
vendor/github.com/moby/buildkit/util/testutil/integration/sandbox.go
generated
vendored
4
vendor/github.com/moby/buildkit/util/testutil/integration/sandbox.go
generated
vendored
@ -86,7 +86,7 @@ func (sb *sandbox) Cmd(args ...string) *exec.Cmd {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (sb *sandbox) Value(k string) interface{} {
|
||||
func (sb *sandbox) Value(k string) any {
|
||||
return sb.mv.values[k].value
|
||||
}
|
||||
|
||||
@ -197,7 +197,7 @@ func RootlessSupported(uid int) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func PrintLogs(logs map[string]*bytes.Buffer, f func(args ...interface{})) {
|
||||
func PrintLogs(logs map[string]*bytes.Buffer, f func(args ...any)) {
|
||||
for name, l := range logs {
|
||||
f(name)
|
||||
s := bufio.NewScanner(l)
|
||||
|
18
vendor/github.com/moby/buildkit/util/testutil/workers/backend.go
generated
vendored
18
vendor/github.com/moby/buildkit/util/testutil/workers/backend.go
generated
vendored
@ -2,6 +2,7 @@ package workers
|
||||
|
||||
import (
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
)
|
||||
|
||||
@ -52,23 +53,14 @@ func (b backend) ExtraEnv() []string {
|
||||
|
||||
func (b backend) Supports(feature string) bool {
|
||||
if enabledFeatures := os.Getenv("BUILDKIT_TEST_ENABLE_FEATURES"); enabledFeatures != "" {
|
||||
for _, enabledFeature := range strings.Split(enabledFeatures, ",") {
|
||||
if feature == enabledFeature {
|
||||
return true
|
||||
}
|
||||
if slices.Contains(strings.Split(enabledFeatures, ","), feature) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
if disabledFeatures := os.Getenv("BUILDKIT_TEST_DISABLE_FEATURES"); disabledFeatures != "" {
|
||||
for _, disabledFeature := range strings.Split(disabledFeatures, ",") {
|
||||
if feature == disabledFeature {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
for _, unsupportedFeature := range b.unsupportedFeatures {
|
||||
if feature == unsupportedFeature {
|
||||
if slices.Contains(strings.Split(disabledFeatures, ","), feature) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
return !slices.Contains(b.unsupportedFeatures, feature)
|
||||
}
|
||||
|
4
vendor/github.com/moby/buildkit/util/testutil/workers/dockerd.go
generated
vendored
4
vendor/github.com/moby/buildkit/util/testutil/workers/dockerd.go
generated
vendored
@ -10,9 +10,9 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/docker/docker/client"
|
||||
"github.com/moby/buildkit/cmd/buildkitd/config"
|
||||
"github.com/moby/buildkit/util/testutil/dockerd"
|
||||
"github.com/moby/buildkit/util/testutil/dockerd/client"
|
||||
"github.com/moby/buildkit/util/testutil/integration"
|
||||
"github.com/pkg/errors"
|
||||
"golang.org/x/sync/errgroup"
|
||||
@ -252,7 +252,7 @@ func waitForAPI(ctx context.Context, apiClient *client.Client, d time.Duration)
|
||||
step := 50 * time.Millisecond
|
||||
i := 0
|
||||
for {
|
||||
if _, err := apiClient.Ping(ctx); err == nil {
|
||||
if err := apiClient.Ping(ctx); err == nil {
|
||||
break
|
||||
}
|
||||
i++
|
||||
|
15
vendor/github.com/moby/buildkit/util/tracing/tracing.go
generated
vendored
15
vendor/github.com/moby/buildkit/util/tracing/tracing.go
generated
vendored
@ -5,7 +5,11 @@ import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/http/httptrace"
|
||||
"slices"
|
||||
|
||||
"github.com/moby/buildkit/util/bklog"
|
||||
"github.com/moby/buildkit/util/stack"
|
||||
"github.com/pkg/errors"
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace"
|
||||
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
|
||||
"go.opentelemetry.io/otel/attribute"
|
||||
@ -14,11 +18,6 @@ import (
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
|
||||
"go.opentelemetry.io/otel/trace"
|
||||
"go.opentelemetry.io/otel/trace/noop"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/moby/buildkit/util/bklog"
|
||||
"github.com/moby/buildkit/util/stack"
|
||||
)
|
||||
|
||||
// StartSpan starts a new span as a child of the span in context.
|
||||
@ -43,10 +42,8 @@ func hasStacktrace(err error) bool {
|
||||
case interface{ Unwrap() error }:
|
||||
return hasStacktrace(e.Unwrap())
|
||||
case interface{ Unwrap() []error }:
|
||||
for _, ue := range e.Unwrap() {
|
||||
if hasStacktrace(ue) {
|
||||
return true
|
||||
}
|
||||
if slices.ContainsFunc(e.Unwrap(), hasStacktrace) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
141
vendor/github.com/moby/sys/user/idtools.go
generated
vendored
Normal file
141
vendor/github.com/moby/sys/user/idtools.go
generated
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// MkdirOpt is a type for options to pass to Mkdir calls
|
||||
type MkdirOpt func(*mkdirOptions)
|
||||
|
||||
type mkdirOptions struct {
|
||||
onlyNew bool
|
||||
}
|
||||
|
||||
// WithOnlyNew is an option for MkdirAllAndChown that will only change ownership and permissions
|
||||
// on newly created directories. If the directory already exists, it will not be modified
|
||||
func WithOnlyNew(o *mkdirOptions) {
|
||||
o.onlyNew = true
|
||||
}
|
||||
|
||||
// MkdirAllAndChown creates a directory (include any along the path) and then modifies
|
||||
// ownership to the requested uid/gid. By default, if the directory already exists, this
|
||||
// function will still change ownership and permissions. If WithOnlyNew is passed as an
|
||||
// option, then only the newly created directories will have ownership and permissions changed.
|
||||
func MkdirAllAndChown(path string, mode os.FileMode, uid, gid int, opts ...MkdirOpt) error {
|
||||
var options mkdirOptions
|
||||
for _, opt := range opts {
|
||||
opt(&options)
|
||||
}
|
||||
|
||||
return mkdirAs(path, mode, uid, gid, true, options.onlyNew)
|
||||
}
|
||||
|
||||
// MkdirAndChown creates a directory and then modifies ownership to the requested uid/gid.
|
||||
// By default, if the directory already exists, this function still changes ownership and permissions.
|
||||
// If WithOnlyNew is passed as an option, then only the newly created directory will have ownership
|
||||
// and permissions changed.
|
||||
// Note that unlike os.Mkdir(), this function does not return IsExist error
|
||||
// in case path already exists.
|
||||
func MkdirAndChown(path string, mode os.FileMode, uid, gid int, opts ...MkdirOpt) error {
|
||||
var options mkdirOptions
|
||||
for _, opt := range opts {
|
||||
opt(&options)
|
||||
}
|
||||
return mkdirAs(path, mode, uid, gid, false, options.onlyNew)
|
||||
}
|
||||
|
||||
// getRootUIDGID retrieves the remapped root uid/gid pair from the set of maps.
|
||||
// If the maps are empty, then the root uid/gid will default to "real" 0/0
|
||||
func getRootUIDGID(uidMap, gidMap []IDMap) (int, int, error) {
|
||||
uid, err := toHost(0, uidMap)
|
||||
if err != nil {
|
||||
return -1, -1, err
|
||||
}
|
||||
gid, err := toHost(0, gidMap)
|
||||
if err != nil {
|
||||
return -1, -1, err
|
||||
}
|
||||
return uid, gid, nil
|
||||
}
|
||||
|
||||
// toContainer takes an id mapping, and uses it to translate a
|
||||
// host ID to the remapped ID. If no map is provided, then the translation
|
||||
// assumes a 1-to-1 mapping and returns the passed in id
|
||||
func toContainer(hostID int, idMap []IDMap) (int, error) {
|
||||
if idMap == nil {
|
||||
return hostID, nil
|
||||
}
|
||||
for _, m := range idMap {
|
||||
if (int64(hostID) >= m.ParentID) && (int64(hostID) <= (m.ParentID + m.Count - 1)) {
|
||||
contID := int(m.ID + (int64(hostID) - m.ParentID))
|
||||
return contID, nil
|
||||
}
|
||||
}
|
||||
return -1, fmt.Errorf("host ID %d cannot be mapped to a container ID", hostID)
|
||||
}
|
||||
|
||||
// toHost takes an id mapping and a remapped ID, and translates the
|
||||
// ID to the mapped host ID. If no map is provided, then the translation
|
||||
// assumes a 1-to-1 mapping and returns the passed in id #
|
||||
func toHost(contID int, idMap []IDMap) (int, error) {
|
||||
if idMap == nil {
|
||||
return contID, nil
|
||||
}
|
||||
for _, m := range idMap {
|
||||
if (int64(contID) >= m.ID) && (int64(contID) <= (m.ID + m.Count - 1)) {
|
||||
hostID := int(m.ParentID + (int64(contID) - m.ID))
|
||||
return hostID, nil
|
||||
}
|
||||
}
|
||||
return -1, fmt.Errorf("container ID %d cannot be mapped to a host ID", contID)
|
||||
}
|
||||
|
||||
// IdentityMapping contains a mappings of UIDs and GIDs.
|
||||
// The zero value represents an empty mapping.
|
||||
type IdentityMapping struct {
|
||||
UIDMaps []IDMap `json:"UIDMaps"`
|
||||
GIDMaps []IDMap `json:"GIDMaps"`
|
||||
}
|
||||
|
||||
// RootPair returns a uid and gid pair for the root user. The error is ignored
|
||||
// because a root user always exists, and the defaults are correct when the uid
|
||||
// and gid maps are empty.
|
||||
func (i IdentityMapping) RootPair() (int, int) {
|
||||
uid, gid, _ := getRootUIDGID(i.UIDMaps, i.GIDMaps)
|
||||
return uid, gid
|
||||
}
|
||||
|
||||
// ToHost returns the host UID and GID for the container uid, gid.
|
||||
// Remapping is only performed if the ids aren't already the remapped root ids
|
||||
func (i IdentityMapping) ToHost(uid, gid int) (int, int, error) {
|
||||
var err error
|
||||
ruid, rgid := i.RootPair()
|
||||
|
||||
if uid != ruid {
|
||||
ruid, err = toHost(uid, i.UIDMaps)
|
||||
if err != nil {
|
||||
return ruid, rgid, err
|
||||
}
|
||||
}
|
||||
|
||||
if gid != rgid {
|
||||
rgid, err = toHost(gid, i.GIDMaps)
|
||||
}
|
||||
return ruid, rgid, err
|
||||
}
|
||||
|
||||
// ToContainer returns the container UID and GID for the host uid and gid
|
||||
func (i IdentityMapping) ToContainer(uid, gid int) (int, int, error) {
|
||||
ruid, err := toContainer(uid, i.UIDMaps)
|
||||
if err != nil {
|
||||
return -1, -1, err
|
||||
}
|
||||
rgid, err := toContainer(gid, i.GIDMaps)
|
||||
return ruid, rgid, err
|
||||
}
|
||||
|
||||
// Empty returns true if there are no id mappings
|
||||
func (i IdentityMapping) Empty() bool {
|
||||
return len(i.UIDMaps) == 0 && len(i.GIDMaps) == 0
|
||||
}
|
143
vendor/github.com/moby/sys/user/idtools_unix.go
generated
vendored
Normal file
143
vendor/github.com/moby/sys/user/idtools_unix.go
generated
vendored
Normal file
@ -0,0 +1,143 @@
|
||||
//go:build !windows
|
||||
|
||||
package user
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func mkdirAs(path string, mode os.FileMode, uid, gid int, mkAll, onlyNew bool) error {
|
||||
path, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
stat, err := os.Stat(path)
|
||||
if err == nil {
|
||||
if !stat.IsDir() {
|
||||
return &os.PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR}
|
||||
}
|
||||
if onlyNew {
|
||||
return nil
|
||||
}
|
||||
|
||||
// short-circuit -- we were called with an existing directory and chown was requested
|
||||
return setPermissions(path, mode, uid, gid, stat)
|
||||
}
|
||||
|
||||
// make an array containing the original path asked for, plus (for mkAll == true)
|
||||
// all path components leading up to the complete path that don't exist before we MkdirAll
|
||||
// so that we can chown all of them properly at the end. If onlyNew is true, we won't
|
||||
// chown the full directory path if it exists
|
||||
var paths []string
|
||||
if os.IsNotExist(err) {
|
||||
paths = append(paths, path)
|
||||
}
|
||||
|
||||
if mkAll {
|
||||
// walk back to "/" looking for directories which do not exist
|
||||
// and add them to the paths array for chown after creation
|
||||
dirPath := path
|
||||
for {
|
||||
dirPath = filepath.Dir(dirPath)
|
||||
if dirPath == "/" {
|
||||
break
|
||||
}
|
||||
if _, err = os.Stat(dirPath); os.IsNotExist(err) {
|
||||
paths = append(paths, dirPath)
|
||||
}
|
||||
}
|
||||
if err = os.MkdirAll(path, mode); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if err = os.Mkdir(path, mode); err != nil {
|
||||
return err
|
||||
}
|
||||
// even if it existed, we will chown the requested path + any subpaths that
|
||||
// didn't exist when we called MkdirAll
|
||||
for _, pathComponent := range paths {
|
||||
if err = setPermissions(pathComponent, mode, uid, gid, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// setPermissions performs a chown/chmod only if the uid/gid don't match what's requested
|
||||
// Normally a Chown is a no-op if uid/gid match, but in some cases this can still cause an error, e.g. if the
|
||||
// dir is on an NFS share, so don't call chown unless we absolutely must.
|
||||
// Likewise for setting permissions.
|
||||
func setPermissions(p string, mode os.FileMode, uid, gid int, stat os.FileInfo) error {
|
||||
if stat == nil {
|
||||
var err error
|
||||
stat, err = os.Stat(p)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if stat.Mode().Perm() != mode.Perm() {
|
||||
if err := os.Chmod(p, mode.Perm()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
ssi := stat.Sys().(*syscall.Stat_t)
|
||||
if ssi.Uid == uint32(uid) && ssi.Gid == uint32(gid) {
|
||||
return nil
|
||||
}
|
||||
return os.Chown(p, uid, gid)
|
||||
}
|
||||
|
||||
// LoadIdentityMapping takes a requested username and
|
||||
// using the data from /etc/sub{uid,gid} ranges, creates the
|
||||
// proper uid and gid remapping ranges for that user/group pair
|
||||
func LoadIdentityMapping(name string) (IdentityMapping, error) {
|
||||
// TODO: Consider adding support for calling out to "getent"
|
||||
usr, err := LookupUser(name)
|
||||
if err != nil {
|
||||
return IdentityMapping{}, fmt.Errorf("could not get user for username %s: %w", name, err)
|
||||
}
|
||||
|
||||
subuidRanges, err := lookupSubRangesFile("/etc/subuid", usr)
|
||||
if err != nil {
|
||||
return IdentityMapping{}, err
|
||||
}
|
||||
subgidRanges, err := lookupSubRangesFile("/etc/subgid", usr)
|
||||
if err != nil {
|
||||
return IdentityMapping{}, err
|
||||
}
|
||||
|
||||
return IdentityMapping{
|
||||
UIDMaps: subuidRanges,
|
||||
GIDMaps: subgidRanges,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func lookupSubRangesFile(path string, usr User) ([]IDMap, error) {
|
||||
uidstr := strconv.Itoa(usr.Uid)
|
||||
rangeList, err := ParseSubIDFileFilter(path, func(sid SubID) bool {
|
||||
return sid.Name == usr.Name || sid.Name == uidstr
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(rangeList) == 0 {
|
||||
return nil, fmt.Errorf("no subuid ranges found for user %q", usr.Name)
|
||||
}
|
||||
|
||||
idMap := []IDMap{}
|
||||
|
||||
var containerID int64
|
||||
for _, idrange := range rangeList {
|
||||
idMap = append(idMap, IDMap{
|
||||
ID: containerID,
|
||||
ParentID: idrange.SubID,
|
||||
Count: idrange.Count,
|
||||
})
|
||||
containerID = containerID + idrange.Count
|
||||
}
|
||||
return idMap, nil
|
||||
}
|
13
vendor/github.com/moby/sys/user/idtools_windows.go
generated
vendored
Normal file
13
vendor/github.com/moby/sys/user/idtools_windows.go
generated
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
package user
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// This is currently a wrapper around [os.MkdirAll] since currently
|
||||
// permissions aren't set through this path, the identity isn't utilized.
|
||||
// Ownership is handled elsewhere, but in the future could be support here
|
||||
// too.
|
||||
func mkdirAs(path string, _ os.FileMode, _, _ int, _, _ bool) error {
|
||||
return os.MkdirAll(path, 0)
|
||||
}
|
Reference in New Issue
Block a user