vendor: github.com/moby/buildkit v0.12.1-0.20230717122532-faa0cc7da353

full diff:

- https://github.com/moby/buildkit/compare/20230620112432...v0.12.0
- https://github.com/moby/buildkit/compare/v0.12.0...faa0cc7da3536923d85b74b2bb2d13c12a6ecc99

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
Sebastiaan van Stijn
2023-07-17 10:49:00 +02:00
parent 2666bd6996
commit 130bbda00e
65 changed files with 5389 additions and 256 deletions

View File

@ -25,6 +25,7 @@ import (
sdktrace "go.opentelemetry.io/otel/sdk/trace"
"go.opentelemetry.io/otel/trace"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
)
@ -184,6 +185,19 @@ func (c *Client) Dialer() session.Dialer {
return grpchijack.Dialer(c.ControlClient())
}
func (c *Client) Wait(ctx context.Context) error {
opts := []grpc.CallOption{grpc.WaitForReady(true)}
_, err := c.ControlClient().Info(ctx, &controlapi.InfoRequest{}, opts...)
if err != nil {
if code := grpcerrors.Code(err); code == codes.Unimplemented {
// only buildkit v0.11+ supports the info api, but an unimplemented
// response error is still a response so we can ignore it
return nil
}
}
return err
}
func (c *Client) Close() error {
return c.conn.Close()
}

View File

@ -15,7 +15,7 @@ type asyncState struct {
target State
set bool
err error
g flightcontrol.Group
g flightcontrol.Group[State]
}
func (as *asyncState) Output() Output {
@ -53,7 +53,7 @@ func (as *asyncState) ToInput(ctx context.Context, c *Constraints) (*pb.Input, e
}
func (as *asyncState) Do(ctx context.Context, c *Constraints) error {
_, err := as.g.Do(ctx, "", func(ctx context.Context) (interface{}, error) {
_, err := as.g.Do(ctx, "", func(ctx context.Context) (State, error) {
if as.set {
return as.target, as.err
}

View File

@ -145,6 +145,7 @@ func Mkdir(p string, m os.FileMode, opt ...MkdirOption) *FileAction {
for _, o := range opt {
o.SetMkdirOption(&mi)
}
return &FileAction{
action: &fileActionMkdir{
file: p,
@ -447,7 +448,6 @@ func Copy(input CopyInput, src, dest string, opts ...CopyOption) *FileAction {
for _, o := range opts {
o.SetCopyOption(&mi)
}
return &FileAction{
action: &fileActionCopy{
state: state,
@ -523,22 +523,19 @@ func (a *fileActionCopy) toProtoAction(ctx context.Context, parent string, base
func (a *fileActionCopy) sourcePath(ctx context.Context) (string, error) {
p := path.Clean(a.src)
dir := "/"
var err error
if !path.IsAbs(p) {
if a.state != nil {
dir, err := a.state.GetDir(ctx)
if err != nil {
return "", err
}
p = path.Join("/", dir, p)
dir, err = a.state.GetDir(ctx)
} else if a.fas != nil {
dir, err := a.fas.state.GetDir(ctx)
if err != nil {
return "", err
}
p = path.Join("/", dir, p)
dir, err = a.fas.state.GetDir(ctx)
}
if err != nil {
return "", err
}
}
return p, nil
return path.Join(dir, p), nil
}
func (a *fileActionCopy) addCaps(f *FileOp) {

View File

@ -10,6 +10,7 @@ import (
"github.com/google/shlex"
"github.com/moby/buildkit/solver/pb"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
type contextKeyT string
@ -78,7 +79,7 @@ func dirf(value string, replace bool, v ...interface{}) StateOption {
if !path.IsAbs(value) {
prev, err := getDir(s)(ctx, c)
if err != nil {
return nil, err
return nil, errors.Wrap(err, "getting dir from state")
}
if prev == "" {
prev = "/"

View File

@ -3,6 +3,7 @@ package llb
import (
"context"
spb "github.com/moby/buildkit/sourcepolicy/pb"
digest "github.com/opencontainers/go-digest"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
)
@ -31,7 +32,7 @@ func WithLayerLimit(l int) ImageOption {
// ImageMetaResolver can resolve image config metadata from a reference
type ImageMetaResolver interface {
ResolveImageConfig(ctx context.Context, ref string, opt ResolveImageConfigOpt) (digest.Digest, []byte, error)
ResolveImageConfig(ctx context.Context, ref string, opt ResolveImageConfigOpt) (string, digest.Digest, []byte, error)
}
type ResolverType int
@ -49,6 +50,8 @@ type ResolveImageConfigOpt struct {
LogName string
Store ResolveImageConfigOptStore
SourcePolicies []*spb.Policy
}
type ResolveImageConfigOptStore struct {

View File

@ -135,7 +135,7 @@ func Image(ref string, opts ...ImageOption) State {
if p == nil {
p = c.Platform
}
_, dt, err := info.metaResolver.ResolveImageConfig(ctx, ref, ResolveImageConfigOpt{
_, _, dt, err := info.metaResolver.ResolveImageConfig(ctx, ref, ResolveImageConfigOpt{
Platform: p,
ResolveMode: info.resolveMode.String(),
ResolverType: ResolverTypeRegistry,
@ -151,7 +151,7 @@ func Image(ref string, opts ...ImageOption) State {
if p == nil {
p = c.Platform
}
dgst, dt, err := info.metaResolver.ResolveImageConfig(context.TODO(), ref, ResolveImageConfigOpt{
ref, dgst, dt, err := info.metaResolver.ResolveImageConfig(context.TODO(), ref, ResolveImageConfigOpt{
Platform: p,
ResolveMode: info.resolveMode.String(),
ResolverType: ResolverTypeRegistry,
@ -159,6 +159,10 @@ func Image(ref string, opts ...ImageOption) State {
if err != nil {
return State{}, err
}
r, err := reference.ParseNormalizedNamed(ref)
if err != nil {
return State{}, err
}
if dgst != "" {
r, err = reference.WithDigest(r, dgst)
if err != nil {

View File

@ -19,9 +19,10 @@ type HealthConfig struct {
Test []string `json:",omitempty"`
// Zero means to inherit. Durations are expressed as integer nanoseconds.
Interval time.Duration `json:",omitempty"` // Interval is the time to wait between checks.
Timeout time.Duration `json:",omitempty"` // Timeout is the time to wait before considering the check to have hung.
StartPeriod time.Duration `json:",omitempty"` // The start period for the container to initialize before the retries starts to count down.
Interval time.Duration `json:",omitempty"` // Interval is the time to wait between checks.
Timeout time.Duration `json:",omitempty"` // Timeout is the time to wait before considering the check to have hung.
StartPeriod time.Duration `json:",omitempty"` // The start period for the container to initialize before the retries starts to count down.
StartInterval time.Duration `json:",omitempty"` // StartInterval is the time to wait between checks during the start period.
// Retries is the number of consecutive failures needed to consider a container as unhealthy.
// Zero means inherit.

View File

@ -19,6 +19,7 @@ import (
"github.com/moby/buildkit/frontend/gateway/client"
"github.com/moby/buildkit/solver/pb"
"github.com/moby/buildkit/util/flightcontrol"
digest "github.com/opencontainers/go-digest"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
@ -76,7 +77,7 @@ type Client struct {
client client.Client
ignoreCache []string
bctx *buildContext
g flightcontrol.Group
g flightcontrol.Group[*buildContext]
bopts client.BuildOpts
dockerignore []byte
@ -96,6 +97,7 @@ type ContextOpt struct {
LocalOpts []llb.LocalOption
Platform *ocispecs.Platform
ResolveMode string
CaptureDigest *digest.Digest
}
func validateMinCaps(c client.Client) error {
@ -278,7 +280,7 @@ func (bc *Client) init() error {
}
func (bc *Client) buildContext(ctx context.Context) (*buildContext, error) {
bctx, err := bc.g.Do(ctx, "initcontext", func(ctx context.Context) (interface{}, error) {
return bc.g.Do(ctx, "initcontext", func(ctx context.Context) (*buildContext, error) {
if bc.bctx != nil {
return bc.bctx, nil
}
@ -288,10 +290,6 @@ func (bc *Client) buildContext(ctx context.Context) (*buildContext, error) {
}
return bctx, err
})
if err != nil {
return nil, err
}
return bctx.(*buildContext), nil
}
func (bc *Client) ReadEntrypoint(ctx context.Context, lang string, opts ...llb.LocalOption) (*Source, error) {

View File

@ -13,25 +13,36 @@ import (
"github.com/moby/buildkit/exporter/containerimage/image"
"github.com/moby/buildkit/frontend/dockerfile/dockerignore"
"github.com/moby/buildkit/frontend/gateway/client"
"github.com/moby/buildkit/util/imageutil"
"github.com/pkg/errors"
)
const (
contextPrefix = "context:"
inputMetadataPrefix = "input-metadata:"
maxContextRecursion = 10
)
func (bc *Client) namedContext(ctx context.Context, name string, nameWithPlatform string, opt ContextOpt) (*llb.State, *image.Image, error) {
return bc.namedContextRecursive(ctx, name, nameWithPlatform, opt, 0)
}
func (bc *Client) namedContextRecursive(ctx context.Context, name string, nameWithPlatform string, opt ContextOpt, count int) (*llb.State, *image.Image, error) {
opts := bc.bopts.Opts
v, ok := opts[contextPrefix+nameWithPlatform]
if !ok {
return nil, nil, nil
}
if count > maxContextRecursion {
return nil, nil, errors.New("context recursion limit exceeded; this may indicate a cycle in the provided source policies: " + v)
}
vv := strings.SplitN(v, ":", 2)
if len(vv) != 2 {
return nil, nil, errors.Errorf("invalid context specifier %s for %s", v, nameWithPlatform)
}
// allow git@ without protocol for SSH URLs for backwards compatibility
if strings.HasPrefix(vv[0], "git@") {
vv[0] = "git"
@ -58,13 +69,17 @@ func (bc *Client) namedContext(ctx context.Context, name string, nameWithPlatfor
named = reference.TagNameOnly(named)
_, data, err := bc.client.ResolveImageConfig(ctx, named.String(), llb.ResolveImageConfigOpt{
ref, dgst, data, err := bc.client.ResolveImageConfig(ctx, named.String(), llb.ResolveImageConfigOpt{
Platform: opt.Platform,
ResolveMode: opt.ResolveMode,
LogName: fmt.Sprintf("[context %s] load metadata for %s", nameWithPlatform, ref),
ResolverType: llb.ResolverTypeRegistry,
})
if err != nil {
e := &imageutil.ResolveToNonImageError{}
if errors.As(err, &e) {
return bc.namedContextRecursive(ctx, e.Updated, name, opt, count+1)
}
return nil, nil, err
}
@ -79,6 +94,9 @@ func (bc *Client) namedContext(ctx context.Context, name string, nameWithPlatfor
if err != nil {
return nil, nil, err
}
if opt.CaptureDigest != nil {
*opt.CaptureDigest = dgst
}
return &st, &img, nil
case "git":
st, ok := DetectGitContext(v, true)
@ -119,7 +137,8 @@ func (bc *Client) namedContext(ctx context.Context, name string, nameWithPlatfor
return nil, nil, errors.Wrapf(err, "could not wrap %q with digest", name)
}
_, data, err := bc.client.ResolveImageConfig(ctx, dummyRef.String(), llb.ResolveImageConfigOpt{
// TODO: How should source policy be handled here with a dummy ref?
_, dgst, data, err := bc.client.ResolveImageConfig(ctx, dummyRef.String(), llb.ResolveImageConfigOpt{
Platform: opt.Platform,
ResolveMode: opt.ResolveMode,
LogName: fmt.Sprintf("[context %s] load metadata for %s", nameWithPlatform, dummyRef.String()),
@ -153,6 +172,9 @@ func (bc *Client) namedContext(ctx context.Context, name string, nameWithPlatfor
if err != nil {
return nil, nil, err
}
if opt.CaptureDigest != nil {
*opt.CaptureDigest = dgst
}
return &st, &img, nil
case "local":
st := llb.Local(vv[1],

View File

@ -27,7 +27,7 @@ func NewResult() *Result {
type Client interface {
Solve(ctx context.Context, req SolveRequest) (*Result, error)
ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (digest.Digest, []byte, error)
ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (string, digest.Digest, []byte, error)
BuildOpts() BuildOpts
Inputs(ctx context.Context) (map[string]llb.State, error)
NewContainer(ctx context.Context, req NewContainerRequest) (Container, error)
@ -71,6 +71,7 @@ type Container interface {
type StartRequest struct {
Args []string
Env []string
SecretEnv []*pb.SecretEnv
User string
Cwd string
Tty bool

View File

@ -478,7 +478,7 @@ func (c *grpcClient) Solve(ctx context.Context, creq client.SolveRequest) (res *
return res, nil
}
func (c *grpcClient) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (digest.Digest, []byte, error) {
func (c *grpcClient) ResolveImageConfig(ctx context.Context, ref string, opt llb.ResolveImageConfigOpt) (string, digest.Digest, []byte, error) {
var p *opspb.Platform
if platform := opt.Platform; platform != nil {
p = &opspb.Platform{
@ -489,19 +489,27 @@ func (c *grpcClient) ResolveImageConfig(ctx context.Context, ref string, opt llb
OSFeatures: platform.OSFeatures,
}
}
resp, err := c.client.ResolveImageConfig(ctx, &pb.ResolveImageConfigRequest{
ResolverType: int32(opt.ResolverType),
Ref: ref,
Platform: p,
ResolveMode: opt.ResolveMode,
LogName: opt.LogName,
SessionID: opt.Store.SessionID,
StoreID: opt.Store.StoreID,
ResolverType: int32(opt.ResolverType),
Ref: ref,
Platform: p,
ResolveMode: opt.ResolveMode,
LogName: opt.LogName,
SessionID: opt.Store.SessionID,
StoreID: opt.Store.StoreID,
SourcePolicies: opt.SourcePolicies,
})
if err != nil {
return "", nil, err
return "", "", nil, err
}
return resp.Digest, resp.Config, nil
newRef := resp.Ref
if newRef == "" {
// No ref returned, use the original one.
// This could occur if the version of buildkitd is too old.
newRef = ref
}
return newRef, resp.Digest, resp.Config, nil
}
func (c *grpcClient) BuildOpts() client.BuildOpts {
@ -806,6 +814,7 @@ func (c *grpcClient) NewContainer(ctx context.Context, req client.NewContainerRe
return &container{
client: c.client,
caps: c.caps,
id: id,
execMsgs: c.execMsgs,
}, nil
@ -813,6 +822,7 @@ func (c *grpcClient) NewContainer(ctx context.Context, req client.NewContainerRe
type container struct {
client pb.LLBBridgeClient
caps apicaps.CapSet
id string
execMsgs *messageForwarder
}
@ -821,6 +831,12 @@ func (ctr *container) Start(ctx context.Context, req client.StartRequest) (clien
pid := fmt.Sprintf("%s:%s", ctr.id, identity.NewID())
msgs := ctr.execMsgs.Register(pid)
if len(req.SecretEnv) > 0 {
if err := ctr.caps.Supports(pb.CapGatewayExecSecretEnv); err != nil {
return nil, err
}
}
init := &pb.InitMessage{
ContainerID: ctr.id,
Meta: &opspb.Meta{
@ -829,8 +845,9 @@ func (ctr *container) Start(ctx context.Context, req client.StartRequest) (clien
Cwd: req.Cwd,
User: req.User,
},
Tty: req.Tty,
Security: req.SecurityMode,
Tty: req.Tty,
Security: req.SecurityMode,
Secretenv: req.SecretEnv,
}
init.Meta.RemoveMountStubsRecursive = req.RemoveMountStubsRecursive
if req.Stdin != nil {

View File

@ -44,6 +44,10 @@ const (
// /etc/hosts for containers created via gateway exec.
CapGatewayExecExtraHosts apicaps.CapID = "gateway.exec.extrahosts"
// CapGatewayExecExtraHosts is the capability to set secrets as env vars for
// containers created via gateway exec.
CapGatewayExecSecretEnv apicaps.CapID = "gateway.exec.secretenv"
// CapGatewayExecExtraHosts is the capability to send signals to a process
// created via gateway exec.
CapGatewayExecSignals apicaps.CapID = "gateway.exec.signals"
@ -179,6 +183,13 @@ func init() {
Status: apicaps.CapStatusExperimental,
})
Caps.Init(apicaps.Cap{
ID: CapGatewayExecSecretEnv,
Name: "gateway exec secret env",
Enabled: true,
Status: apicaps.CapStatusExperimental,
})
Caps.Init(apicaps.Cap{
ID: CapGatewayExecSignals,
Name: "gateway exec signals",

View File

@ -736,16 +736,17 @@ func (m *InputsResponse) GetDefinitions() map[string]*pb.Definition {
}
type ResolveImageConfigRequest struct {
Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
Platform *pb.Platform `protobuf:"bytes,2,opt,name=Platform,proto3" json:"Platform,omitempty"`
ResolveMode string `protobuf:"bytes,3,opt,name=ResolveMode,proto3" json:"ResolveMode,omitempty"`
LogName string `protobuf:"bytes,4,opt,name=LogName,proto3" json:"LogName,omitempty"`
ResolverType int32 `protobuf:"varint,5,opt,name=ResolverType,proto3" json:"ResolverType,omitempty"`
SessionID string `protobuf:"bytes,6,opt,name=SessionID,proto3" json:"SessionID,omitempty"`
StoreID string `protobuf:"bytes,7,opt,name=StoreID,proto3" json:"StoreID,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
Ref string `protobuf:"bytes,1,opt,name=Ref,proto3" json:"Ref,omitempty"`
Platform *pb.Platform `protobuf:"bytes,2,opt,name=Platform,proto3" json:"Platform,omitempty"`
ResolveMode string `protobuf:"bytes,3,opt,name=ResolveMode,proto3" json:"ResolveMode,omitempty"`
LogName string `protobuf:"bytes,4,opt,name=LogName,proto3" json:"LogName,omitempty"`
ResolverType int32 `protobuf:"varint,5,opt,name=ResolverType,proto3" json:"ResolverType,omitempty"`
SessionID string `protobuf:"bytes,6,opt,name=SessionID,proto3" json:"SessionID,omitempty"`
StoreID string `protobuf:"bytes,7,opt,name=StoreID,proto3" json:"StoreID,omitempty"`
SourcePolicies []*pb1.Policy `protobuf:"bytes,8,rep,name=SourcePolicies,proto3" json:"SourcePolicies,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
func (m *ResolveImageConfigRequest) Reset() { *m = ResolveImageConfigRequest{} }
@ -830,9 +831,17 @@ func (m *ResolveImageConfigRequest) GetStoreID() string {
return ""
}
func (m *ResolveImageConfigRequest) GetSourcePolicies() []*pb1.Policy {
if m != nil {
return m.SourcePolicies
}
return nil
}
type ResolveImageConfigResponse struct {
Digest github_com_opencontainers_go_digest.Digest `protobuf:"bytes,1,opt,name=Digest,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"Digest"`
Config []byte `protobuf:"bytes,2,opt,name=Config,proto3" json:"Config,omitempty"`
Ref string `protobuf:"bytes,3,opt,name=Ref,proto3" json:"Ref,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -878,6 +887,13 @@ func (m *ResolveImageConfigResponse) GetConfig() []byte {
return nil
}
func (m *ResolveImageConfigResponse) GetRef() string {
if m != nil {
return m.Ref
}
return ""
}
type SolveRequest struct {
Definition *pb.Definition `protobuf:"bytes,1,opt,name=Definition,proto3" json:"Definition,omitempty"`
Frontend string `protobuf:"bytes,2,opt,name=Frontend,proto3" json:"Frontend,omitempty"`
@ -2204,6 +2220,7 @@ type InitMessage struct {
Fds []uint32 `protobuf:"varint,3,rep,packed,name=Fds,proto3" json:"Fds,omitempty"`
Tty bool `protobuf:"varint,4,opt,name=Tty,proto3" json:"Tty,omitempty"`
Security pb.SecurityMode `protobuf:"varint,5,opt,name=Security,proto3,enum=pb.SecurityMode" json:"Security,omitempty"`
Secretenv []*pb.SecretEnv `protobuf:"bytes,6,rep,name=secretenv,proto3" json:"secretenv,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
@ -2277,6 +2294,13 @@ func (m *InitMessage) GetSecurity() pb.SecurityMode {
return pb.SecurityMode_SANDBOX
}
func (m *InitMessage) GetSecretenv() []*pb.SecretEnv {
if m != nil {
return m.Secretenv
}
return nil
}
type ExitMessage struct {
Code uint32 `protobuf:"varint,1,opt,name=Code,proto3" json:"Code,omitempty"`
Error *rpc.Status `protobuf:"bytes,2,opt,name=Error,proto3" json:"Error,omitempty"`
@ -2635,161 +2659,164 @@ func init() {
func init() { proto.RegisterFile("gateway.proto", fileDescriptor_f1a937782ebbded5) }
var fileDescriptor_f1a937782ebbded5 = []byte{
// 2464 bytes of a gzipped FileDescriptorProto
// 2497 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x59, 0xcf, 0x6f, 0x1b, 0xc7,
0xf5, 0xd7, 0x8a, 0x14, 0x25, 0x3d, 0xfe, 0x10, 0x3d, 0x71, 0xf2, 0x65, 0x16, 0x81, 0x23, 0xaf,
0x63, 0x45, 0x56, 0x9c, 0xa5, 0xbf, 0xb2, 0x0d, 0xb9, 0x76, 0xeb, 0xc4, 0xfa, 0x05, 0x29, 0x96,
0x6c, 0x76, 0xe4, 0xc2, 0x45, 0x90, 0x02, 0x5d, 0x71, 0x87, 0xd4, 0xd6, 0xab, 0xdd, 0xed, 0xee,
0xd0, 0xb2, 0x92, 0x4b, 0x7b, 0x28, 0x50, 0xe4, 0x0f, 0xe8, 0x2d, 0x28, 0xd0, 0x02, 0x3d, 0xf5,
0xd0, 0xfe, 0x01, 0xed, 0x39, 0x40, 0x2f, 0x3d, 0xf7, 0x10, 0x14, 0xfe, 0x07, 0x7a, 0x2b, 0xd0,
0x5b, 0xf1, 0x66, 0x66, 0xc9, 0xe1, 0x0f, 0x2d, 0xc9, 0xfa, 0xc4, 0x99, 0x37, 0xef, 0xc7, 0xbc,
0xf7, 0xe6, 0xbd, 0xf9, 0xcc, 0x12, 0xca, 0x6d, 0x87, 0xb3, 0x33, 0xe7, 0xdc, 0x8e, 0xe2, 0x90,
0x87, 0xe4, 0xdd, 0xd3, 0xf0, 0xf8, 0xdc, 0x3e, 0xee, 0x78, 0xbe, 0xfb, 0xc2, 0xe3, 0xf6, 0xcb,
0xff, 0xb7, 0x5b, 0x71, 0x18, 0x70, 0x16, 0xb8, 0xe6, 0xc7, 0x6d, 0x8f, 0x9f, 0x74, 0x8e, 0xed,
0x66, 0x78, 0x5a, 0x6f, 0x87, 0xed, 0xb0, 0x2e, 0x24, 0x8e, 0x3b, 0x2d, 0x31, 0x13, 0x13, 0x31,
0x92, 0x9a, 0xcc, 0xf5, 0x41, 0xf6, 0x76, 0x18, 0xb6, 0x7d, 0xe6, 0x44, 0x5e, 0xa2, 0x86, 0xf5,
0x38, 0x6a, 0xd6, 0x13, 0xee, 0xf0, 0x4e, 0xa2, 0x64, 0x6e, 0x6a, 0x32, 0xb8, 0x91, 0x7a, 0xba,
0x91, 0x7a, 0x12, 0xfa, 0x2f, 0x59, 0x5c, 0x8f, 0x8e, 0xeb, 0x61, 0x94, 0x72, 0xd7, 0x2f, 0xe4,
0x76, 0x22, 0xaf, 0xce, 0xcf, 0x23, 0x96, 0xd4, 0xcf, 0xc2, 0xf8, 0x05, 0x8b, 0x95, 0xc0, 0xed,
0x0b, 0x05, 0x3a, 0xdc, 0xf3, 0x51, 0xaa, 0xe9, 0x44, 0x09, 0x1a, 0xc1, 0x5f, 0x25, 0xa4, 0xbb,
0xcd, 0xc3, 0xc0, 0x4b, 0xb8, 0xe7, 0xb5, 0xbd, 0x7a, 0x2b, 0x11, 0x32, 0xd2, 0x0a, 0x3a, 0xa1,
0xd8, 0xef, 0x66, 0xb8, 0xd0, 0x89, 0x9b, 0x2c, 0x0a, 0x7d, 0xaf, 0x79, 0x8e, 0x36, 0xe4, 0x48,
0x8a, 0x59, 0x7f, 0xcb, 0x43, 0x81, 0xb2, 0xa4, 0xe3, 0x73, 0xb2, 0x02, 0xe5, 0x98, 0xb5, 0xb6,
0x59, 0x14, 0xb3, 0xa6, 0xc3, 0x99, 0x5b, 0x33, 0x96, 0x8d, 0xd5, 0xc5, 0xbd, 0x19, 0xda, 0x4f,
0x26, 0x3f, 0x82, 0x4a, 0xcc, 0x5a, 0x89, 0xc6, 0x38, 0xbb, 0x6c, 0xac, 0x16, 0xd7, 0x3f, 0xb2,
0x2f, 0xcc, 0xa1, 0x4d, 0x59, 0xeb, 0xd0, 0x89, 0x7a, 0x22, 0x7b, 0x33, 0x74, 0x40, 0x09, 0x59,
0x87, 0x5c, 0xcc, 0x5a, 0xb5, 0x9c, 0xd0, 0x75, 0x25, 0x5b, 0xd7, 0xde, 0x0c, 0x45, 0x66, 0xb2,
0x01, 0x79, 0xd4, 0x52, 0xcb, 0x0b, 0xa1, 0xab, 0x63, 0x37, 0xb0, 0x37, 0x43, 0x85, 0x00, 0x79,
0x0c, 0x0b, 0xa7, 0x8c, 0x3b, 0xae, 0xc3, 0x9d, 0x1a, 0x2c, 0xe7, 0x56, 0x8b, 0xeb, 0xf5, 0x4c,
0x61, 0x0c, 0x90, 0x7d, 0xa8, 0x24, 0x76, 0x02, 0x1e, 0x9f, 0xd3, 0xae, 0x02, 0xf2, 0x1c, 0x4a,
0x0e, 0xe7, 0x0c, 0x93, 0xe1, 0x85, 0x41, 0x52, 0x2b, 0x09, 0x85, 0xb7, 0xc7, 0x2b, 0x7c, 0xa4,
0x49, 0x49, 0xa5, 0x7d, 0x8a, 0xcc, 0x07, 0x50, 0xee, 0xb3, 0x49, 0xaa, 0x90, 0x7b, 0xc1, 0xce,
0x65, 0x62, 0x28, 0x0e, 0xc9, 0x65, 0x98, 0x7b, 0xe9, 0xf8, 0x1d, 0x26, 0x72, 0x50, 0xa2, 0x72,
0x72, 0x7f, 0xf6, 0x9e, 0x61, 0x9e, 0xc0, 0xa5, 0x21, 0xfd, 0x23, 0x14, 0xfc, 0x40, 0x57, 0x50,
0x5c, 0xff, 0x30, 0x63, 0xd7, 0xba, 0x3a, 0xcd, 0xd2, 0xe6, 0x02, 0x14, 0x62, 0xe1, 0x90, 0xf5,
0x1b, 0x03, 0xaa, 0x83, 0xa9, 0x26, 0xfb, 0x2a, 0x49, 0x86, 0x08, 0xcb, 0xdd, 0x29, 0x4e, 0x09,
0x12, 0x54, 0x60, 0x84, 0x0a, 0x73, 0x03, 0x16, 0xbb, 0xa4, 0x71, 0xc1, 0x58, 0xd4, 0xb6, 0x68,
0x6d, 0x40, 0x8e, 0xb2, 0x16, 0xa9, 0xc0, 0xac, 0xa7, 0xce, 0x35, 0x9d, 0xf5, 0x5c, 0xb2, 0x0c,
0x39, 0x97, 0xb5, 0x94, 0xeb, 0x15, 0x3b, 0x3a, 0xb6, 0xb7, 0x59, 0xcb, 0x0b, 0x3c, 0x74, 0x91,
0xe2, 0x92, 0xf5, 0x3b, 0x03, 0xeb, 0x03, 0xb7, 0x45, 0x3e, 0xe9, 0xf3, 0x63, 0xfc, 0x69, 0x1f,
0xda, 0xfd, 0xf3, 0xec, 0xdd, 0xdf, 0xe9, 0xcf, 0xc4, 0x98, 0x12, 0xd0, 0xbd, 0xfb, 0x31, 0x94,
0xf4, 0xdc, 0x90, 0x3d, 0x28, 0x6a, 0xe7, 0x48, 0x6d, 0x78, 0x65, 0xb2, 0xcc, 0x52, 0x5d, 0xd4,
0xfa, 0x43, 0x0e, 0x8a, 0xda, 0x22, 0x79, 0x08, 0xf9, 0x17, 0x5e, 0x20, 0x43, 0x58, 0x59, 0x5f,
0x9b, 0x4c, 0xe5, 0x63, 0x2f, 0x70, 0xa9, 0x90, 0x23, 0x0d, 0xad, 0xee, 0x66, 0xc5, 0xb6, 0xee,
0x4c, 0xa6, 0xe3, 0xc2, 0xe2, 0xbb, 0x35, 0x45, 0xdb, 0x90, 0x4d, 0x83, 0x40, 0x3e, 0x72, 0xf8,
0x89, 0x68, 0x1a, 0x8b, 0x54, 0x8c, 0xc9, 0x2d, 0x78, 0xcb, 0x0b, 0x9e, 0x85, 0x3c, 0x6c, 0xc4,
0xcc, 0xf5, 0xf0, 0xf0, 0x3d, 0x3b, 0x8f, 0x58, 0x6d, 0x4e, 0xb0, 0x8c, 0x5a, 0x22, 0x0d, 0xa8,
0x48, 0xf2, 0x51, 0xe7, 0xf8, 0x67, 0xac, 0xc9, 0x93, 0x5a, 0x41, 0xf8, 0xb3, 0x9a, 0xb1, 0x85,
0x7d, 0x5d, 0x80, 0x0e, 0xc8, 0xbf, 0x51, 0xb5, 0x5b, 0x7f, 0x36, 0xa0, 0xdc, 0xa7, 0x9e, 0x7c,
0xda, 0x97, 0xaa, 0x9b, 0x93, 0x6e, 0x4b, 0x4b, 0xd6, 0x67, 0x50, 0x70, 0xbd, 0x36, 0x4b, 0xb8,
0x48, 0xd5, 0xe2, 0xe6, 0xfa, 0xb7, 0xdf, 0xbd, 0x3f, 0xf3, 0x8f, 0xef, 0xde, 0x5f, 0xd3, 0xae,
0x9a, 0x30, 0x62, 0x41, 0x33, 0x0c, 0xb8, 0xe3, 0x05, 0x2c, 0xc6, 0x0b, 0xf6, 0x63, 0x29, 0x62,
0x6f, 0x8b, 0x1f, 0xaa, 0x34, 0x60, 0xd0, 0x03, 0xe7, 0x94, 0x89, 0x3c, 0x2d, 0x52, 0x31, 0xb6,
0x38, 0x94, 0x29, 0xe3, 0x9d, 0x38, 0xa0, 0xec, 0xe7, 0x1d, 0x64, 0xfa, 0x5e, 0xda, 0x48, 0xc4,
0xa6, 0xc7, 0x35, 0x74, 0x64, 0xa4, 0x4a, 0x80, 0xac, 0xc2, 0x1c, 0x8b, 0xe3, 0x30, 0x56, 0xc5,
0x43, 0x6c, 0x79, 0xd5, 0xdb, 0x71, 0xd4, 0xb4, 0x8f, 0xc4, 0x55, 0x4f, 0x25, 0x83, 0x55, 0x85,
0x4a, 0x6a, 0x35, 0x89, 0xc2, 0x20, 0x61, 0xd6, 0x12, 0x86, 0x2e, 0xea, 0xf0, 0x44, 0xed, 0xc3,
0xfa, 0xab, 0x01, 0x95, 0x94, 0x22, 0x79, 0xc8, 0x17, 0x50, 0xec, 0xb5, 0x86, 0xb4, 0x07, 0xdc,
0xcf, 0x0c, 0xaa, 0x2e, 0xaf, 0xf5, 0x15, 0xd5, 0x12, 0x74, 0x75, 0xe6, 0x13, 0xa8, 0x0e, 0x32,
0x8c, 0xc8, 0xfe, 0x07, 0xfd, 0x0d, 0x62, 0xb0, 0x5f, 0x69, 0xa7, 0xe1, 0x5f, 0x06, 0xbc, 0x4b,
0x99, 0xc0, 0x2e, 0xfb, 0xa7, 0x4e, 0x9b, 0x6d, 0x85, 0x41, 0xcb, 0x6b, 0xa7, 0x61, 0xae, 0x8a,
0x66, 0x98, 0x6a, 0xc6, 0xbe, 0xb8, 0x0a, 0x0b, 0x0d, 0xdf, 0xe1, 0xad, 0x30, 0x3e, 0x55, 0xca,
0x4b, 0xa8, 0x3c, 0xa5, 0xd1, 0xee, 0x2a, 0x59, 0x86, 0xa2, 0x52, 0x7c, 0x18, 0xba, 0x69, 0x3a,
0x75, 0x12, 0xa9, 0xc1, 0xfc, 0x41, 0xd8, 0x7e, 0x82, 0xc9, 0x96, 0x15, 0x96, 0x4e, 0x89, 0x05,
0x25, 0xc5, 0x18, 0x77, 0xab, 0x6b, 0x8e, 0xf6, 0xd1, 0xc8, 0x7b, 0xb0, 0x78, 0xc4, 0x92, 0xc4,
0x0b, 0x83, 0xfd, 0xed, 0x5a, 0x41, 0xc8, 0xf7, 0x08, 0xa8, 0xfb, 0x88, 0x87, 0x31, 0xdb, 0xdf,
0xae, 0xcd, 0x4b, 0xdd, 0x6a, 0x6a, 0xfd, 0xc2, 0x00, 0x73, 0x94, 0xc7, 0x2a, 0x7d, 0x9f, 0x41,
0x41, 0x1e, 0x48, 0xe9, 0xf5, 0xff, 0x76, 0x94, 0xe5, 0x2f, 0x79, 0x07, 0x0a, 0x52, 0xbb, 0xaa,
0x42, 0x35, 0xb3, 0x7e, 0x55, 0x80, 0xd2, 0x11, 0x6e, 0x20, 0x8d, 0xb3, 0x0d, 0xd0, 0x4b, 0x8f,
0x3a, 0xd2, 0x83, 0x49, 0xd3, 0x38, 0x88, 0x09, 0x0b, 0xbb, 0xea, 0xf8, 0xa8, 0x1b, 0xac, 0x3b,
0x27, 0x9f, 0x43, 0x31, 0x1d, 0x3f, 0x8d, 0x78, 0x2d, 0x27, 0xce, 0xdf, 0xbd, 0x8c, 0xf3, 0xa7,
0xef, 0xc4, 0xd6, 0x44, 0xd5, 0xe9, 0xd3, 0x28, 0xe4, 0x26, 0x5c, 0x72, 0x7c, 0x3f, 0x3c, 0x53,
0x25, 0x25, 0x8a, 0x43, 0x24, 0x67, 0x81, 0x0e, 0x2f, 0x60, 0xab, 0xd4, 0x88, 0x8f, 0xe2, 0xd8,
0x39, 0xc7, 0xd3, 0x54, 0x10, 0xfc, 0xa3, 0x96, 0xb0, 0x6b, 0xed, 0x7a, 0x81, 0xe3, 0xd7, 0x40,
0xf0, 0xc8, 0x09, 0x9e, 0x86, 0x9d, 0x57, 0x51, 0x18, 0x73, 0x16, 0x3f, 0xe2, 0x3c, 0xae, 0x15,
0x45, 0x30, 0xfb, 0x68, 0xa4, 0x01, 0xa5, 0x2d, 0xa7, 0x79, 0xc2, 0xf6, 0x4f, 0x91, 0x98, 0x22,
0xab, 0xac, 0x5e, 0x26, 0xd8, 0x9f, 0x46, 0x3a, 0xa4, 0xd2, 0x35, 0x90, 0x26, 0x54, 0x52, 0xd7,
0x65, 0x85, 0xd6, 0xca, 0x42, 0xe7, 0x83, 0x69, 0x43, 0x29, 0xa5, 0xa5, 0x89, 0x01, 0x95, 0x98,
0xc8, 0x1d, 0x2c, 0x46, 0x87, 0xb3, 0x5a, 0x45, 0xf8, 0xdc, 0x9d, 0x93, 0x43, 0xa8, 0x1c, 0x09,
0x40, 0xde, 0x40, 0x18, 0xee, 0xb1, 0xa4, 0xb6, 0x24, 0x36, 0x70, 0x7d, 0x78, 0x03, 0x3a, 0x70,
0xb7, 0x05, 0xfb, 0x39, 0x1d, 0x10, 0x36, 0x1f, 0x42, 0x75, 0x30, 0xb9, 0xd3, 0x00, 0x23, 0xf3,
0x87, 0xf0, 0xd6, 0x08, 0x8f, 0xde, 0xa8, 0xf9, 0xfc, 0xc9, 0x80, 0x4b, 0x43, 0x69, 0xc0, 0x0b,
0x40, 0x14, 0xbd, 0x54, 0x29, 0xc6, 0xe4, 0x10, 0xe6, 0x30, 0xcd, 0x89, 0x82, 0x02, 0x1b, 0xd3,
0xe4, 0xd5, 0x16, 0x92, 0x32, 0xfe, 0x52, 0x8b, 0x79, 0x0f, 0xa0, 0x47, 0x9c, 0x0a, 0x1e, 0x7e,
0x01, 0x65, 0x95, 0x64, 0xd5, 0x2f, 0xaa, 0x12, 0x55, 0x28, 0x61, 0x44, 0x0d, 0xbd, 0xbb, 0x29,
0x37, 0xe5, 0xdd, 0x64, 0x7d, 0x05, 0x4b, 0x94, 0x39, 0xee, 0xae, 0xe7, 0xb3, 0x8b, 0x5b, 0x30,
0x16, 0xbf, 0xe7, 0xb3, 0x06, 0x22, 0x93, 0xb4, 0xf8, 0xd5, 0x9c, 0xdc, 0x87, 0x39, 0xea, 0x04,
0x6d, 0xa6, 0x4c, 0x7f, 0x90, 0x61, 0x5a, 0x18, 0x41, 0x5e, 0x2a, 0x45, 0xac, 0x07, 0xb0, 0xd8,
0xa5, 0x61, 0xeb, 0x7a, 0xda, 0x6a, 0x25, 0x4c, 0xb6, 0xc1, 0x1c, 0x55, 0x33, 0xa4, 0x1f, 0xb0,
0xa0, 0xad, 0x4c, 0xe7, 0xa8, 0x9a, 0x59, 0x2b, 0x08, 0xe7, 0xd3, 0x9d, 0xab, 0xd0, 0x10, 0xc8,
0x6f, 0x23, 0x7c, 0x33, 0x44, 0xbd, 0x8a, 0xb1, 0xe5, 0xe2, 0x9d, 0xea, 0xb8, 0xdb, 0x5e, 0x7c,
0xb1, 0x83, 0x35, 0x98, 0xdf, 0xf6, 0x62, 0xcd, 0xbf, 0x74, 0x4a, 0x56, 0xf0, 0xb6, 0x6d, 0xfa,
0x1d, 0x17, 0xbd, 0xe5, 0x2c, 0x0e, 0xd4, 0xb5, 0x32, 0x40, 0xb5, 0x3e, 0x91, 0x71, 0x14, 0x56,
0xd4, 0x66, 0x6e, 0xc2, 0x3c, 0x0b, 0x78, 0x8c, 0x65, 0x24, 0xaf, 0x64, 0x62, 0xcb, 0x07, 0xb2,
0x2d, 0x1e, 0xc8, 0xe2, 0xea, 0xa7, 0x29, 0x8b, 0xb5, 0x01, 0x4b, 0x48, 0xc8, 0x4e, 0x04, 0x81,
0xbc, 0xb6, 0x49, 0x31, 0xb6, 0xee, 0x43, 0xb5, 0x27, 0xa8, 0x4c, 0xaf, 0x40, 0x1e, 0xb1, 0xa9,
0xea, 0xeb, 0xa3, 0xec, 0x8a, 0x75, 0xeb, 0x1a, 0x2c, 0xa5, 0xc5, 0x7f, 0xa1, 0x51, 0x8b, 0x40,
0xb5, 0xc7, 0xa4, 0x60, 0x49, 0x19, 0x8a, 0x0d, 0x2f, 0x48, 0x6f, 0x6d, 0xeb, 0xb5, 0x01, 0xa5,
0x46, 0x18, 0xf4, 0xee, 0xb4, 0x06, 0x2c, 0xa5, 0xa5, 0xfb, 0xa8, 0xb1, 0xbf, 0xe5, 0x44, 0x69,
0x0c, 0x96, 0x87, 0xcf, 0x87, 0xfa, 0xc4, 0x60, 0x4b, 0xc6, 0xcd, 0x3c, 0x5e, 0x7f, 0x74, 0x50,
0x9c, 0x7c, 0x0a, 0xf3, 0x07, 0x07, 0x9b, 0x42, 0xd3, 0xec, 0x54, 0x9a, 0x52, 0x31, 0xf2, 0x10,
0xe6, 0x9f, 0x8b, 0x2f, 0x1f, 0x89, 0xba, 0xa2, 0x46, 0x9c, 0x55, 0x19, 0x21, 0xc9, 0x46, 0x59,
0x33, 0x8c, 0x5d, 0x9a, 0x0a, 0x59, 0xff, 0x36, 0xa0, 0xf8, 0xdc, 0xe9, 0x21, 0xc2, 0x1e, 0x04,
0x7d, 0x83, 0x7b, 0x5b, 0x41, 0xd0, 0xcb, 0x30, 0xe7, 0xb3, 0x97, 0xcc, 0x57, 0x67, 0x5c, 0x4e,
0x90, 0x9a, 0x9c, 0x84, 0xb1, 0x2c, 0xeb, 0x12, 0x95, 0x13, 0x2c, 0x08, 0x97, 0x71, 0xc7, 0xf3,
0x6b, 0xf9, 0xe5, 0x1c, 0xde, 0xf1, 0x72, 0x86, 0x99, 0xeb, 0xc4, 0xbe, 0x7a, 0x17, 0xe0, 0x90,
0x58, 0x90, 0xf7, 0x82, 0x56, 0x28, 0xee, 0x3f, 0xd5, 0x16, 0x65, 0x8b, 0xde, 0x0f, 0x5a, 0x21,
0x15, 0x6b, 0xe4, 0x2a, 0x14, 0x62, 0xac, 0xbf, 0xa4, 0x36, 0x2f, 0x82, 0xb2, 0x88, 0x5c, 0xb2,
0x4a, 0xd5, 0x82, 0x55, 0x81, 0x92, 0xf4, 0x5b, 0x25, 0xff, 0x8f, 0xb3, 0xf0, 0xd6, 0x13, 0x76,
0xb6, 0x95, 0xfa, 0x95, 0x06, 0x64, 0x19, 0x8a, 0x5d, 0xda, 0xfe, 0xb6, 0x3a, 0x42, 0x3a, 0x09,
0x8d, 0x1d, 0x86, 0x9d, 0x80, 0xa7, 0x39, 0x14, 0xc6, 0x04, 0x85, 0xaa, 0x05, 0x72, 0x1d, 0xe6,
0x9f, 0x30, 0x7e, 0x16, 0xc6, 0x2f, 0x84, 0xd7, 0x95, 0xf5, 0x22, 0xf2, 0x3c, 0x61, 0x1c, 0x01,
0x1c, 0x4d, 0xd7, 0x10, 0x15, 0x46, 0x29, 0x2a, 0xcc, 0x8f, 0x42, 0x85, 0xe9, 0x2a, 0xd9, 0x80,
0x62, 0x33, 0x0c, 0x12, 0x1e, 0x3b, 0x1e, 0x1a, 0x9e, 0x13, 0xcc, 0x6f, 0x23, 0xb3, 0x4c, 0xec,
0x56, 0x6f, 0x91, 0xea, 0x9c, 0x64, 0x0d, 0x80, 0xbd, 0xe2, 0xb1, 0xb3, 0x17, 0x26, 0xdd, 0x17,
0x14, 0xa0, 0x1c, 0x12, 0xf6, 0x1b, 0x54, 0x5b, 0xc5, 0x0e, 0x79, 0x12, 0x26, 0x5c, 0x3c, 0x23,
0x24, 0xfa, 0xeb, 0xce, 0xad, 0x77, 0xe0, 0x72, 0x7f, 0xb4, 0x54, 0x18, 0x1f, 0xc0, 0xff, 0x51,
0xe6, 0x33, 0x27, 0x61, 0xd3, 0x47, 0xd2, 0x32, 0xa1, 0x36, 0x2c, 0xac, 0x14, 0xff, 0x27, 0x07,
0xc5, 0x9d, 0x57, 0xac, 0x79, 0xc8, 0x92, 0xc4, 0x69, 0x0b, 0xdc, 0xda, 0x88, 0xc3, 0x26, 0x4b,
0x92, 0xae, 0xae, 0x1e, 0x81, 0x7c, 0x1f, 0xf2, 0xfb, 0x81, 0xc7, 0xd5, 0xdd, 0xb9, 0x92, 0xf9,
0x6c, 0xf0, 0xb8, 0xd2, 0xb9, 0x37, 0x43, 0x85, 0x14, 0xb9, 0x0f, 0x79, 0xec, 0x3c, 0x93, 0x74,
0x7f, 0x57, 0x93, 0x45, 0x19, 0xb2, 0x29, 0x3e, 0xef, 0x79, 0x5f, 0x32, 0x95, 0xc1, 0xd5, 0xec,
0x6b, 0xcb, 0xfb, 0x92, 0xf5, 0x34, 0x28, 0x49, 0xb2, 0x83, 0xa8, 0xdb, 0x89, 0x39, 0x73, 0x55,
0x66, 0x6f, 0x64, 0x81, 0x25, 0xc9, 0xd9, 0xd3, 0x92, 0xca, 0x62, 0x10, 0x76, 0x5e, 0x79, 0x5c,
0x55, 0x4a, 0x56, 0x10, 0x90, 0x4d, 0x73, 0x04, 0xa7, 0x28, 0xbd, 0x1d, 0x06, 0x32, 0xf3, 0xd9,
0xd2, 0xc8, 0xa6, 0x49, 0xe3, 0x14, 0xc3, 0x70, 0xe4, 0xb5, 0x11, 0x83, 0x2e, 0x8c, 0x0d, 0x83,
0x64, 0xd4, 0xc2, 0x20, 0x09, 0x9b, 0xf3, 0x30, 0x27, 0x20, 0x92, 0xf5, 0x5b, 0x03, 0x8a, 0x5a,
0x9e, 0x26, 0xa8, 0xc9, 0xf7, 0x20, 0x8f, 0x4f, 0x7b, 0x95, 0xff, 0x05, 0x51, 0x91, 0x8c, 0x3b,
0x54, 0x50, 0xb1, 0xa9, 0xec, 0xba, 0xb2, 0x61, 0x96, 0x29, 0x0e, 0x91, 0xf2, 0x8c, 0x9f, 0x8b,
0x94, 0x2d, 0x50, 0x1c, 0x92, 0x9b, 0xb0, 0x70, 0xc4, 0x9a, 0x9d, 0xd8, 0xe3, 0xe7, 0x22, 0x09,
0x95, 0xf5, 0xaa, 0x68, 0x35, 0x8a, 0x26, 0x0a, 0xb7, 0xcb, 0x61, 0x3d, 0xc6, 0xc3, 0xd9, 0xdb,
0x20, 0x81, 0xfc, 0x16, 0xbe, 0xd6, 0x70, 0x67, 0x65, 0x2a, 0xc6, 0xf8, 0x60, 0xde, 0x19, 0xf7,
0x60, 0xde, 0x49, 0x1f, 0xcc, 0xfd, 0x49, 0xc5, 0x9b, 0x49, 0x0b, 0xb2, 0xf5, 0x08, 0x16, 0xbb,
0x07, 0x8f, 0x54, 0x60, 0x76, 0xd7, 0x55, 0x96, 0x66, 0x77, 0x5d, 0x74, 0x65, 0xe7, 0xe9, 0xae,
0xb0, 0xb2, 0x40, 0x71, 0xd8, 0x05, 0x10, 0x39, 0x0d, 0x40, 0x6c, 0x40, 0xb9, 0xef, 0xf4, 0x21,
0x13, 0x0d, 0xcf, 0x92, 0x74, 0xcb, 0x38, 0x96, 0x6e, 0xf8, 0x89, 0xd0, 0x25, 0xdc, 0xf0, 0x13,
0xeb, 0x1a, 0x94, 0xfb, 0xf2, 0x85, 0x4c, 0xe2, 0xed, 0xa9, 0x70, 0x26, 0x8e, 0xd7, 0x18, 0x2c,
0x0d, 0x7c, 0x8e, 0x22, 0xd7, 0xa1, 0x20, 0x3f, 0x7b, 0x54, 0x67, 0xcc, 0x77, 0xbf, 0xfe, 0x66,
0xf9, 0xed, 0x01, 0x06, 0xb9, 0x88, 0x6c, 0x9b, 0x9d, 0xc0, 0xf5, 0x59, 0xd5, 0x18, 0xc9, 0x26,
0x17, 0xcd, 0xfc, 0xaf, 0x7f, 0x7f, 0x65, 0x66, 0xcd, 0x81, 0x4b, 0x43, 0x9f, 0x52, 0xc8, 0x35,
0xc8, 0x1f, 0x31, 0xbf, 0x95, 0x9a, 0x19, 0x62, 0xc0, 0x45, 0x72, 0x15, 0x72, 0xd4, 0x39, 0xab,
0x1a, 0x66, 0xed, 0xeb, 0x6f, 0x96, 0x2f, 0x0f, 0x7f, 0x8f, 0x71, 0xce, 0xa4, 0x89, 0xf5, 0xbf,
0x00, 0x2c, 0x1e, 0x1c, 0x6c, 0x6e, 0xc6, 0x9e, 0xdb, 0x66, 0xe4, 0x97, 0x06, 0x90, 0xe1, 0x47,
0x2f, 0xb9, 0x93, 0x5d, 0xe3, 0xa3, 0xbf, 0x0a, 0x98, 0x77, 0xa7, 0x94, 0x52, 0x28, 0xe4, 0x73,
0x98, 0x13, 0xd0, 0x99, 0x7c, 0x38, 0xe1, 0x0b, 0xca, 0x5c, 0x1d, 0xcf, 0xa8, 0x74, 0x37, 0x61,
0x21, 0x85, 0x9f, 0x64, 0x2d, 0x73, 0x7b, 0x7d, 0xe8, 0xda, 0xfc, 0x68, 0x22, 0x5e, 0x65, 0xe4,
0xa7, 0x30, 0xaf, 0x50, 0x25, 0xb9, 0x31, 0x46, 0xae, 0x87, 0x6f, 0xcd, 0xb5, 0x49, 0x58, 0x7b,
0x6e, 0xa4, 0xe8, 0x31, 0xd3, 0x8d, 0x01, 0x6c, 0x9a, 0xe9, 0xc6, 0x10, 0x1c, 0x6d, 0xf6, 0xde,
0x9c, 0x99, 0x46, 0x06, 0xb0, 0x68, 0xa6, 0x91, 0x41, 0x48, 0x4a, 0x9e, 0x43, 0x1e, 0x21, 0x29,
0xc9, 0x6a, 0xbf, 0x1a, 0x66, 0x35, 0xb3, 0xce, 0x44, 0x1f, 0x96, 0xfd, 0x09, 0x5e, 0x53, 0xe2,
0xf3, 0x42, 0xf6, 0x05, 0xa5, 0x7d, 0x2d, 0x34, 0x6f, 0x4c, 0xc0, 0xd9, 0x53, 0xaf, 0x9e, 0xe6,
0xab, 0x13, 0x7c, 0xb2, 0x1b, 0xaf, 0x7e, 0xe0, 0xe3, 0x60, 0x08, 0x25, 0x1d, 0x7d, 0x10, 0x3b,
0x43, 0x74, 0x04, 0xa8, 0x33, 0xeb, 0x13, 0xf3, 0x2b, 0x83, 0x5f, 0xe1, 0xbb, 0xac, 0x1f, 0x99,
0x90, 0xf5, 0xcc, 0x70, 0x8c, 0xc4, 0x40, 0xe6, 0xed, 0xa9, 0x64, 0x94, 0x71, 0x47, 0x22, 0x1f,
0x85, 0x6e, 0x48, 0xf6, 0x45, 0xde, 0x45, 0x48, 0xe6, 0x84, 0x7c, 0xab, 0xc6, 0x2d, 0x03, 0xcf,
0x19, 0xa2, 0xe1, 0x4c, 0xdd, 0xda, 0x33, 0x21, 0xf3, 0x9c, 0xe9, 0xb0, 0x7a, 0xb3, 0xf4, 0xed,
0xeb, 0x2b, 0xc6, 0xdf, 0x5f, 0x5f, 0x31, 0xfe, 0xf9, 0xfa, 0x8a, 0x71, 0x5c, 0x10, 0xff, 0x81,
0xde, 0xfe, 0x6f, 0x00, 0x00, 0x00, 0xff, 0xff, 0xec, 0xb9, 0xed, 0xf9, 0x8c, 0x1e, 0x00, 0x00,
0xf5, 0xd7, 0x8a, 0x14, 0x45, 0x3e, 0xfe, 0x10, 0x3d, 0x71, 0xf2, 0xa5, 0x17, 0x81, 0x23, 0xaf,
0x63, 0x45, 0x96, 0x1d, 0xd2, 0x5f, 0xd9, 0x86, 0x5c, 0xbb, 0x75, 0x62, 0xfd, 0x82, 0x14, 0x4b,
0x36, 0x3b, 0x72, 0xe1, 0x22, 0x48, 0x81, 0xae, 0xb8, 0x43, 0x6a, 0xeb, 0xd5, 0xee, 0x76, 0x77,
0x28, 0x59, 0xc9, 0xa9, 0x87, 0x02, 0x45, 0x8e, 0x3d, 0xf4, 0x96, 0x4b, 0x0b, 0xf4, 0xd4, 0x43,
0xfb, 0x07, 0x34, 0xe7, 0x00, 0xed, 0xa1, 0xe7, 0x1e, 0x82, 0xc2, 0x7f, 0x44, 0x81, 0xde, 0x8a,
0x37, 0x33, 0x4b, 0x0e, 0x7f, 0x68, 0x45, 0xd6, 0x27, 0xce, 0xbc, 0x79, 0x3f, 0xe6, 0xbd, 0x37,
0xef, 0xcd, 0x67, 0x96, 0x50, 0xee, 0xd8, 0x9c, 0x9d, 0xda, 0x67, 0xf5, 0x30, 0x0a, 0x78, 0x40,
0xae, 0x1c, 0x07, 0x87, 0x67, 0xf5, 0xc3, 0xae, 0xeb, 0x39, 0xaf, 0x5c, 0x5e, 0x3f, 0xf9, 0xff,
0x7a, 0x3b, 0x0a, 0x7c, 0xce, 0x7c, 0xc7, 0xfc, 0xb8, 0xe3, 0xf2, 0xa3, 0xee, 0x61, 0xbd, 0x15,
0x1c, 0x37, 0x3a, 0x41, 0x27, 0x68, 0x08, 0x89, 0xc3, 0x6e, 0x5b, 0xcc, 0xc4, 0x44, 0x8c, 0xa4,
0x26, 0x73, 0x75, 0x98, 0xbd, 0x13, 0x04, 0x1d, 0x8f, 0xd9, 0xa1, 0x1b, 0xab, 0x61, 0x23, 0x0a,
0x5b, 0x8d, 0x98, 0xdb, 0xbc, 0x1b, 0x2b, 0x99, 0xdb, 0x9a, 0x0c, 0x6e, 0xa4, 0x91, 0x6c, 0xa4,
0x11, 0x07, 0xde, 0x09, 0x8b, 0x1a, 0xe1, 0x61, 0x23, 0x08, 0x13, 0xee, 0xc6, 0xb9, 0xdc, 0x76,
0xe8, 0x36, 0xf8, 0x59, 0xc8, 0xe2, 0xc6, 0x69, 0x10, 0xbd, 0x62, 0x91, 0x12, 0xb8, 0x7b, 0xae,
0x40, 0x97, 0xbb, 0x1e, 0x4a, 0xb5, 0xec, 0x30, 0x46, 0x23, 0xf8, 0xab, 0x84, 0x74, 0xb7, 0x79,
0xe0, 0xbb, 0x31, 0x77, 0xdd, 0x8e, 0xdb, 0x68, 0xc7, 0x42, 0x46, 0x5a, 0x41, 0x27, 0x14, 0xfb,
0xfd, 0x14, 0x17, 0xba, 0x51, 0x8b, 0x85, 0x81, 0xe7, 0xb6, 0xce, 0xd0, 0x86, 0x1c, 0x49, 0x31,
0xeb, 0x6f, 0x59, 0xc8, 0x51, 0x16, 0x77, 0x3d, 0x4e, 0x96, 0xa0, 0x1c, 0xb1, 0xf6, 0x26, 0x0b,
0x23, 0xd6, 0xb2, 0x39, 0x73, 0x6a, 0xc6, 0xa2, 0xb1, 0x5c, 0xd8, 0x99, 0xa1, 0x83, 0x64, 0xf2,
0x13, 0xa8, 0x44, 0xac, 0x1d, 0x6b, 0x8c, 0xb3, 0x8b, 0xc6, 0x72, 0x71, 0xf5, 0x56, 0xfd, 0xdc,
0x1c, 0xd6, 0x29, 0x6b, 0xef, 0xdb, 0x61, 0x5f, 0x64, 0x67, 0x86, 0x0e, 0x29, 0x21, 0xab, 0x90,
0x89, 0x58, 0xbb, 0x96, 0x11, 0xba, 0xae, 0xa6, 0xeb, 0xda, 0x99, 0xa1, 0xc8, 0x4c, 0xd6, 0x20,
0x8b, 0x5a, 0x6a, 0x59, 0x21, 0x74, 0xed, 0xc2, 0x0d, 0xec, 0xcc, 0x50, 0x21, 0x40, 0x9e, 0x42,
0xfe, 0x98, 0x71, 0xdb, 0xb1, 0xb9, 0x5d, 0x83, 0xc5, 0xcc, 0x72, 0x71, 0xb5, 0x91, 0x2a, 0x8c,
0x01, 0xaa, 0xef, 0x2b, 0x89, 0x2d, 0x9f, 0x47, 0x67, 0xb4, 0xa7, 0x80, 0xbc, 0x84, 0x92, 0xcd,
0x39, 0xc3, 0x64, 0xb8, 0x81, 0x1f, 0xd7, 0x4a, 0x42, 0xe1, 0xdd, 0x8b, 0x15, 0x3e, 0xd1, 0xa4,
0xa4, 0xd2, 0x01, 0x45, 0xe6, 0x23, 0x28, 0x0f, 0xd8, 0x24, 0x55, 0xc8, 0xbc, 0x62, 0x67, 0x32,
0x31, 0x14, 0x87, 0xe4, 0x32, 0xcc, 0x9d, 0xd8, 0x5e, 0x97, 0x89, 0x1c, 0x94, 0xa8, 0x9c, 0x3c,
0x9c, 0x7d, 0x60, 0x98, 0x47, 0x70, 0x69, 0x44, 0xff, 0x18, 0x05, 0x3f, 0xd2, 0x15, 0x14, 0x57,
0x3f, 0x4a, 0xd9, 0xb5, 0xae, 0x4e, 0xb3, 0xb4, 0x9e, 0x87, 0x5c, 0x24, 0x1c, 0xb2, 0x7e, 0x67,
0x40, 0x75, 0x38, 0xd5, 0x64, 0x57, 0x25, 0xc9, 0x10, 0x61, 0xb9, 0x3f, 0xc5, 0x29, 0x41, 0x82,
0x0a, 0x8c, 0x50, 0x61, 0xae, 0x41, 0xa1, 0x47, 0xba, 0x28, 0x18, 0x05, 0x6d, 0x8b, 0xd6, 0x1a,
0x64, 0x28, 0x6b, 0x93, 0x0a, 0xcc, 0xba, 0xea, 0x5c, 0xd3, 0x59, 0xd7, 0x21, 0x8b, 0x90, 0x71,
0x58, 0x5b, 0xb9, 0x5e, 0xa9, 0x87, 0x87, 0xf5, 0x4d, 0xd6, 0x76, 0x7d, 0x17, 0x5d, 0xa4, 0xb8,
0x64, 0xfd, 0xde, 0xc0, 0xfa, 0xc0, 0x6d, 0x91, 0x4f, 0x06, 0xfc, 0xb8, 0xf8, 0xb4, 0x8f, 0xec,
0xfe, 0x65, 0xfa, 0xee, 0xef, 0x0d, 0x66, 0xe2, 0x82, 0x12, 0xd0, 0xbd, 0xfb, 0x29, 0x94, 0xf4,
0xdc, 0x90, 0x1d, 0x28, 0x6a, 0xe7, 0x48, 0x6d, 0x78, 0x69, 0xb2, 0xcc, 0x52, 0x5d, 0xd4, 0xfa,
0x63, 0x06, 0x8a, 0xda, 0x22, 0x79, 0x0c, 0xd9, 0x57, 0xae, 0x2f, 0x43, 0x58, 0x59, 0x5d, 0x99,
0x4c, 0xe5, 0x53, 0xd7, 0x77, 0xa8, 0x90, 0x23, 0x4d, 0xad, 0xee, 0x66, 0xc5, 0xb6, 0xee, 0x4d,
0xa6, 0xe3, 0xdc, 0xe2, 0xbb, 0x33, 0x45, 0xdb, 0x90, 0x4d, 0x83, 0x40, 0x36, 0xb4, 0xf9, 0x91,
0x68, 0x1a, 0x05, 0x2a, 0xc6, 0xe4, 0x0e, 0xbc, 0xe3, 0xfa, 0x2f, 0x02, 0x1e, 0x34, 0x23, 0xe6,
0xb8, 0x78, 0xf8, 0x5e, 0x9c, 0x85, 0xac, 0x36, 0x27, 0x58, 0xc6, 0x2d, 0x91, 0x26, 0x54, 0x24,
0xf9, 0xa0, 0x7b, 0xf8, 0x0b, 0xd6, 0xe2, 0x71, 0x2d, 0x27, 0xfc, 0x59, 0x4e, 0xd9, 0xc2, 0xae,
0x2e, 0x40, 0x87, 0xe4, 0xdf, 0xaa, 0xda, 0xad, 0xbf, 0x18, 0x50, 0x1e, 0x50, 0x4f, 0x3e, 0x1d,
0x48, 0xd5, 0xed, 0x49, 0xb7, 0xa5, 0x25, 0xeb, 0x33, 0xc8, 0x39, 0x6e, 0x87, 0xc5, 0x5c, 0xa4,
0xaa, 0xb0, 0xbe, 0xfa, 0xdd, 0xf7, 0x1f, 0xcc, 0xfc, 0xf3, 0xfb, 0x0f, 0x56, 0xb4, 0xab, 0x26,
0x08, 0x99, 0xdf, 0x0a, 0x7c, 0x6e, 0xbb, 0x3e, 0x8b, 0xf0, 0x82, 0xfd, 0x58, 0x8a, 0xd4, 0x37,
0xc5, 0x0f, 0x55, 0x1a, 0x30, 0xe8, 0xbe, 0x7d, 0xcc, 0x44, 0x9e, 0x0a, 0x54, 0x8c, 0x2d, 0x0e,
0x65, 0xca, 0x78, 0x37, 0xf2, 0x29, 0xfb, 0x65, 0x17, 0x99, 0x7e, 0x90, 0x34, 0x12, 0xb1, 0xe9,
0x8b, 0x1a, 0x3a, 0x32, 0x52, 0x25, 0x40, 0x96, 0x61, 0x8e, 0x45, 0x51, 0x10, 0xa9, 0xe2, 0x21,
0x75, 0x79, 0xd5, 0xd7, 0xa3, 0xb0, 0x55, 0x3f, 0x10, 0x57, 0x3d, 0x95, 0x0c, 0x56, 0x15, 0x2a,
0x89, 0xd5, 0x38, 0x0c, 0xfc, 0x98, 0x59, 0x0b, 0x18, 0xba, 0xb0, 0xcb, 0x63, 0xb5, 0x0f, 0xeb,
0x5b, 0x03, 0x2a, 0x09, 0x45, 0xf2, 0x90, 0x2f, 0xa0, 0xd8, 0x6f, 0x0d, 0x49, 0x0f, 0x78, 0x98,
0x1a, 0x54, 0x5d, 0x5e, 0xeb, 0x2b, 0xaa, 0x25, 0xe8, 0xea, 0xcc, 0x67, 0x50, 0x1d, 0x66, 0x18,
0x93, 0xfd, 0x0f, 0x07, 0x1b, 0xc4, 0x70, 0xbf, 0xd2, 0x4e, 0xc3, 0xb7, 0xb3, 0x70, 0x85, 0x32,
0x81, 0x5d, 0x76, 0x8f, 0xed, 0x0e, 0xdb, 0x08, 0xfc, 0xb6, 0xdb, 0x49, 0xc2, 0x5c, 0x15, 0xcd,
0x30, 0xd1, 0x8c, 0x7d, 0x71, 0x19, 0xf2, 0x4d, 0xcf, 0xe6, 0xed, 0x20, 0x3a, 0x56, 0xca, 0x4b,
0xa8, 0x3c, 0xa1, 0xd1, 0xde, 0x2a, 0x59, 0x84, 0xa2, 0x52, 0xbc, 0x1f, 0x38, 0x49, 0x3a, 0x75,
0x12, 0xa9, 0xc1, 0xfc, 0x5e, 0xd0, 0x79, 0x86, 0xc9, 0x96, 0x15, 0x96, 0x4c, 0x89, 0x05, 0x25,
0xc5, 0x18, 0xf5, 0xaa, 0x6b, 0x8e, 0x0e, 0xd0, 0xc8, 0xfb, 0x50, 0x38, 0x60, 0x71, 0xec, 0x06,
0xfe, 0xee, 0x66, 0x2d, 0x27, 0xe4, 0xfb, 0x04, 0xd4, 0x7d, 0xc0, 0x83, 0x88, 0xed, 0x6e, 0xd6,
0xe6, 0xa5, 0x6e, 0x35, 0x25, 0xfb, 0x50, 0x39, 0x10, 0x38, 0xa7, 0x89, 0xe8, 0xc6, 0x65, 0x71,
0x2d, 0x2f, 0x52, 0x74, 0x63, 0x34, 0x45, 0x3a, 0x1e, 0xaa, 0x0b, 0xf6, 0x33, 0x3a, 0x24, 0x6c,
0xfd, 0xd6, 0x00, 0x73, 0x5c, 0x00, 0xd5, 0x69, 0xf8, 0x0c, 0x72, 0xf2, 0x7c, 0xcb, 0x20, 0xfe,
0x6f, 0x95, 0x21, 0x7f, 0xc9, 0x7b, 0x90, 0x93, 0xda, 0x55, 0x51, 0xab, 0x59, 0x92, 0xa5, 0x4c,
0x2f, 0x4b, 0xd6, 0xaf, 0x73, 0x50, 0x3a, 0xc0, 0x2d, 0x25, 0x89, 0xac, 0x03, 0xf4, 0xf3, 0xaf,
0x6a, 0x66, 0xf8, 0x54, 0x68, 0x1c, 0xc4, 0x84, 0xfc, 0xb6, 0x3a, 0x9f, 0xea, 0x8a, 0xec, 0xcd,
0xc9, 0xe7, 0x50, 0x4c, 0xc6, 0xcf, 0x43, 0x5e, 0xcb, 0x88, 0xe8, 0x3d, 0x48, 0x39, 0xe0, 0xfa,
0x4e, 0xea, 0x9a, 0xa8, 0x3a, 0xde, 0x1a, 0x85, 0xdc, 0x86, 0x4b, 0xb6, 0xe7, 0x05, 0xa7, 0xaa,
0x66, 0x45, 0xf5, 0x89, 0xec, 0xe7, 0xe9, 0xe8, 0x02, 0xf6, 0x62, 0x8d, 0xf8, 0x24, 0x8a, 0xec,
0x33, 0x0c, 0x44, 0x4e, 0xf0, 0x8f, 0x5b, 0xc2, 0xb6, 0xb8, 0xed, 0xfa, 0xb6, 0x57, 0x03, 0xc1,
0x23, 0x27, 0x78, 0xdc, 0xb6, 0x5e, 0x87, 0x41, 0xc4, 0x59, 0xf4, 0x84, 0xf3, 0xa8, 0x56, 0x14,
0xe1, 0x1d, 0xa0, 0x91, 0x26, 0x94, 0x36, 0xec, 0xd6, 0x11, 0xdb, 0x3d, 0x46, 0x62, 0x02, 0xdd,
0xd2, 0x9a, 0xa5, 0x60, 0x7f, 0x1e, 0xea, 0x98, 0x4d, 0xd7, 0x40, 0x5a, 0x50, 0x49, 0x5c, 0x97,
0x2d, 0xa0, 0x56, 0x16, 0x3a, 0x1f, 0x4d, 0x1b, 0x4a, 0x29, 0x2d, 0x4d, 0x0c, 0xa9, 0xc4, 0x44,
0x6e, 0x61, 0xb5, 0xdb, 0x9c, 0xd5, 0x2a, 0xc2, 0xe7, 0xde, 0x7c, 0x4c, 0x25, 0x2c, 0xbc, 0x45,
0x25, 0x98, 0x8f, 0xa1, 0x3a, 0x9c, 0xdc, 0x69, 0x90, 0x97, 0xf9, 0x63, 0x78, 0x67, 0x8c, 0x47,
0x6f, 0xd5, 0xdd, 0xfe, 0x6c, 0xc0, 0xa5, 0x91, 0x34, 0xe0, 0x0d, 0x23, 0xba, 0x8a, 0x54, 0x29,
0xc6, 0x64, 0x1f, 0xe6, 0x30, 0xcd, 0xb1, 0xc2, 0x1a, 0x6b, 0xd3, 0xe4, 0xb5, 0x2e, 0x24, 0x65,
0xfc, 0xa5, 0x16, 0xf3, 0x01, 0x40, 0x9f, 0x38, 0x15, 0xfe, 0xfc, 0x02, 0xca, 0x2a, 0xc9, 0xaa,
0x83, 0x54, 0x25, 0x6c, 0x51, 0xc2, 0x08, 0x4b, 0xfa, 0x97, 0x5f, 0x66, 0xca, 0xcb, 0xcf, 0xfa,
0x0a, 0x16, 0x28, 0xb3, 0x9d, 0x6d, 0xd7, 0x63, 0xe7, 0xf7, 0x78, 0x2c, 0x7e, 0xd7, 0x63, 0x4d,
0x84, 0x3e, 0x49, 0xf1, 0xab, 0x39, 0x79, 0x08, 0x73, 0xd4, 0xf6, 0x3b, 0x4c, 0x99, 0xfe, 0x30,
0xc5, 0xb4, 0x30, 0x82, 0xbc, 0x54, 0x8a, 0x58, 0x8f, 0xa0, 0xd0, 0xa3, 0x61, 0x33, 0x7b, 0xde,
0x6e, 0xc7, 0x4c, 0x36, 0xc6, 0x0c, 0x55, 0x33, 0xa4, 0xef, 0x31, 0xbf, 0xa3, 0x4c, 0x67, 0xa8,
0x9a, 0x59, 0x4b, 0xf8, 0x5e, 0x48, 0x76, 0xae, 0x42, 0x43, 0x20, 0xbb, 0x89, 0xf8, 0xd0, 0x10,
0xf5, 0x2a, 0xc6, 0x96, 0x83, 0x97, 0xb6, 0xed, 0x6c, 0xba, 0xd1, 0xf9, 0x0e, 0xd6, 0x60, 0x7e,
0xd3, 0x8d, 0x34, 0xff, 0x92, 0x29, 0x59, 0xc2, 0xeb, 0xbc, 0xe5, 0x75, 0x1d, 0xf4, 0x96, 0xb3,
0xc8, 0x57, 0x5d, 0x75, 0x88, 0x6a, 0x7d, 0x22, 0xe3, 0x28, 0xac, 0xa8, 0xcd, 0xdc, 0x86, 0x79,
0xe6, 0xf3, 0x08, 0xcb, 0x48, 0xde, 0xf9, 0xa4, 0x2e, 0x5f, 0xe0, 0x75, 0xf1, 0x02, 0x17, 0xd8,
0x82, 0x26, 0x2c, 0xd6, 0x1a, 0x2c, 0x20, 0x21, 0x3d, 0x11, 0x04, 0xb2, 0xda, 0x26, 0xc5, 0xd8,
0x7a, 0x08, 0xd5, 0xbe, 0xa0, 0x32, 0xbd, 0x04, 0x59, 0x04, 0xbf, 0xaa, 0xaf, 0x8f, 0xb3, 0x2b,
0xd6, 0xad, 0xeb, 0xb0, 0x90, 0x14, 0xff, 0xb9, 0x46, 0x2d, 0x02, 0xd5, 0x3e, 0x93, 0xc2, 0x3d,
0x65, 0x28, 0x36, 0x5d, 0x3f, 0x81, 0x05, 0xd6, 0x1b, 0x03, 0x4a, 0xcd, 0xc0, 0xef, 0xdf, 0x72,
0x4d, 0x58, 0x48, 0x4a, 0xf7, 0x49, 0x73, 0x77, 0xc3, 0x0e, 0x93, 0x18, 0x2c, 0x8e, 0x9e, 0x0f,
0xf5, 0x0d, 0xa3, 0x2e, 0x19, 0xd7, 0xb3, 0x78, 0x21, 0xd2, 0x61, 0x71, 0xf2, 0x29, 0xcc, 0xef,
0xed, 0xad, 0x0b, 0x4d, 0xb3, 0x53, 0x69, 0x4a, 0xc4, 0xc8, 0x63, 0x98, 0x7f, 0x29, 0x3e, 0xad,
0xc4, 0xea, 0x8a, 0x1a, 0x73, 0x56, 0x65, 0x84, 0x24, 0x1b, 0x65, 0xad, 0x20, 0x72, 0x68, 0x22,
0x64, 0xfd, 0xdb, 0x80, 0xe2, 0x4b, 0xbb, 0x0f, 0x39, 0xfb, 0x18, 0xf7, 0x2d, 0x6e, 0x72, 0x85,
0x71, 0x2f, 0xc3, 0x9c, 0xc7, 0x4e, 0x98, 0xa7, 0xce, 0xb8, 0x9c, 0x20, 0x35, 0x3e, 0x0a, 0x22,
0x59, 0xd6, 0x25, 0x2a, 0x27, 0x58, 0x10, 0x0e, 0xe3, 0xb6, 0xeb, 0xd5, 0xb2, 0x8b, 0x19, 0xbc,
0xf5, 0xe5, 0x0c, 0x33, 0xd7, 0x8d, 0x3c, 0xf5, 0xf0, 0xc0, 0x21, 0xb1, 0x20, 0xeb, 0xfa, 0xed,
0x40, 0xdc, 0x7f, 0xaa, 0x2d, 0xca, 0x16, 0xbd, 0xeb, 0xb7, 0x03, 0x2a, 0xd6, 0xc8, 0x35, 0xc8,
0x45, 0x58, 0x7f, 0x71, 0x6d, 0x5e, 0x04, 0xa5, 0x80, 0x5c, 0xb2, 0x4a, 0xd5, 0x82, 0x55, 0x81,
0x92, 0xf4, 0x5b, 0x25, 0xff, 0x4f, 0xb3, 0xf0, 0xce, 0x33, 0x76, 0xba, 0x91, 0xf8, 0x95, 0x04,
0x64, 0x11, 0x8a, 0x3d, 0xda, 0xee, 0xa6, 0x3a, 0x42, 0x3a, 0x09, 0x8d, 0xed, 0x07, 0x5d, 0x9f,
0x27, 0x39, 0x14, 0xc6, 0x04, 0x85, 0xaa, 0x05, 0x72, 0x03, 0xe6, 0x9f, 0x31, 0x7e, 0x1a, 0x44,
0xaf, 0x84, 0xd7, 0x95, 0xd5, 0x22, 0xf2, 0x3c, 0x63, 0x1c, 0x11, 0x22, 0x4d, 0xd6, 0x10, 0x76,
0x86, 0x09, 0xec, 0xcc, 0x8e, 0x83, 0x9d, 0xc9, 0x2a, 0x59, 0x83, 0x62, 0x2b, 0xf0, 0x63, 0x1e,
0xd9, 0x2e, 0x1a, 0x9e, 0x13, 0xcc, 0xef, 0x22, 0xb3, 0x4c, 0xec, 0x46, 0x7f, 0x91, 0xea, 0x9c,
0x64, 0x05, 0x80, 0xbd, 0xe6, 0x91, 0xbd, 0x13, 0xc4, 0xbd, 0x27, 0x1a, 0xa0, 0x1c, 0x12, 0x76,
0x9b, 0x54, 0x5b, 0xc5, 0x0e, 0x79, 0x14, 0xc4, 0x5c, 0xbc, 0x53, 0x24, 0xbc, 0xec, 0xcd, 0xad,
0xf7, 0xe0, 0xf2, 0x60, 0xb4, 0x54, 0x18, 0x1f, 0xc1, 0xff, 0x51, 0xe6, 0x31, 0x3b, 0x66, 0xd3,
0x47, 0xd2, 0x32, 0xa1, 0x36, 0x2a, 0xac, 0x14, 0xff, 0x27, 0x03, 0xc5, 0xad, 0xd7, 0xac, 0xb5,
0xcf, 0xe2, 0xd8, 0xee, 0x08, 0x60, 0xdc, 0x8c, 0x82, 0x16, 0x8b, 0xe3, 0x9e, 0xae, 0x3e, 0x81,
0xfc, 0x10, 0xb2, 0xbb, 0xbe, 0xcb, 0xd5, 0xdd, 0xb9, 0x94, 0xfa, 0x2e, 0x71, 0xb9, 0xd2, 0xb9,
0x33, 0x43, 0x85, 0x14, 0x79, 0x08, 0x59, 0xec, 0x3c, 0x93, 0x74, 0x7f, 0x47, 0x93, 0x45, 0x19,
0xb2, 0x2e, 0xbe, 0x1f, 0xba, 0x5f, 0x32, 0x95, 0xc1, 0xe5, 0xf4, 0x6b, 0xcb, 0xfd, 0x92, 0xf5,
0x35, 0x28, 0x49, 0xb2, 0x85, 0xb0, 0xde, 0x8e, 0x38, 0x73, 0x54, 0x66, 0x6f, 0xa6, 0x81, 0x25,
0xc9, 0xd9, 0xd7, 0x92, 0xc8, 0x62, 0x10, 0xb6, 0x5e, 0xbb, 0x5c, 0x55, 0x4a, 0x5a, 0x10, 0x90,
0x4d, 0x73, 0x04, 0xa7, 0x28, 0xbd, 0x19, 0xf8, 0x32, 0xf3, 0xe9, 0xd2, 0xc8, 0xa6, 0x49, 0xe3,
0x14, 0xc3, 0x70, 0xe0, 0x76, 0x10, 0x83, 0xe6, 0x2f, 0x0c, 0x83, 0x64, 0xd4, 0xc2, 0x20, 0x09,
0xeb, 0xf3, 0x30, 0x27, 0x20, 0x92, 0xf5, 0x77, 0x03, 0x8a, 0x5a, 0x9e, 0x26, 0xa8, 0xc9, 0xf7,
0x21, 0xbb, 0xcf, 0xc4, 0x37, 0x15, 0x34, 0x9e, 0x17, 0x15, 0xc9, 0xb8, 0x4d, 0x05, 0x15, 0x9b,
0xca, 0xb6, 0x23, 0x1b, 0x66, 0x99, 0xe2, 0x10, 0x29, 0x2f, 0xf8, 0x99, 0x48, 0x59, 0x9e, 0xe2,
0x90, 0xdc, 0x86, 0xfc, 0x01, 0x6b, 0x75, 0x23, 0x97, 0x9f, 0x89, 0x24, 0x54, 0x56, 0xab, 0xa2,
0xd5, 0x28, 0x9a, 0x28, 0xdc, 0x1e, 0x07, 0xb9, 0x05, 0x85, 0x98, 0xb5, 0x22, 0xc6, 0x99, 0x7f,
0xa2, 0xaa, 0xaa, 0xac, 0xd8, 0x23, 0xc6, 0xb7, 0xfc, 0x13, 0xda, 0x5f, 0xb7, 0x9e, 0xe2, 0x49,
0xee, 0x7b, 0x43, 0x20, 0xbb, 0x81, 0x6f, 0x47, 0x74, 0xa3, 0x4c, 0xc5, 0x18, 0x9f, 0xef, 0x5b,
0x17, 0x3d, 0xdf, 0xb7, 0x92, 0xe7, 0xfb, 0xe0, 0x09, 0xc0, 0x6b, 0x4c, 0xcb, 0x88, 0xf5, 0x04,
0x0a, 0xbd, 0x53, 0x4a, 0x2a, 0x30, 0xbb, 0xed, 0x28, 0x4b, 0xb3, 0xdb, 0x0e, 0xfa, 0xbd, 0xf5,
0x7c, 0x5b, 0x58, 0xc9, 0x53, 0x1c, 0xf6, 0xd0, 0x46, 0x46, 0x43, 0x1b, 0x6b, 0x50, 0x1e, 0x38,
0xaa, 0xc8, 0x44, 0x83, 0xd3, 0x38, 0xd9, 0x32, 0x8e, 0xa5, 0x1b, 0x5e, 0x2c, 0x74, 0x09, 0x37,
0xbc, 0xd8, 0xba, 0x0e, 0xe5, 0x81, 0xe4, 0x22, 0x93, 0x78, 0x09, 0x2b, 0x50, 0x8a, 0xe3, 0x15,
0x06, 0x0b, 0x43, 0x1f, 0xc7, 0xc8, 0x0d, 0xc8, 0xc9, 0x8f, 0x30, 0xd5, 0x19, 0xf3, 0xca, 0xd7,
0xdf, 0x2c, 0xbe, 0x3b, 0xc4, 0x20, 0x17, 0x91, 0x6d, 0xbd, 0xeb, 0x3b, 0x1e, 0xab, 0x1a, 0x63,
0xd9, 0xe4, 0xa2, 0x99, 0xfd, 0xcd, 0x1f, 0xae, 0xce, 0xac, 0xd8, 0x70, 0x69, 0xe4, 0xc3, 0x0e,
0xb9, 0x0e, 0xd9, 0x03, 0xe6, 0xb5, 0x13, 0x33, 0x23, 0x0c, 0xb8, 0x48, 0xae, 0x41, 0x86, 0xda,
0xa7, 0x55, 0xc3, 0xac, 0x7d, 0xfd, 0xcd, 0xe2, 0xe5, 0xd1, 0xaf, 0x43, 0xf6, 0xa9, 0x34, 0xb1,
0xfa, 0x57, 0x80, 0xc2, 0xde, 0xde, 0xfa, 0x7a, 0xe4, 0x3a, 0x1d, 0x46, 0x7e, 0x65, 0x00, 0x19,
0x7d, 0x33, 0x93, 0x7b, 0xe9, 0x0d, 0x61, 0xfc, 0x37, 0x0a, 0xf3, 0xfe, 0x94, 0x52, 0x0a, 0xb2,
0x7c, 0x0e, 0x73, 0x02, 0x67, 0x93, 0x8f, 0x26, 0x7c, 0x6e, 0x99, 0xcb, 0x17, 0x33, 0x2a, 0xdd,
0x2d, 0xc8, 0x27, 0x58, 0x95, 0xac, 0xa4, 0x6e, 0x6f, 0x00, 0x8a, 0x9b, 0xb7, 0x26, 0xe2, 0x55,
0x46, 0x7e, 0x0e, 0xf3, 0x0a, 0x82, 0x92, 0x9b, 0x17, 0xc8, 0xf5, 0xc1, 0xb0, 0xb9, 0x32, 0x09,
0x6b, 0xdf, 0x8d, 0x04, 0x6a, 0xa6, 0xba, 0x31, 0x04, 0x64, 0x53, 0xdd, 0x18, 0xc1, 0xae, 0xad,
0xfe, 0x03, 0x35, 0xd5, 0xc8, 0x10, 0x70, 0x4d, 0x35, 0x32, 0x8c, 0x5f, 0xc9, 0x4b, 0xc8, 0x22,
0x7e, 0x25, 0x69, 0xbd, 0x5a, 0x03, 0xb8, 0x66, 0xda, 0x99, 0x18, 0x00, 0xbe, 0x3f, 0xc3, 0x3b,
0x4d, 0x7c, 0x8b, 0x48, 0xbf, 0xcd, 0xb4, 0x6f, 0x97, 0xe6, 0xcd, 0x09, 0x38, 0xfb, 0xea, 0xd5,
0x3b, 0x7e, 0x79, 0x82, 0x0f, 0x88, 0x17, 0xab, 0x1f, 0xfa, 0x54, 0x19, 0x40, 0x49, 0x87, 0x2a,
0xa4, 0x9e, 0x22, 0x3a, 0x06, 0x01, 0x9a, 0x8d, 0x89, 0xf9, 0x95, 0xc1, 0xaf, 0xf0, 0x11, 0x37,
0x08, 0x63, 0xc8, 0x6a, 0x6a, 0x38, 0xc6, 0x02, 0x26, 0xf3, 0xee, 0x54, 0x32, 0xca, 0xb8, 0x2d,
0x61, 0x92, 0x82, 0x42, 0x24, 0xfd, 0xd6, 0xef, 0xc1, 0x29, 0x73, 0x42, 0xbe, 0x65, 0xe3, 0x8e,
0x81, 0xe7, 0x0c, 0xa1, 0x73, 0xaa, 0x6e, 0xed, 0x4d, 0x91, 0x7a, 0xce, 0x74, 0x0c, 0xbe, 0x5e,
0xfa, 0xee, 0xcd, 0x55, 0xe3, 0x1f, 0x6f, 0xae, 0x1a, 0xff, 0x7a, 0x73, 0xd5, 0x38, 0xcc, 0x89,
0x7f, 0x64, 0xef, 0xfe, 0x37, 0x00, 0x00, 0xff, 0xff, 0x20, 0x47, 0x7d, 0x27, 0x1a, 0x1f, 0x00,
0x00,
}
// Reference imports to suppress errors if they are not otherwise used.
@ -4022,6 +4049,20 @@ func (m *ResolveImageConfigRequest) MarshalToSizedBuffer(dAtA []byte) (int, erro
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if len(m.SourcePolicies) > 0 {
for iNdEx := len(m.SourcePolicies) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.SourcePolicies[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGateway(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x42
}
}
if len(m.StoreID) > 0 {
i -= len(m.StoreID)
copy(dAtA[i:], m.StoreID)
@ -4101,6 +4142,13 @@ func (m *ResolveImageConfigResponse) MarshalToSizedBuffer(dAtA []byte) (int, err
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if len(m.Ref) > 0 {
i -= len(m.Ref)
copy(dAtA[i:], m.Ref)
i = encodeVarintGateway(dAtA, i, uint64(len(m.Ref)))
i--
dAtA[i] = 0x1a
}
if len(m.Config) > 0 {
i -= len(m.Config)
copy(dAtA[i:], m.Config)
@ -5348,6 +5396,20 @@ func (m *InitMessage) MarshalToSizedBuffer(dAtA []byte) (int, error) {
i -= len(m.XXX_unrecognized)
copy(dAtA[i:], m.XXX_unrecognized)
}
if len(m.Secretenv) > 0 {
for iNdEx := len(m.Secretenv) - 1; iNdEx >= 0; iNdEx-- {
{
size, err := m.Secretenv[iNdEx].MarshalToSizedBuffer(dAtA[:i])
if err != nil {
return 0, err
}
i -= size
i = encodeVarintGateway(dAtA, i, uint64(size))
}
i--
dAtA[i] = 0x32
}
}
if m.Security != 0 {
i = encodeVarintGateway(dAtA, i, uint64(m.Security))
i--
@ -5973,6 +6035,12 @@ func (m *ResolveImageConfigRequest) Size() (n int) {
if l > 0 {
n += 1 + l + sovGateway(uint64(l))
}
if len(m.SourcePolicies) > 0 {
for _, e := range m.SourcePolicies {
l = e.Size()
n += 1 + l + sovGateway(uint64(l))
}
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
@ -5993,6 +6061,10 @@ func (m *ResolveImageConfigResponse) Size() (n int) {
if l > 0 {
n += 1 + l + sovGateway(uint64(l))
}
l = len(m.Ref)
if l > 0 {
n += 1 + l + sovGateway(uint64(l))
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
@ -6586,6 +6658,12 @@ func (m *InitMessage) Size() (n int) {
if m.Security != 0 {
n += 1 + sovGateway(uint64(m.Security))
}
if len(m.Secretenv) > 0 {
for _, e := range m.Secretenv {
l = e.Size()
n += 1 + l + sovGateway(uint64(l))
}
}
if m.XXX_unrecognized != nil {
n += len(m.XXX_unrecognized)
}
@ -8819,6 +8897,40 @@ func (m *ResolveImageConfigRequest) Unmarshal(dAtA []byte) error {
}
m.StoreID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
case 8:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field SourcePolicies", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGateway
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGateway
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGateway
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.SourcePolicies = append(m.SourcePolicies, &pb1.Policy{})
if err := m.SourcePolicies[len(m.SourcePolicies)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGateway(dAtA[iNdEx:])
@ -8936,6 +9048,38 @@ func (m *ResolveImageConfigResponse) Unmarshal(dAtA []byte) error {
m.Config = []byte{}
}
iNdEx = postIndex
case 3:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Ref", wireType)
}
var stringLen uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGateway
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLen |= uint64(b&0x7F) << shift
if b < 0x80 {
break
}
}
intStringLen := int(stringLen)
if intStringLen < 0 {
return ErrInvalidLengthGateway
}
postIndex := iNdEx + intStringLen
if postIndex < 0 {
return ErrInvalidLengthGateway
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Ref = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGateway(dAtA[iNdEx:])
@ -12261,6 +12405,40 @@ func (m *InitMessage) Unmarshal(dAtA []byte) error {
break
}
}
case 6:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Secretenv", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowGateway
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= int(b&0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthGateway
}
postIndex := iNdEx + msglen
if postIndex < 0 {
return ErrInvalidLengthGateway
}
if postIndex > l {
return io.ErrUnexpectedEOF
}
m.Secretenv = append(m.Secretenv, &pb.SecretEnv{})
if err := m.Secretenv[len(m.Secretenv)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil {
return err
}
iNdEx = postIndex
default:
iNdEx = preIndex
skippy, err := skipGateway(dAtA[iNdEx:])

View File

@ -11,6 +11,7 @@ import "github.com/tonistiigi/fsutil/types/stat.proto";
import "github.com/moby/buildkit/sourcepolicy/pb/policy.proto";
option (gogoproto.sizer_all) = true;
option (gogoproto.marshaler_all) = true;
option (gogoproto.unmarshaler_all) = true;
@ -38,7 +39,7 @@ service LLBBridge {
rpc ExecProcess(stream ExecMessage) returns (stream ExecMessage);
// apicaps:CapGatewayWarnings
rpc Warn(WarnRequest) returns (WarnResponse);
rpc Warn(WarnRequest) returns (WarnResponse);
}
message Result {
@ -124,11 +125,13 @@ message ResolveImageConfigRequest {
int32 ResolverType = 5;
string SessionID = 6;
string StoreID = 7;
repeated moby.buildkit.v1.sourcepolicy.Policy SourcePolicies = 8;
}
message ResolveImageConfigResponse {
string Digest = 1 [(gogoproto.customtype) = "github.com/opencontainers/go-digest.Digest", (gogoproto.nullable) = false];
bytes Config = 2;
string Ref = 3;
}
message SolveRequest {
@ -138,7 +141,7 @@ message SolveRequest {
// 4 was removed in BuildKit v0.11.0.
bool allowResultReturn = 5;
bool allowResultArrayRef = 6;
// apicaps.CapSolveInlineReturn deprecated
bool Final = 10;
bytes ExporterAttr = 11;
@ -165,7 +168,7 @@ message SolveResponse {
string ref = 1; // can be used by readfile request
// deprecated
/* bytes ExporterAttr = 2;*/
// these fields are returned when allowMapReturn was set
Result result = 3;
}
@ -256,7 +259,7 @@ message ExecMessage {
// InitMessage sent from client to server will start a new process in a
// container
InitMessage Init = 2;
// FdMessage used from client to server for input (stdin) and
// FdMessage used from client to server for input (stdin) and
// from server to client for output (stdout, stderr)
FdMessage File = 3;
// ResizeMessage used from client to server for terminal resize events
@ -281,6 +284,7 @@ message InitMessage{
repeated uint32 Fds = 3;
bool Tty = 4;
pb.SecurityMode Security = 5;
repeated pb.SecretEnv secretenv = 6;
}
message ExitMessage {

View File

@ -4,8 +4,11 @@ import (
"context"
"fmt"
io "io"
"net/url"
"os"
"strconv"
"strings"
"unicode"
"github.com/moby/buildkit/session"
"github.com/pkg/errors"
@ -82,6 +85,7 @@ func (sp *fsSyncProvider) handle(method string, stream grpc.ServerStream) (retEr
}
opts, _ := metadata.FromIncomingContext(stream.Context()) // if no metadata continue with empty object
opts = decodeOpts(opts)
dirName := ""
name, ok := opts[keyDirName]
@ -209,6 +213,8 @@ func FSSync(ctx context.Context, c session.Caller, opt FSSendRequestOpt) error {
var stream grpc.ClientStream
opts = encodeOpts(opts)
ctx = metadata.NewOutgoingContext(ctx, opts)
switch pr.name {
@ -337,3 +343,60 @@ func (e InvalidSessionError) Error() string {
func (e InvalidSessionError) Unwrap() error {
return e.err
}
func encodeOpts(opts map[string][]string) map[string][]string {
md := make(map[string][]string, len(opts))
for k, v := range opts {
out, encoded := encodeStringForHeader(v)
md[k] = out
if encoded {
md[k+"-encoded"] = []string{"1"}
}
}
return md
}
func decodeOpts(opts map[string][]string) map[string][]string {
md := make(map[string][]string, len(opts))
for k, v := range opts {
out := make([]string, len(v))
var isDecoded bool
if v, ok := opts[k+"-encoded"]; ok && len(v) > 0 {
if b, _ := strconv.ParseBool(v[0]); b {
isDecoded = true
}
}
if isDecoded {
for i, s := range v {
out[i], _ = url.QueryUnescape(s)
}
} else {
copy(out, v)
}
md[k] = out
}
return md
}
// encodeStringForHeader encodes a string value so it can be used in grpc header. This encoding
// is backwards compatible and avoids encoding ASCII characters.
func encodeStringForHeader(inputs []string) ([]string, bool) {
var encode bool
for _, input := range inputs {
for _, runeVal := range input {
// Only encode non-ASCII characters, and characters that have special
// meaning during decoding.
if runeVal > unicode.MaxASCII {
encode = true
break
}
}
}
if !encode {
return inputs, false
}
for i, input := range inputs {
inputs[i] = url.QueryEscape(input)
}
return inputs, true
}

10
vendor/github.com/moby/buildkit/source/types/types.go generated vendored Normal file
View File

@ -0,0 +1,10 @@
package srctypes
const (
DockerImageScheme = "docker-image"
GitScheme = "git"
LocalScheme = "local"
HTTPScheme = "http"
HTTPSScheme = "https"
OCIScheme = "oci-layout"
)

161
vendor/github.com/moby/buildkit/sourcepolicy/engine.go generated vendored Normal file
View File

@ -0,0 +1,161 @@
package sourcepolicy
import (
"context"
"github.com/moby/buildkit/solver/pb"
spb "github.com/moby/buildkit/sourcepolicy/pb"
"github.com/moby/buildkit/util/bklog"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
)
var (
// ErrSourceDenied is returned by the policy engine when a source is denied by the policy.
ErrSourceDenied = errors.New("source denied by policy")
// ErrTooManyOps is returned by the policy engine when there are too many converts for a single source op.
ErrTooManyOps = errors.New("too many operations")
)
// Engine is the source policy engine.
// It is responsible for evaluating a source policy against a source operation.
// Create one with `NewEngine`
//
// Rule matching is delegated to the `Matcher` interface.
// Mutations are delegated to the `Mutater` interface.
type Engine struct {
pol []*spb.Policy
sources map[string]*selectorCache
}
// NewEngine creates a new source policy engine.
func NewEngine(pol []*spb.Policy) *Engine {
return &Engine{
pol: pol,
}
}
// TODO: The key here can't be used to cache attr constraint regexes.
func (e *Engine) selectorCache(src *spb.Selector) *selectorCache {
if e.sources == nil {
e.sources = map[string]*selectorCache{}
}
key := src.MatchType.String() + " " + src.Identifier
if s, ok := e.sources[key]; ok {
return s
}
s := &selectorCache{Selector: src}
e.sources[key] = s
return s
}
// Evaluate evaluates a source operation against the policy.
//
// Policies are re-evaluated for each convert rule.
// Evaluate will error if the there are too many converts for a single source op to prevent infinite loops.
// This function may error out even if the op was mutated, in which case `true` will be returned along with the error.
//
// An error is returned when the source is denied by the policy.
func (e *Engine) Evaluate(ctx context.Context, op *pb.Op) (bool, error) {
if len(e.pol) == 0 {
return false, nil
}
var mutated bool
const maxIterr = 20
for i := 0; ; i++ {
if i > maxIterr {
return mutated, errors.Wrapf(ErrTooManyOps, "too many mutations on a single source")
}
srcOp := op.GetSource()
if srcOp == nil {
return false, nil
}
if i == 0 {
ctx = bklog.WithLogger(ctx, bklog.G(ctx).WithField("orig", *srcOp).WithField("updated", op.GetSource()))
}
mut, err := e.evaluatePolicies(ctx, srcOp)
if mut {
mutated = true
}
if err != nil {
return mutated, err
}
if !mut {
break
}
}
return mutated, nil
}
func (e *Engine) evaluatePolicies(ctx context.Context, srcOp *pb.SourceOp) (bool, error) {
for _, pol := range e.pol {
mut, err := e.evaluatePolicy(ctx, pol, srcOp)
if mut || err != nil {
return mut, err
}
}
return false, nil
}
// evaluatePolicy evaluates a single policy against a source operation.
// If the source is mutated the policy is short-circuited and `true` is returned.
// If the source is denied, an error will be returned.
//
// For Allow/Deny rules, the last matching rule wins.
// E.g. `ALLOW foo; DENY foo` will deny `foo`, `DENY foo; ALLOW foo` will allow `foo`.
func (e *Engine) evaluatePolicy(ctx context.Context, pol *spb.Policy, srcOp *pb.SourceOp) (retMut bool, retErr error) {
ident := srcOp.GetIdentifier()
ctx = bklog.WithLogger(ctx, bklog.G(ctx).WithField("ref", ident))
defer func() {
if retMut || retErr != nil {
bklog.G(ctx).WithFields(
logrus.Fields{
"mutated": retMut,
"updated": srcOp.GetIdentifier(),
logrus.ErrorKey: retErr,
}).Debug("Evaluated source policy")
}
}()
var deny bool
for _, rule := range pol.Rules {
selector := e.selectorCache(rule.Selector)
matched, err := match(ctx, selector, ident, srcOp.Attrs)
if err != nil {
return false, errors.Wrap(err, "error matching source policy")
}
if !matched {
continue
}
switch rule.Action {
case spb.PolicyAction_ALLOW:
deny = false
case spb.PolicyAction_DENY:
deny = true
case spb.PolicyAction_CONVERT:
mut, err := mutate(ctx, srcOp, rule, selector, ident)
if err != nil || mut {
return mut, errors.Wrap(err, "error mutating source policy")
}
default:
return false, errors.Errorf("source policy: rule %s %s: unknown type %q", rule.Action, rule.Selector.Identifier, ident)
}
}
if deny {
return false, errors.Wrapf(ErrSourceDenied, "source %q denied by policy", ident)
}
return false, nil
}

View File

@ -0,0 +1,92 @@
package sourcepolicy
import (
"regexp"
spb "github.com/moby/buildkit/sourcepolicy/pb"
"github.com/moby/buildkit/util/wildcard"
"github.com/pkg/errors"
)
// Source wraps a a protobuf source in order to store cached state such as the compiled regexes.
type selectorCache struct {
*spb.Selector
re *regexp.Regexp
w *wildcardCache
}
// Format formats the provided ref according to the match/type of the source.
//
// For example, if the source is a wildcard, the ref will be formatted with the wildcard in the source replacing the parameters in the destination.
//
// matcher: wildcard source: "docker.io/library/golang:*" match: "docker.io/library/golang:1.19" format: "docker.io/library/golang:${1}-alpine" result: "docker.io/library/golang:1.19-alpine"
func (s *selectorCache) Format(match, format string) (string, error) {
switch s.MatchType {
case spb.MatchType_EXACT:
return s.Identifier, nil
case spb.MatchType_REGEX:
re, err := s.regex()
if err != nil {
return "", err
}
return re.ReplaceAllString(match, format), nil
case spb.MatchType_WILDCARD:
w, err := s.wildcard()
if err != nil {
return "", err
}
m := w.Match(match)
if m == nil {
return match, nil
}
return m.Format(format)
}
return "", errors.Errorf("unknown match type: %s", s.MatchType)
}
// wildcardCache wraps a wildcard.Wildcard to cache returned matches by ref.
// This way a match only needs to be computed once per ref.
type wildcardCache struct {
w *wildcard.Wildcard
m map[string]*wildcard.Match
}
func (w *wildcardCache) Match(ref string) *wildcard.Match {
if w.m == nil {
w.m = make(map[string]*wildcard.Match)
}
if m, ok := w.m[ref]; ok {
return m
}
m := w.w.Match(ref)
w.m[ref] = m
return m
}
func (s *selectorCache) wildcard() (*wildcardCache, error) {
if s.w != nil {
return s.w, nil
}
w, err := wildcard.New(s.Identifier)
if err != nil {
return nil, err
}
s.w = &wildcardCache{w: w}
return s.w, nil
}
func (s *selectorCache) regex() (*regexp.Regexp, error) {
if s.re != nil {
return s.re, nil
}
re, err := regexp.Compile(s.Identifier)
if err != nil {
return nil, err
}
s.re = re
return re, nil
}

View File

@ -0,0 +1,58 @@
package sourcepolicy
import (
"context"
"regexp"
spb "github.com/moby/buildkit/sourcepolicy/pb"
"github.com/pkg/errors"
)
func match(ctx context.Context, src *selectorCache, ref string, attrs map[string]string) (bool, error) {
for _, c := range src.Constraints {
switch c.Condition {
case spb.AttrMatch_EQUAL:
if attrs[c.Key] != c.Value {
return false, nil
}
case spb.AttrMatch_NOTEQUAL:
if attrs[c.Key] == c.Value {
return false, nil
}
case spb.AttrMatch_MATCHES:
// TODO: Cache the compiled regex
matches, err := regexp.MatchString(c.Value, attrs[c.Key])
if err != nil {
return false, errors.Errorf("invalid regex %q: %v", c.Value, err)
}
if !matches {
return false, nil
}
default:
return false, errors.Errorf("unknown attr condition: %s", c.Condition)
}
}
if src.Identifier == ref {
return true, nil
}
switch src.MatchType {
case spb.MatchType_EXACT:
return false, nil
case spb.MatchType_REGEX:
re, err := src.regex()
if err != nil {
return false, err
}
return re.MatchString(ref), nil
case spb.MatchType_WILDCARD:
w, err := src.wildcard()
if err != nil {
return false, err
}
return w.Match(ref) != nil, nil
default:
return false, errors.Errorf("unknown match type: %s", src.MatchType)
}
}

50
vendor/github.com/moby/buildkit/sourcepolicy/mutate.go generated vendored Normal file
View File

@ -0,0 +1,50 @@
package sourcepolicy
import (
"context"
"github.com/moby/buildkit/solver/pb"
spb "github.com/moby/buildkit/sourcepolicy/pb"
"github.com/moby/buildkit/util/bklog"
"github.com/pkg/errors"
)
// mutate is a MutateFn which converts the source operation to the identifier and attributes provided by the policy.
// If there is no change, then the return value should be false and is not considered an error.
func mutate(ctx context.Context, op *pb.SourceOp, rule *spb.Rule, selector *selectorCache, ref string) (bool, error) {
if rule.Updates == nil {
return false, errors.Errorf("missing destination for convert rule")
}
dest := rule.Updates.Identifier
if dest == "" {
dest = rule.Selector.Identifier
}
dest, err := selector.Format(ref, dest)
if err != nil {
return false, errors.Wrap(err, "error formatting destination")
}
bklog.G(ctx).Debugf("sourcepolicy: converting %s to %s, pattern: %s", ref, dest, rule.Updates.Identifier)
var mutated bool
if op.Identifier != dest && dest != "" {
mutated = true
op.Identifier = dest
}
if rule.Updates.Attrs != nil {
if op.Attrs == nil {
op.Attrs = make(map[string]string, len(rule.Updates.Attrs))
}
for k, v := range rule.Updates.Attrs {
if op.Attrs[k] != v {
bklog.G(ctx).Debugf("setting attr %s=%s", k, v)
op.Attrs[k] = v
mutated = true
}
}
}
return mutated, nil
}

View File

@ -20,7 +20,6 @@ func ProviderFromRef(ref string) (ocispecs.Descriptor, content.Provider, error)
headers := http.Header{}
headers.Set("User-Agent", version.UserAgent())
remote := docker.NewResolver(docker.ResolverOptions{
Client: http.DefaultClient,
Headers: headers,
})
@ -40,7 +39,6 @@ func IngesterFromRef(ref string) (content.Ingester, error) {
headers := http.Header{}
headers.Set("User-Agent", version.UserAgent())
remote := docker.NewResolver(docker.ResolverOptions{
Client: http.DefaultClient,
Headers: headers,
})

View File

@ -25,13 +25,13 @@ type contextKeyT string
var contextKey = contextKeyT("buildkit/util/flightcontrol.progress")
// Group is a flightcontrol synchronization group
type Group struct {
mu sync.Mutex // protects m
m map[string]*call // lazily initialized
type Group[T any] struct {
mu sync.Mutex // protects m
m map[string]*call[T] // lazily initialized
}
// Do executes a context function syncronized by the key
func (g *Group) Do(ctx context.Context, key string, fn func(ctx context.Context) (interface{}, error)) (v interface{}, err error) {
func (g *Group[T]) Do(ctx context.Context, key string, fn func(ctx context.Context) (T, error)) (v T, err error) {
var backoff time.Duration
for {
v, err = g.do(ctx, key, fn)
@ -53,10 +53,10 @@ func (g *Group) Do(ctx context.Context, key string, fn func(ctx context.Context)
}
}
func (g *Group) do(ctx context.Context, key string, fn func(ctx context.Context) (interface{}, error)) (interface{}, error) {
func (g *Group[T]) do(ctx context.Context, key string, fn func(ctx context.Context) (T, error)) (T, error) {
g.mu.Lock()
if g.m == nil {
g.m = make(map[string]*call)
g.m = make(map[string]*call[T])
}
if c, ok := g.m[key]; ok { // register 2nd waiter
@ -78,16 +78,16 @@ func (g *Group) do(ctx context.Context, key string, fn func(ctx context.Context)
return c.wait(ctx)
}
type call struct {
type call[T any] struct {
mu sync.Mutex
result interface{}
result T
err error
ready chan struct{}
cleaned chan struct{}
ctx *sharedContext
ctx *sharedContext[T]
ctxs []context.Context
fn func(ctx context.Context) (interface{}, error)
fn func(ctx context.Context) (T, error)
once sync.Once
closeProgressWriter func()
@ -95,8 +95,8 @@ type call struct {
progressCtx context.Context
}
func newCall(fn func(ctx context.Context) (interface{}, error)) *call {
c := &call{
func newCall[T any](fn func(ctx context.Context) (T, error)) *call[T] {
c := &call[T]{
fn: fn,
ready: make(chan struct{}),
cleaned: make(chan struct{}),
@ -114,7 +114,7 @@ func newCall(fn func(ctx context.Context) (interface{}, error)) *call {
return c
}
func (c *call) run() {
func (c *call[T]) run() {
defer c.closeProgressWriter()
ctx, cancel := context.WithCancel(c.ctx)
defer cancel()
@ -126,7 +126,8 @@ func (c *call) run() {
close(c.ready)
}
func (c *call) wait(ctx context.Context) (v interface{}, err error) {
func (c *call[T]) wait(ctx context.Context) (v T, err error) {
var empty T
c.mu.Lock()
// detect case where caller has just returned, let it clean up before
select {
@ -134,7 +135,7 @@ func (c *call) wait(ctx context.Context) (v interface{}, err error) {
c.mu.Unlock()
if c.err != nil { // on error retry
<-c.cleaned
return nil, errRetry
return empty, errRetry
}
pw, ok, _ := progress.NewFromContext(ctx)
if ok {
@ -145,7 +146,7 @@ func (c *call) wait(ctx context.Context) (v interface{}, err error) {
case <-c.ctx.done: // could return if no error
c.mu.Unlock()
<-c.cleaned
return nil, errRetry
return empty, errRetry
default:
}
@ -174,13 +175,13 @@ func (c *call) wait(ctx context.Context) (v interface{}, err error) {
if ok {
c.progressState.close(pw)
}
return nil, ctx.Err()
return empty, ctx.Err()
case <-c.ready:
return c.result, c.err // shared not implemented yet
}
}
func (c *call) Deadline() (deadline time.Time, ok bool) {
func (c *call[T]) Deadline() (deadline time.Time, ok bool) {
c.mu.Lock()
defer c.mu.Unlock()
for _, ctx := range c.ctxs {
@ -196,11 +197,11 @@ func (c *call) Deadline() (deadline time.Time, ok bool) {
return time.Time{}, false
}
func (c *call) Done() <-chan struct{} {
func (c *call[T]) Done() <-chan struct{} {
return c.ctx.done
}
func (c *call) Err() error {
func (c *call[T]) Err() error {
select {
case <-c.ctx.Done():
return c.ctx.err
@ -209,7 +210,7 @@ func (c *call) Err() error {
}
}
func (c *call) Value(key interface{}) interface{} {
func (c *call[T]) Value(key interface{}) interface{} {
if key == contextKey {
return c.progressState
}
@ -239,17 +240,17 @@ func (c *call) Value(key interface{}) interface{} {
return nil
}
type sharedContext struct {
*call
type sharedContext[T any] struct {
*call[T]
done chan struct{}
err error
}
func newContext(c *call) *sharedContext {
return &sharedContext{call: c, done: make(chan struct{})}
func newContext[T any](c *call[T]) *sharedContext[T] {
return &sharedContext[T]{call: c, done: make(chan struct{})}
}
func (sc *sharedContext) checkDone() bool {
func (sc *sharedContext[T]) checkDone() bool {
sc.mu.Lock()
select {
case <-sc.done:

View File

@ -0,0 +1,285 @@
package imageutil
import (
"context"
"encoding/json"
"fmt"
"strings"
"sync"
"time"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/images"
"github.com/containerd/containerd/leases"
"github.com/containerd/containerd/platforms"
"github.com/containerd/containerd/reference"
"github.com/containerd/containerd/remotes"
"github.com/containerd/containerd/remotes/docker"
intoto "github.com/in-toto/in-toto-golang/in_toto"
"github.com/moby/buildkit/solver/pb"
srctypes "github.com/moby/buildkit/source/types"
"github.com/moby/buildkit/sourcepolicy"
spb "github.com/moby/buildkit/sourcepolicy/pb"
"github.com/moby/buildkit/util/contentutil"
"github.com/moby/buildkit/util/leaseutil"
"github.com/moby/buildkit/util/resolver/limited"
"github.com/moby/buildkit/util/resolver/retryhandler"
digest "github.com/opencontainers/go-digest"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
type ContentCache interface {
content.Ingester
content.Provider
content.Manager
}
var leasesMu sync.Mutex
var leasesF []func(context.Context) error
func CancelCacheLeases() {
leasesMu.Lock()
for _, f := range leasesF {
f(context.TODO())
}
leasesF = nil
leasesMu.Unlock()
}
func AddLease(f func(context.Context) error) {
leasesMu.Lock()
leasesF = append(leasesF, f)
leasesMu.Unlock()
}
// ResolveToNonImageError is returned by the resolver when the ref is mutated by policy to a non-image ref
type ResolveToNonImageError struct {
Ref string
Updated string
}
func (e ResolveToNonImageError) Error() string {
return fmt.Sprintf("ref mutated by policy to non-image: %s://%s -> %s", srctypes.DockerImageScheme, e.Ref, e.Updated)
}
func Config(ctx context.Context, str string, resolver remotes.Resolver, cache ContentCache, leaseManager leases.Manager, p *ocispecs.Platform, spls []*spb.Policy) (string, digest.Digest, []byte, error) {
// TODO: fix buildkit to take interface instead of struct
var platform platforms.MatchComparer
if p != nil {
platform = platforms.Only(*p)
} else {
platform = platforms.Default()
}
ref, err := reference.Parse(str)
if err != nil {
return "", "", nil, errors.WithStack(err)
}
op := &pb.Op{
Op: &pb.Op_Source{
Source: &pb.SourceOp{
Identifier: srctypes.DockerImageScheme + "://" + ref.String(),
},
},
}
mut, err := sourcepolicy.NewEngine(spls).Evaluate(ctx, op)
if err != nil {
return "", "", nil, errors.Wrap(err, "could not resolve image due to policy")
}
if mut {
var (
t string
ok bool
)
t, newRef, ok := strings.Cut(op.GetSource().GetIdentifier(), "://")
if !ok {
return "", "", nil, errors.Errorf("could not parse ref: %s", op.GetSource().GetIdentifier())
}
if ok && t != srctypes.DockerImageScheme {
return "", "", nil, &ResolveToNonImageError{Ref: str, Updated: newRef}
}
ref, err = reference.Parse(newRef)
if err != nil {
return "", "", nil, errors.WithStack(err)
}
}
if leaseManager != nil {
ctx2, done, err := leaseutil.WithLease(ctx, leaseManager, leases.WithExpiration(5*time.Minute), leaseutil.MakeTemporary)
if err != nil {
return "", "", nil, errors.WithStack(err)
}
ctx = ctx2
defer func() {
// this lease is not deleted to allow other components to access manifest/config from cache. It will be deleted after 5 min deadline or on pruning inactive builder
AddLease(done)
}()
}
desc := ocispecs.Descriptor{
Digest: ref.Digest(),
}
if desc.Digest != "" {
ra, err := cache.ReaderAt(ctx, desc)
if err == nil {
info, err := cache.Info(ctx, desc.Digest)
if err == nil {
if ok, err := contentutil.HasSource(info, ref); err == nil && ok {
desc.Size = ra.Size()
mt, err := DetectManifestMediaType(ra)
if err == nil {
desc.MediaType = mt
}
}
}
}
}
// use resolver if desc is incomplete
if desc.MediaType == "" {
_, desc, err = resolver.Resolve(ctx, ref.String())
if err != nil {
return "", "", nil, err
}
}
fetcher, err := resolver.Fetcher(ctx, ref.String())
if err != nil {
return "", "", nil, err
}
if desc.MediaType == images.MediaTypeDockerSchema1Manifest {
dgst, dt, err := readSchema1Config(ctx, ref.String(), desc, fetcher, cache)
return ref.String(), dgst, dt, err
}
children := childrenConfigHandler(cache, platform)
dslHandler, err := docker.AppendDistributionSourceLabel(cache, ref.String())
if err != nil {
return "", "", nil, err
}
handlers := []images.Handler{
retryhandler.New(limited.FetchHandler(cache, fetcher, str), func(_ []byte) {}),
dslHandler,
children,
}
if err := images.Dispatch(ctx, images.Handlers(handlers...), nil, desc); err != nil {
return "", "", nil, err
}
config, err := images.Config(ctx, cache, desc, platform)
if err != nil {
return "", "", nil, err
}
dt, err := content.ReadBlob(ctx, cache, config)
if err != nil {
return "", "", nil, err
}
return ref.String(), desc.Digest, dt, nil
}
func childrenConfigHandler(provider content.Provider, platform platforms.MatchComparer) images.HandlerFunc {
return func(ctx context.Context, desc ocispecs.Descriptor) ([]ocispecs.Descriptor, error) {
var descs []ocispecs.Descriptor
switch desc.MediaType {
case images.MediaTypeDockerSchema2Manifest, ocispecs.MediaTypeImageManifest:
p, err := content.ReadBlob(ctx, provider, desc)
if err != nil {
return nil, err
}
// TODO(stevvooe): We just assume oci manifest, for now. There may be
// subtle differences from the docker version.
var manifest ocispecs.Manifest
if err := json.Unmarshal(p, &manifest); err != nil {
return nil, err
}
descs = append(descs, manifest.Config)
case images.MediaTypeDockerSchema2ManifestList, ocispecs.MediaTypeImageIndex:
p, err := content.ReadBlob(ctx, provider, desc)
if err != nil {
return nil, err
}
var index ocispecs.Index
if err := json.Unmarshal(p, &index); err != nil {
return nil, err
}
if platform != nil {
for _, d := range index.Manifests {
if d.Platform == nil || platform.Match(*d.Platform) {
descs = append(descs, d)
}
}
} else {
descs = append(descs, index.Manifests...)
}
case images.MediaTypeDockerSchema2Config, ocispecs.MediaTypeImageConfig, docker.LegacyConfigMediaType,
intoto.PayloadType:
// childless data types.
return nil, nil
default:
return nil, errors.Errorf("encountered unknown type %v; children may not be fetched", desc.MediaType)
}
return descs, nil
}
}
// specs.MediaTypeImageManifest, // TODO: detect schema1/manifest-list
func DetectManifestMediaType(ra content.ReaderAt) (string, error) {
// TODO: schema1
dt := make([]byte, ra.Size())
if _, err := ra.ReadAt(dt, 0); err != nil {
return "", err
}
return DetectManifestBlobMediaType(dt)
}
func DetectManifestBlobMediaType(dt []byte) (string, error) {
var mfst struct {
MediaType *string `json:"mediaType"`
Config json.RawMessage `json:"config"`
Manifests json.RawMessage `json:"manifests"`
Layers json.RawMessage `json:"layers"`
}
if err := json.Unmarshal(dt, &mfst); err != nil {
return "", err
}
mt := images.MediaTypeDockerSchema2ManifestList
if mfst.Config != nil || mfst.Layers != nil {
mt = images.MediaTypeDockerSchema2Manifest
if mfst.Manifests != nil {
return "", errors.Errorf("invalid ambiguous manifest and manifest list")
}
}
if mfst.MediaType != nil {
switch *mfst.MediaType {
case images.MediaTypeDockerSchema2ManifestList, ocispecs.MediaTypeImageIndex:
if mt != images.MediaTypeDockerSchema2ManifestList {
return "", errors.Errorf("mediaType in manifest does not match manifest contents")
}
mt = *mfst.MediaType
case images.MediaTypeDockerSchema2Manifest, ocispecs.MediaTypeImageManifest:
if mt != images.MediaTypeDockerSchema2Manifest {
return "", errors.Errorf("mediaType in manifest does not match manifest contents")
}
mt = *mfst.MediaType
}
}
return mt, nil
}

View File

@ -0,0 +1,88 @@
package imageutil
import (
"context"
"encoding/json"
"io"
"strings"
"time"
"github.com/containerd/containerd/remotes"
"github.com/moby/buildkit/exporter/containerimage/image"
digest "github.com/opencontainers/go-digest"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
)
func readSchema1Config(ctx context.Context, ref string, desc ocispecs.Descriptor, fetcher remotes.Fetcher, cache ContentCache) (digest.Digest, []byte, error) {
rc, err := fetcher.Fetch(ctx, desc)
if err != nil {
return "", nil, err
}
defer rc.Close()
dt, err := io.ReadAll(rc)
if err != nil {
return "", nil, errors.Wrap(err, "failed to fetch schema1 manifest")
}
dt, err = convertSchema1ConfigMeta(dt)
if err != nil {
return "", nil, err
}
return desc.Digest, dt, nil
}
func convertSchema1ConfigMeta(in []byte) ([]byte, error) {
type history struct {
V1Compatibility string `json:"v1Compatibility"`
}
var m struct {
History []history `json:"history"`
}
if err := json.Unmarshal(in, &m); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal schema1 manifest")
}
if len(m.History) == 0 {
return nil, errors.Errorf("invalid schema1 manifest")
}
var img image.Image
if err := json.Unmarshal([]byte(m.History[0].V1Compatibility), &img); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal image from schema 1 history")
}
img.RootFS = ocispecs.RootFS{
Type: "layers", // filled in by exporter
}
img.History = make([]ocispecs.History, len(m.History))
for i := range m.History {
var h v1History
if err := json.Unmarshal([]byte(m.History[i].V1Compatibility), &h); err != nil {
return nil, errors.Wrap(err, "failed to unmarshal history")
}
img.History[len(m.History)-i-1] = ocispecs.History{
Author: h.Author,
Comment: h.Comment,
Created: &h.Created,
CreatedBy: strings.Join(h.ContainerConfig.Cmd, " "),
EmptyLayer: (h.ThrowAway != nil && *h.ThrowAway) || (h.Size != nil && *h.Size == 0),
}
}
dt, err := json.MarshalIndent(img, "", " ")
if err != nil {
return nil, errors.Wrap(err, "failed to marshal schema1 config")
}
return dt, nil
}
type v1History struct {
Author string `json:"author,omitempty"`
Created time.Time `json:"created"`
Comment string `json:"comment,omitempty"`
ThrowAway *bool `json:"throwaway,omitempty"`
Size *int `json:"Size,omitempty"` // used before ThrowAway field
ContainerConfig struct {
Cmd []string `json:"Cmd,omitempty"`
} `json:"container_config,omitempty"`
}

View File

@ -0,0 +1,83 @@
package leaseutil
import (
"context"
"time"
"github.com/containerd/containerd/leases"
"github.com/containerd/containerd/namespaces"
)
func WithLease(ctx context.Context, ls leases.Manager, opts ...leases.Opt) (context.Context, func(context.Context) error, error) {
_, ok := leases.FromContext(ctx)
if ok {
return ctx, func(context.Context) error {
return nil
}, nil
}
l, err := ls.Create(ctx, append([]leases.Opt{leases.WithRandomID(), leases.WithExpiration(time.Hour)}, opts...)...)
if err != nil {
return nil, nil, err
}
ctx = leases.WithLease(ctx, l.ID)
return ctx, func(ctx context.Context) error {
return ls.Delete(ctx, l)
}, nil
}
func MakeTemporary(l *leases.Lease) error {
if l.Labels == nil {
l.Labels = map[string]string{}
}
l.Labels["buildkit/lease.temporary"] = time.Now().UTC().Format(time.RFC3339Nano)
return nil
}
func WithNamespace(lm leases.Manager, ns string) *Manager {
return &Manager{manager: lm, ns: ns}
}
type Manager struct {
manager leases.Manager
ns string
}
func (l *Manager) Namespace() string {
return l.ns
}
func (l *Manager) WithNamespace(ns string) *Manager {
return WithNamespace(l.manager, ns)
}
func (l *Manager) Create(ctx context.Context, opts ...leases.Opt) (leases.Lease, error) {
ctx = namespaces.WithNamespace(ctx, l.ns)
return l.manager.Create(ctx, opts...)
}
func (l *Manager) Delete(ctx context.Context, lease leases.Lease, opts ...leases.DeleteOpt) error {
ctx = namespaces.WithNamespace(ctx, l.ns)
return l.manager.Delete(ctx, lease, opts...)
}
func (l *Manager) List(ctx context.Context, filters ...string) ([]leases.Lease, error) {
ctx = namespaces.WithNamespace(ctx, l.ns)
return l.manager.List(ctx, filters...)
}
func (l *Manager) AddResource(ctx context.Context, lease leases.Lease, resource leases.Resource) error {
ctx = namespaces.WithNamespace(ctx, l.ns)
return l.manager.AddResource(ctx, lease, resource)
}
func (l *Manager) DeleteResource(ctx context.Context, lease leases.Lease, resource leases.Resource) error {
ctx = namespaces.WithNamespace(ctx, l.ns)
return l.manager.DeleteResource(ctx, lease, resource)
}
func (l *Manager) ListResources(ctx context.Context, lease leases.Lease) ([]leases.Resource, error) {
ctx = namespaces.WithNamespace(ctx, l.ns)
return l.manager.ListResources(ctx, lease)
}

View File

@ -37,8 +37,8 @@ func NormalizePath(parent, newPath, inputOS string, keepSlash bool) (string, err
inputOS = "linux"
}
newPath = toSlash(newPath, inputOS)
parent = toSlash(parent, inputOS)
newPath = ToSlash(newPath, inputOS)
parent = ToSlash(parent, inputOS)
origPath := newPath
if parent == "" {
@ -82,18 +82,17 @@ func NormalizePath(parent, newPath, inputOS string, keepSlash bool) (string, err
}
}
return toSlash(newPath, inputOS), nil
return ToSlash(newPath, inputOS), nil
}
func toSlash(inputPath, inputOS string) string {
separator := "/"
if inputOS == "windows" {
separator = "\\"
func ToSlash(inputPath, inputOS string) string {
if inputOS != "windows" {
return inputPath
}
return strings.Replace(inputPath, separator, "/", -1)
return strings.Replace(inputPath, "\\", "/", -1)
}
func fromSlash(inputPath, inputOS string) string {
func FromSlash(inputPath, inputOS string) string {
separator := "/"
if inputOS == "windows" {
separator = "\\"
@ -119,7 +118,7 @@ func NormalizeWorkdir(current, wd string, inputOS string) (string, error) {
// Make sure we use the platform specific path separator. HCS does not like forward
// slashes in CWD.
return fromSlash(wd, inputOS), nil
return FromSlash(wd, inputOS), nil
}
// IsAbs returns a boolean value indicating whether or not the path
@ -142,7 +141,7 @@ func IsAbs(pth, inputOS string) bool {
if err != nil {
return false
}
cleanedPath = toSlash(cleanedPath, inputOS)
cleanedPath = ToSlash(cleanedPath, inputOS)
// We stripped any potential drive letter and converted any backslashes to
// forward slashes. We can safely use path.IsAbs() for both Windows and Linux.
return path.IsAbs(cleanedPath)
@ -189,14 +188,14 @@ func CheckSystemDriveAndRemoveDriveLetter(path string, inputOS string) (string,
}
// UNC paths should error out
if len(path) >= 2 && toSlash(path[:2], inputOS) == "//" {
if len(path) >= 2 && ToSlash(path[:2], inputOS) == "//" {
return "", errors.Errorf("UNC paths are not supported")
}
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(filepath.Clean(path), inputOS), nil
}
// We expect all paths to be in C:
@ -221,5 +220,5 @@ 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(filepath.Clean(parts[1]), inputOS), nil
}

View File

@ -137,6 +137,7 @@ func (c Moby) New(ctx context.Context, cfg *BackendConfig) (b Backend, cl func()
dockerdFlags := []string{
"--config-file", dockerdConfigFile,
"--userland-proxy=false",
"--tls=false",
"--debug",
}
if s := os.Getenv("BUILDKIT_INTEGRATION_DOCKERD_FLAGS"); s != "" {

View File

@ -0,0 +1,87 @@
package wildcard
import (
"regexp"
"strings"
"github.com/pkg/errors"
)
// New returns a wildcard object for a string that contains "*" symbols.
func New(s string) (*Wildcard, error) {
reStr, err := Wildcard2Regexp(s)
if err != nil {
return nil, errors.Wrapf(err, "failed to translate wildcard %q to regexp", s)
}
re, err := regexp.Compile(reStr)
if err != nil {
return nil, errors.Wrapf(err, "failed to compile regexp %q (translated from wildcard %q)", reStr, s)
}
w := &Wildcard{
orig: s,
re: re,
}
return w, nil
}
// Wildcard2Regexp translates a wildcard string to a regexp string.
func Wildcard2Regexp(wildcard string) (string, error) {
s := regexp.QuoteMeta(wildcard)
if strings.Contains(s, "\\*\\*") {
return "", errors.New("invalid wildcard: \"**\"")
}
s = strings.ReplaceAll(s, "\\*", "(.*)")
s = "^" + s + "$"
return s, nil
}
// Wildcard is a wildcard matcher object.
type Wildcard struct {
orig string
re *regexp.Regexp
}
// String implements fmt.Stringer.
func (w *Wildcard) String() string {
return w.orig
}
// Match returns a non-nil Match on match.
func (w *Wildcard) Match(q string) *Match {
submatches := w.re.FindStringSubmatch(q)
if len(submatches) == 0 {
return nil
}
m := &Match{
w: w,
Submatches: submatches,
// FIXME: avoid executing regexp twice
idx: w.re.FindStringSubmatchIndex(q),
}
return m
}
// Match is a matched result.
type Match struct {
w *Wildcard
Submatches []string // 0: the entire query, 1: the first submatch, 2: the second submatch, ...
idx []int
}
// String implements fmt.Stringer.
func (m *Match) String() string {
if len(m.Submatches) == 0 {
return ""
}
return m.Submatches[0]
}
// Format formats submatch strings like "$1", "$2".
func (m *Match) Format(f string) (string, error) {
if m.w == nil || len(m.Submatches) == 0 || len(m.idx) == 0 {
return "", errors.New("invalid state")
}
var b []byte
b = m.w.re.ExpandString(b, f, m.Submatches[0], m.idx)
return string(b), nil
}