build: set record provenance in response

Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax 2024-03-15 14:38:00 +01:00
parent d2ac1f2d6e
commit 2e2f9f571f
No known key found for this signature in database
GPG Key ID: ADE44D8C9D44FBE4
18 changed files with 885 additions and 225 deletions

View File

@ -82,6 +82,8 @@ jobs:
driver-opt: qemu.install=true driver-opt: qemu.install=true
- driver: remote - driver: remote
endpoint: tcp://localhost:1234 endpoint: tcp://localhost:1234
- driver: docker-container
metadata-provenance: max
exclude: exclude:
- driver: docker - driver: docker
multi-node: mnode-true multi-node: mnode-true
@ -129,6 +131,9 @@ jobs:
else else
echo "MULTI_NODE=0" >> $GITHUB_ENV echo "MULTI_NODE=0" >> $GITHUB_ENV
fi fi
if [ -n "${{ matrix.metadata-provenance }}" ]; then
echo "BUILDX_METADATA_PROVENANCE=${{ matrix.metadata-provenance }}" >> $GITHUB_ENV
fi
- -
name: Install k3s name: Install k3s
if: matrix.driver == 'kubernetes' if: matrix.driver == 'kubernetes'

View File

@ -79,11 +79,12 @@ type Options struct {
Target string Target string
Ulimits *opts.UlimitOpt Ulimits *opts.UlimitOpt
Session []session.Attachable Session []session.Attachable
Linked bool // Linked marks this target as exclusively linked (not requested by the user). Linked bool // Linked marks this target as exclusively linked (not requested by the user).
PrintFunc *PrintFunc PrintFunc *PrintFunc
SourcePolicy *spb.Policy WithProvenanceResponse bool
GroupRef string SourcePolicy *spb.Policy
GroupRef string
} }
type PrintFunc struct { type PrintFunc struct {
@ -488,6 +489,11 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s
rr.ExporterResponse[k] = string(v) rr.ExporterResponse[k] = string(v)
} }
rr.ExporterResponse["buildx.build.ref"] = buildRef rr.ExporterResponse["buildx.build.ref"] = buildRef
if opt.WithProvenanceResponse && node.Driver.HistoryAPISupported(ctx) {
if err := setRecordProvenance(ctx, c, rr, so.Ref, pw); err != nil {
return err
}
}
node := dp.Node().Driver node := dp.Node().Driver
if node.IsMobyDriver() { if node.IsMobyDriver() {

157
build/provenance.go Normal file
View File

@ -0,0 +1,157 @@
package build
import (
"context"
"encoding/base64"
"encoding/json"
"io"
"strings"
"sync"
"github.com/containerd/containerd/content"
"github.com/containerd/containerd/content/proxy"
"github.com/docker/buildx/util/confutil"
"github.com/docker/buildx/util/progress"
controlapi "github.com/moby/buildkit/api/services/control"
"github.com/moby/buildkit/client"
provenancetypes "github.com/moby/buildkit/solver/llbsolver/provenance/types"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"golang.org/x/sync/errgroup"
)
type provenancePredicate struct {
Builder *provenanceBuilder `json:"builder,omitempty"`
provenancetypes.ProvenancePredicate
}
type provenanceBuilder struct {
ID string `json:"id,omitempty"`
}
func setRecordProvenance(ctx context.Context, c *client.Client, sr *client.SolveResponse, ref string, pw progress.Writer) error {
mode := confutil.MetadataProvenance()
if mode == confutil.MetadataProvenanceModeDisabled {
return nil
}
pw = progress.ResetTime(pw)
return progress.Wrap("resolving provenance for metadata file", pw.Write, func(l progress.SubLogger) error {
res, err := fetchProvenance(ctx, c, ref, mode)
if err != nil {
return err
}
for k, v := range res {
sr.ExporterResponse[k] = v
}
return nil
})
}
func fetchProvenance(ctx context.Context, c *client.Client, ref string, mode confutil.MetadataProvenanceMode) (out map[string]string, err error) {
cl, err := c.ControlClient().ListenBuildHistory(ctx, &controlapi.BuildHistoryRequest{
Ref: ref,
EarlyExit: true,
})
if err != nil {
return nil, err
}
var mu sync.Mutex
eg, ctx := errgroup.WithContext(ctx)
store := proxy.NewContentStore(c.ContentClient())
for {
ev, err := cl.Recv()
if errors.Is(err, io.EOF) {
break
} else if err != nil {
return nil, err
}
if ev.Record == nil {
continue
}
if ev.Record.Result != nil {
desc := lookupProvenance(ev.Record.Result)
if desc == nil {
continue
}
eg.Go(func() error {
dt, err := content.ReadBlob(ctx, store, *desc)
if err != nil {
return errors.Wrapf(err, "failed to load provenance blob from build record")
}
prv, err := encodeProvenance(dt, mode)
if err != nil {
return err
}
mu.Lock()
if out == nil {
out = make(map[string]string)
}
out["buildx.build.provenance"] = prv
mu.Unlock()
return nil
})
} else if ev.Record.Results != nil {
for platform, res := range ev.Record.Results {
platform := platform
desc := lookupProvenance(res)
if desc == nil {
continue
}
eg.Go(func() error {
dt, err := content.ReadBlob(ctx, store, *desc)
if err != nil {
return errors.Wrapf(err, "failed to load provenance blob from build record")
}
prv, err := encodeProvenance(dt, mode)
if err != nil {
return err
}
mu.Lock()
if out == nil {
out = make(map[string]string)
}
out["buildx.build.provenance/"+platform] = prv
mu.Unlock()
return nil
})
}
}
}
return out, eg.Wait()
}
func lookupProvenance(res *controlapi.BuildResultInfo) *ocispecs.Descriptor {
for _, a := range res.Attestations {
if a.MediaType == "application/vnd.in-toto+json" && strings.HasPrefix(a.Annotations["in-toto.io/predicate-type"], "https://slsa.dev/provenance/") {
return &ocispecs.Descriptor{
Digest: a.Digest,
Size: a.Size_,
MediaType: a.MediaType,
Annotations: a.Annotations,
}
}
}
return nil
}
func encodeProvenance(dt []byte, mode confutil.MetadataProvenanceMode) (string, error) {
var prv provenancePredicate
if err := json.Unmarshal(dt, &prv); err != nil {
return "", errors.Wrapf(err, "failed to unmarshal provenance")
}
if prv.Builder != nil && prv.Builder.ID == "" {
// reset builder if id is empty
prv.Builder = nil
}
if mode == confutil.MetadataProvenanceModeMin {
// reset fields for minimal provenance
prv.BuildConfig = nil
prv.Metadata = nil
}
dtprv, err := json.Marshal(prv)
if err != nil {
return "", errors.Wrapf(err, "failed to marshal provenance")
}
return base64.StdEncoding.EncodeToString(dtprv), nil
}

View File

@ -202,12 +202,12 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba
return nil return nil
} }
// local state group
groupRef := identity.NewID() groupRef := identity.NewID()
var refs []string var refs []string
for k, b := range bo { for k, b := range bo {
b.Ref = identity.NewID() b.Ref = identity.NewID()
b.GroupRef = groupRef b.GroupRef = groupRef
b.WithProvenanceResponse = len(in.metadataFile) > 0
refs = append(refs, b.Ref) refs = append(refs, b.Ref)
bo[k] = b bo[k] = b
} }

View File

@ -121,26 +121,27 @@ func (o *buildOptions) toControllerOptions() (*controllerapi.BuildOptions, error
} }
opts := controllerapi.BuildOptions{ opts := controllerapi.BuildOptions{
Allow: o.allow, Allow: o.allow,
Annotations: o.annotations, Annotations: o.annotations,
BuildArgs: buildArgs, BuildArgs: buildArgs,
CgroupParent: o.cgroupParent, CgroupParent: o.cgroupParent,
ContextPath: o.contextPath, ContextPath: o.contextPath,
DockerfileName: o.dockerfileName, DockerfileName: o.dockerfileName,
ExtraHosts: o.extraHosts, ExtraHosts: o.extraHosts,
Labels: labels, Labels: labels,
NetworkMode: o.networkMode, NetworkMode: o.networkMode,
NoCacheFilter: o.noCacheFilter, NoCacheFilter: o.noCacheFilter,
Platforms: o.platforms, Platforms: o.platforms,
ShmSize: int64(o.shmSize), ShmSize: int64(o.shmSize),
Tags: o.tags, Tags: o.tags,
Target: o.target, Target: o.target,
Ulimits: dockerUlimitToControllerUlimit(o.ulimits), Ulimits: dockerUlimitToControllerUlimit(o.ulimits),
Builder: o.builder, Builder: o.builder,
NoCache: o.noCache, NoCache: o.noCache,
Pull: o.pull, Pull: o.pull,
ExportPush: o.exportPush, ExportPush: o.exportPush,
ExportLoad: o.exportLoad, ExportLoad: o.exportLoad,
WithProvenanceResponse: len(o.metadataFile) > 0,
} }
// TODO: extract env var parsing to a method easily usable by library consumers // TODO: extract env var parsing to a method easily usable by library consumers
@ -582,7 +583,7 @@ func buildCmd(dockerCli command.Cli, rootOpts *rootOptions, debugConfig *debug.D
flags.StringVarP(&options.dockerfileName, "file", "f", "", `Name of the Dockerfile (default: "PATH/Dockerfile")`) flags.StringVarP(&options.dockerfileName, "file", "f", "", `Name of the Dockerfile (default: "PATH/Dockerfile")`)
flags.SetAnnotation("file", annotation.ExternalURL, []string{"https://docs.docker.com/reference/cli/docker/image/build/#file"}) flags.SetAnnotation("file", annotation.ExternalURL, []string{"https://docs.docker.com/reference/cli/docker/image/build/#file"})
flags.StringVar(&options.imageIDFile, "iidfile", "", "Write the image ID to the file") flags.StringVar(&options.imageIDFile, "iidfile", "", "Write the image ID to a file")
flags.StringArrayVar(&options.labels, "label", []string{}, "Set metadata for an image") flags.StringArrayVar(&options.labels, "label", []string{}, "Set metadata for an image")
@ -697,7 +698,7 @@ func commonBuildFlags(options *commonFlags, flags *pflag.FlagSet) {
options.noCache = flags.Bool("no-cache", false, "Do not use cache when building the image") options.noCache = flags.Bool("no-cache", false, "Do not use cache when building the image")
flags.StringVar(&options.progress, "progress", "auto", `Set type of progress output ("auto", "plain", "tty"). Use plain to show container output`) flags.StringVar(&options.progress, "progress", "auto", `Set type of progress output ("auto", "plain", "tty"). Use plain to show container output`)
options.pull = flags.Bool("pull", false, "Always attempt to pull all referenced images") options.pull = flags.Bool("pull", false, "Always attempt to pull all referenced images")
flags.StringVar(&options.metadataFile, "metadata-file", "", "Write build result metadata to the file") flags.StringVar(&options.metadataFile, "metadata-file", "", "Write build result metadata to a file")
} }
func checkWarnedFlags(f *pflag.Flag) { func checkWarnedFlags(f *pflag.Flag) {

View File

@ -53,20 +53,21 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
InStream: inStream, InStream: inStream,
NamedContexts: contexts, NamedContexts: contexts,
}, },
Ref: in.Ref, Ref: in.Ref,
BuildArgs: in.BuildArgs, BuildArgs: in.BuildArgs,
CgroupParent: in.CgroupParent, CgroupParent: in.CgroupParent,
ExtraHosts: in.ExtraHosts, ExtraHosts: in.ExtraHosts,
Labels: in.Labels, Labels: in.Labels,
NetworkMode: in.NetworkMode, NetworkMode: in.NetworkMode,
NoCache: in.NoCache, NoCache: in.NoCache,
NoCacheFilter: in.NoCacheFilter, NoCacheFilter: in.NoCacheFilter,
Pull: in.Pull, Pull: in.Pull,
ShmSize: dockeropts.MemBytes(in.ShmSize), ShmSize: dockeropts.MemBytes(in.ShmSize),
Tags: in.Tags, Tags: in.Tags,
Target: in.Target, Target: in.Target,
Ulimits: controllerUlimitOpt2DockerUlimit(in.Ulimits), Ulimits: controllerUlimitOpt2DockerUlimit(in.Ulimits),
GroupRef: in.GroupRef, GroupRef: in.GroupRef,
WithProvenanceResponse: in.WithProvenanceResponse,
} }
platforms, err := platformutil.Parse(in.Platforms) platforms, err := platformutil.Parse(in.Platforms)

View File

@ -271,40 +271,41 @@ func (m *BuildRequest) GetOptions() *BuildOptions {
} }
type BuildOptions struct { type BuildOptions struct {
ContextPath string `protobuf:"bytes,1,opt,name=ContextPath,proto3" json:"ContextPath,omitempty"` ContextPath string `protobuf:"bytes,1,opt,name=ContextPath,proto3" json:"ContextPath,omitempty"`
DockerfileName string `protobuf:"bytes,2,opt,name=DockerfileName,proto3" json:"DockerfileName,omitempty"` DockerfileName string `protobuf:"bytes,2,opt,name=DockerfileName,proto3" json:"DockerfileName,omitempty"`
PrintFunc *PrintFunc `protobuf:"bytes,3,opt,name=PrintFunc,proto3" json:"PrintFunc,omitempty"` PrintFunc *PrintFunc `protobuf:"bytes,3,opt,name=PrintFunc,proto3" json:"PrintFunc,omitempty"`
NamedContexts map[string]string `protobuf:"bytes,4,rep,name=NamedContexts,proto3" json:"NamedContexts,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` NamedContexts map[string]string `protobuf:"bytes,4,rep,name=NamedContexts,proto3" json:"NamedContexts,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
Allow []string `protobuf:"bytes,5,rep,name=Allow,proto3" json:"Allow,omitempty"` Allow []string `protobuf:"bytes,5,rep,name=Allow,proto3" json:"Allow,omitempty"`
Attests []*Attest `protobuf:"bytes,6,rep,name=Attests,proto3" json:"Attests,omitempty"` Attests []*Attest `protobuf:"bytes,6,rep,name=Attests,proto3" json:"Attests,omitempty"`
BuildArgs map[string]string `protobuf:"bytes,7,rep,name=BuildArgs,proto3" json:"BuildArgs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` BuildArgs map[string]string `protobuf:"bytes,7,rep,name=BuildArgs,proto3" json:"BuildArgs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
CacheFrom []*CacheOptionsEntry `protobuf:"bytes,8,rep,name=CacheFrom,proto3" json:"CacheFrom,omitempty"` CacheFrom []*CacheOptionsEntry `protobuf:"bytes,8,rep,name=CacheFrom,proto3" json:"CacheFrom,omitempty"`
CacheTo []*CacheOptionsEntry `protobuf:"bytes,9,rep,name=CacheTo,proto3" json:"CacheTo,omitempty"` CacheTo []*CacheOptionsEntry `protobuf:"bytes,9,rep,name=CacheTo,proto3" json:"CacheTo,omitempty"`
CgroupParent string `protobuf:"bytes,10,opt,name=CgroupParent,proto3" json:"CgroupParent,omitempty"` CgroupParent string `protobuf:"bytes,10,opt,name=CgroupParent,proto3" json:"CgroupParent,omitempty"`
Exports []*ExportEntry `protobuf:"bytes,11,rep,name=Exports,proto3" json:"Exports,omitempty"` Exports []*ExportEntry `protobuf:"bytes,11,rep,name=Exports,proto3" json:"Exports,omitempty"`
ExtraHosts []string `protobuf:"bytes,12,rep,name=ExtraHosts,proto3" json:"ExtraHosts,omitempty"` ExtraHosts []string `protobuf:"bytes,12,rep,name=ExtraHosts,proto3" json:"ExtraHosts,omitempty"`
Labels map[string]string `protobuf:"bytes,13,rep,name=Labels,proto3" json:"Labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Labels map[string]string `protobuf:"bytes,13,rep,name=Labels,proto3" json:"Labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
NetworkMode string `protobuf:"bytes,14,opt,name=NetworkMode,proto3" json:"NetworkMode,omitempty"` NetworkMode string `protobuf:"bytes,14,opt,name=NetworkMode,proto3" json:"NetworkMode,omitempty"`
NoCacheFilter []string `protobuf:"bytes,15,rep,name=NoCacheFilter,proto3" json:"NoCacheFilter,omitempty"` NoCacheFilter []string `protobuf:"bytes,15,rep,name=NoCacheFilter,proto3" json:"NoCacheFilter,omitempty"`
Platforms []string `protobuf:"bytes,16,rep,name=Platforms,proto3" json:"Platforms,omitempty"` Platforms []string `protobuf:"bytes,16,rep,name=Platforms,proto3" json:"Platforms,omitempty"`
Secrets []*Secret `protobuf:"bytes,17,rep,name=Secrets,proto3" json:"Secrets,omitempty"` Secrets []*Secret `protobuf:"bytes,17,rep,name=Secrets,proto3" json:"Secrets,omitempty"`
ShmSize int64 `protobuf:"varint,18,opt,name=ShmSize,proto3" json:"ShmSize,omitempty"` ShmSize int64 `protobuf:"varint,18,opt,name=ShmSize,proto3" json:"ShmSize,omitempty"`
SSH []*SSH `protobuf:"bytes,19,rep,name=SSH,proto3" json:"SSH,omitempty"` SSH []*SSH `protobuf:"bytes,19,rep,name=SSH,proto3" json:"SSH,omitempty"`
Tags []string `protobuf:"bytes,20,rep,name=Tags,proto3" json:"Tags,omitempty"` Tags []string `protobuf:"bytes,20,rep,name=Tags,proto3" json:"Tags,omitempty"`
Target string `protobuf:"bytes,21,opt,name=Target,proto3" json:"Target,omitempty"` Target string `protobuf:"bytes,21,opt,name=Target,proto3" json:"Target,omitempty"`
Ulimits *UlimitOpt `protobuf:"bytes,22,opt,name=Ulimits,proto3" json:"Ulimits,omitempty"` Ulimits *UlimitOpt `protobuf:"bytes,22,opt,name=Ulimits,proto3" json:"Ulimits,omitempty"`
Builder string `protobuf:"bytes,23,opt,name=Builder,proto3" json:"Builder,omitempty"` Builder string `protobuf:"bytes,23,opt,name=Builder,proto3" json:"Builder,omitempty"`
NoCache bool `protobuf:"varint,24,opt,name=NoCache,proto3" json:"NoCache,omitempty"` NoCache bool `protobuf:"varint,24,opt,name=NoCache,proto3" json:"NoCache,omitempty"`
Pull bool `protobuf:"varint,25,opt,name=Pull,proto3" json:"Pull,omitempty"` Pull bool `protobuf:"varint,25,opt,name=Pull,proto3" json:"Pull,omitempty"`
ExportPush bool `protobuf:"varint,26,opt,name=ExportPush,proto3" json:"ExportPush,omitempty"` ExportPush bool `protobuf:"varint,26,opt,name=ExportPush,proto3" json:"ExportPush,omitempty"`
ExportLoad bool `protobuf:"varint,27,opt,name=ExportLoad,proto3" json:"ExportLoad,omitempty"` ExportLoad bool `protobuf:"varint,27,opt,name=ExportLoad,proto3" json:"ExportLoad,omitempty"`
SourcePolicy *pb.Policy `protobuf:"bytes,28,opt,name=SourcePolicy,proto3" json:"SourcePolicy,omitempty"` SourcePolicy *pb.Policy `protobuf:"bytes,28,opt,name=SourcePolicy,proto3" json:"SourcePolicy,omitempty"`
Ref string `protobuf:"bytes,29,opt,name=Ref,proto3" json:"Ref,omitempty"` Ref string `protobuf:"bytes,29,opt,name=Ref,proto3" json:"Ref,omitempty"`
GroupRef string `protobuf:"bytes,30,opt,name=GroupRef,proto3" json:"GroupRef,omitempty"` GroupRef string `protobuf:"bytes,30,opt,name=GroupRef,proto3" json:"GroupRef,omitempty"`
Annotations []string `protobuf:"bytes,31,rep,name=Annotations,proto3" json:"Annotations,omitempty"` Annotations []string `protobuf:"bytes,31,rep,name=Annotations,proto3" json:"Annotations,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"` WithProvenanceResponse bool `protobuf:"varint,32,opt,name=WithProvenanceResponse,proto3" json:"WithProvenanceResponse,omitempty"`
XXX_unrecognized []byte `json:"-"` XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_sizecache int32 `json:"-"` XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
} }
func (m *BuildOptions) Reset() { *m = BuildOptions{} } func (m *BuildOptions) Reset() { *m = BuildOptions{} }
@ -548,6 +549,13 @@ func (m *BuildOptions) GetAnnotations() []string {
return nil return nil
} }
func (m *BuildOptions) GetWithProvenanceResponse() bool {
if m != nil {
return m.WithProvenanceResponse
}
return false
}
type ExportEntry struct { type ExportEntry struct {
Type string `protobuf:"bytes,1,opt,name=Type,proto3" json:"Type,omitempty"` Type string `protobuf:"bytes,1,opt,name=Type,proto3" json:"Type,omitempty"`
Attrs map[string]string `protobuf:"bytes,2,rep,name=Attrs,proto3" json:"Attrs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` Attrs map[string]string `protobuf:"bytes,2,rep,name=Attrs,proto3" json:"Attrs,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
@ -2078,128 +2086,129 @@ func init() {
func init() { proto.RegisterFile("controller.proto", fileDescriptor_ed7f10298fa1d90f) } func init() { proto.RegisterFile("controller.proto", fileDescriptor_ed7f10298fa1d90f) }
var fileDescriptor_ed7f10298fa1d90f = []byte{ var fileDescriptor_ed7f10298fa1d90f = []byte{
// 1922 bytes of a gzipped FileDescriptorProto // 1946 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x58, 0x5f, 0x73, 0x1b, 0x49, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x58, 0x5f, 0x53, 0x1b, 0xc9,
0x11, 0x67, 0x25, 0x59, 0x7f, 0x5a, 0x96, 0xcf, 0x19, 0x9c, 0x30, 0xd9, 0xe4, 0x12, 0x67, 0x93, 0x11, 0xcf, 0x4a, 0x42, 0x7f, 0x5a, 0x08, 0xe3, 0x09, 0x76, 0xc6, 0x6b, 0x9f, 0x8d, 0xd7, 0xf6,
0x1c, 0x2a, 0x42, 0xc9, 0x77, 0x3e, 0x82, 0x2f, 0x97, 0xbb, 0x2a, 0x6c, 0xd9, 0xc2, 0xbe, 0x4a, 0x45, 0x15, 0xa7, 0xc4, 0x1d, 0x17, 0x1f, 0xe7, 0xf3, 0x5d, 0x55, 0x40, 0xa0, 0xc0, 0x95, 0x0d,
0x6c, 0xd7, 0xca, 0xc9, 0x15, 0x50, 0xc5, 0xd5, 0x5a, 0x1a, 0xcb, 0x5b, 0x5a, 0xed, 0x88, 0x9d, 0xd4, 0x0a, 0xdb, 0x95, 0xa4, 0x2a, 0xae, 0x45, 0x1a, 0xc4, 0x16, 0xcb, 0x8e, 0xb2, 0x33, 0x12,
0x91, 0x6d, 0xf1, 0xc4, 0x03, 0xbc, 0x51, 0x14, 0x5f, 0x83, 0xe2, 0x23, 0xf0, 0xc4, 0x37, 0xe2, 0x28, 0x4f, 0x79, 0x48, 0xde, 0x52, 0xf9, 0x1e, 0xa9, 0x7c, 0x84, 0x3c, 0xe5, 0x2d, 0x1f, 0x27,
0x23, 0x50, 0xd3, 0x33, 0xbb, 0x5a, 0x59, 0x5a, 0xd9, 0x86, 0x27, 0x4d, 0xf7, 0xfe, 0xba, 0x7b, 0x1f, 0x21, 0x35, 0x3d, 0xb3, 0xab, 0x15, 0xd2, 0x0a, 0xc8, 0x3d, 0x69, 0xba, 0xf7, 0xd7, 0xdd,
0xba, 0xa7, 0xa7, 0xbb, 0x47, 0xb0, 0xda, 0xe1, 0xa1, 0x8c, 0x78, 0x10, 0xb0, 0xa8, 0x31, 0x8c, 0xd3, 0x3d, 0x3d, 0xdd, 0x3d, 0x82, 0xe5, 0x0e, 0x0f, 0x65, 0xc4, 0x83, 0x80, 0x45, 0x8d, 0x7e,
0xb8, 0xe4, 0x64, 0xed, 0x74, 0xe4, 0x07, 0xdd, 0xab, 0x46, 0xea, 0xc3, 0xc5, 0x17, 0xf6, 0xdb, 0xc4, 0x25, 0x27, 0x2b, 0xc7, 0x03, 0x3f, 0xe8, 0x5e, 0x36, 0x52, 0x1f, 0x86, 0x5f, 0xda, 0x6f,
0x9e, 0x2f, 0xcf, 0x47, 0xa7, 0x8d, 0x0e, 0x1f, 0x6c, 0x0c, 0xf8, 0xe9, 0x78, 0x03, 0x51, 0x7d, 0x7a, 0xbe, 0x3c, 0x1d, 0x1c, 0x37, 0x3a, 0xfc, 0x7c, 0xed, 0x9c, 0x1f, 0x8f, 0xd6, 0x10, 0x75,
0x5f, 0x6e, 0x78, 0x43, 0x7f, 0x43, 0xb0, 0xe8, 0xc2, 0xef, 0x30, 0xb1, 0x61, 0x84, 0xe2, 0x5f, 0xe6, 0xcb, 0x35, 0xaf, 0xef, 0xaf, 0x09, 0x16, 0x0d, 0xfd, 0x0e, 0x13, 0x6b, 0x46, 0x28, 0xfe,
0xad, 0xd2, 0x7e, 0x9d, 0x29, 0x2c, 0xf8, 0x28, 0xea, 0xb0, 0x21, 0x0f, 0xfc, 0xce, 0x78, 0x63, 0xd5, 0x2a, 0xed, 0x57, 0x99, 0xc2, 0x82, 0x0f, 0xa2, 0x0e, 0xeb, 0xf3, 0xc0, 0xef, 0x8c, 0xd6,
0x78, 0xba, 0xa1, 0x57, 0x5a, 0xcc, 0xa9, 0xc3, 0xda, 0x3b, 0x5f, 0xc8, 0xe3, 0x88, 0x77, 0x98, 0xfa, 0xc7, 0x6b, 0x7a, 0xa5, 0xc5, 0x9c, 0x3a, 0xac, 0xbc, 0xf5, 0x85, 0x3c, 0x8c, 0x78, 0x87,
0x10, 0x4c, 0xb8, 0xec, 0x0f, 0x23, 0x26, 0x24, 0x59, 0x85, 0xbc, 0xcb, 0xce, 0xa8, 0xb5, 0x6e, 0x09, 0xc1, 0x84, 0xcb, 0xfe, 0x38, 0x60, 0x42, 0x92, 0x65, 0xc8, 0xbb, 0xec, 0x84, 0x5a, 0xab,
0xd5, 0x2b, 0xae, 0x5a, 0x3a, 0xc7, 0x70, 0xff, 0x1a, 0x52, 0x0c, 0x79, 0x28, 0x18, 0xd9, 0x82, 0x56, 0xbd, 0xe2, 0xaa, 0xa5, 0x73, 0x08, 0xf7, 0xae, 0x20, 0x45, 0x9f, 0x87, 0x82, 0x91, 0x0d,
0xa5, 0x83, 0xf0, 0x8c, 0x0b, 0x6a, 0xad, 0xe7, 0xeb, 0xd5, 0xcd, 0x67, 0x8d, 0x79, 0xce, 0x35, 0x58, 0xd8, 0x0b, 0x4f, 0xb8, 0xa0, 0xd6, 0x6a, 0xbe, 0x5e, 0x5d, 0x7f, 0xda, 0x98, 0xe5, 0x5c,
0x8c, 0x9c, 0x42, 0xba, 0x1a, 0xef, 0x08, 0xa8, 0xa6, 0xb8, 0xe4, 0x31, 0x54, 0x62, 0x72, 0xd7, 0xc3, 0xc8, 0x29, 0xa4, 0xab, 0xf1, 0x8e, 0x80, 0x6a, 0x8a, 0x4b, 0x1e, 0x41, 0x25, 0x26, 0xb7,
0x18, 0x9e, 0x30, 0x48, 0x0b, 0x96, 0x0f, 0xc2, 0x0b, 0xde, 0x67, 0x4d, 0x1e, 0x9e, 0xf9, 0x3d, 0x8d, 0xe1, 0x31, 0x83, 0xb4, 0x60, 0x71, 0x2f, 0x1c, 0xf2, 0x33, 0xd6, 0xe4, 0xe1, 0x89, 0xdf,
0x9a, 0x5b, 0xb7, 0xea, 0xd5, 0x4d, 0x67, 0xbe, 0xb1, 0x34, 0xd2, 0x9d, 0x92, 0x73, 0xbe, 0x03, 0xa3, 0xb9, 0x55, 0xab, 0x5e, 0x5d, 0x77, 0x66, 0x1b, 0x4b, 0x23, 0xdd, 0x09, 0x39, 0xe7, 0x07,
0xba, 0xeb, 0x8b, 0x0e, 0x0f, 0x43, 0xd6, 0x89, 0x9d, 0xc9, 0x74, 0x7a, 0x7a, 0x4f, 0xb9, 0x6b, 0xa0, 0xdb, 0xbe, 0xe8, 0xf0, 0x30, 0x64, 0x9d, 0xd8, 0x99, 0x4c, 0xa7, 0x27, 0xf7, 0x94, 0xbb,
0x7b, 0x72, 0x1e, 0xc1, 0xc3, 0x39, 0xba, 0x74, 0x58, 0x9c, 0xdf, 0xc3, 0xf2, 0x8e, 0xda, 0x5b, 0xb2, 0x27, 0xe7, 0x21, 0x3c, 0x98, 0xa1, 0x4b, 0x87, 0xc5, 0xf9, 0x03, 0x2c, 0x6e, 0xa9, 0xbd,
0xb6, 0xf2, 0x6f, 0xa0, 0x74, 0x34, 0x94, 0x3e, 0x0f, 0xc5, 0x62, 0x6f, 0x50, 0x8d, 0x41, 0xba, 0x65, 0x2b, 0xff, 0x0e, 0x4a, 0x07, 0x7d, 0xe9, 0xf3, 0x50, 0xcc, 0xf7, 0x06, 0xd5, 0x18, 0xa4,
0xb1, 0x88, 0xf3, 0xf7, 0x65, 0x63, 0xc0, 0x30, 0xc8, 0x3a, 0x54, 0x9b, 0x3c, 0x94, 0xec, 0x4a, 0x1b, 0x8b, 0x38, 0xff, 0x59, 0x34, 0x06, 0x0c, 0x83, 0xac, 0x42, 0xb5, 0xc9, 0x43, 0xc9, 0x2e,
0x1e, 0x7b, 0xf2, 0xdc, 0x18, 0x4a, 0xb3, 0xc8, 0x67, 0xb0, 0xb2, 0xcb, 0x3b, 0x7d, 0x16, 0x9d, 0xe5, 0xa1, 0x27, 0x4f, 0x8d, 0xa1, 0x34, 0x8b, 0x7c, 0x0e, 0x4b, 0xdb, 0xbc, 0x73, 0xc6, 0xa2,
0xf9, 0x01, 0x3b, 0xf4, 0x06, 0xcc, 0xb8, 0x74, 0x8d, 0x4b, 0xbe, 0x55, 0x5e, 0xfb, 0xa1, 0x6c, 0x13, 0x3f, 0x60, 0xfb, 0xde, 0x39, 0x33, 0x2e, 0x5d, 0xe1, 0x92, 0xef, 0x95, 0xd7, 0x7e, 0x28,
0x8d, 0xc2, 0x0e, 0xcd, 0xe3, 0xd6, 0x9e, 0x66, 0x9d, 0xaa, 0x81, 0xb9, 0x13, 0x09, 0xf2, 0x3b, 0x5b, 0x83, 0xb0, 0x43, 0xf3, 0xb8, 0xb5, 0x27, 0x59, 0xa7, 0x6a, 0x60, 0xee, 0x58, 0x82, 0xfc,
0xa8, 0x29, 0x35, 0x5d, 0x63, 0x5a, 0xd0, 0x02, 0x26, 0xc6, 0xeb, 0x9b, 0xbd, 0x6b, 0x4c, 0xc9, 0x1e, 0x6a, 0x4a, 0x4d, 0xd7, 0x98, 0x16, 0xb4, 0x80, 0x89, 0xf1, 0xea, 0x7a, 0xef, 0x1a, 0x13,
0xed, 0x85, 0x32, 0x1a, 0xbb, 0xd3, 0xba, 0xc8, 0x1a, 0x2c, 0x6d, 0x07, 0x01, 0xbf, 0xa4, 0x4b, 0x72, 0x3b, 0xa1, 0x8c, 0x46, 0xee, 0xa4, 0x2e, 0xb2, 0x02, 0x0b, 0x9b, 0x41, 0xc0, 0x2f, 0xe8,
0xeb, 0xf9, 0x7a, 0xc5, 0xd5, 0x04, 0xf9, 0x25, 0x94, 0xb6, 0xa5, 0x64, 0x42, 0x0a, 0x5a, 0x44, 0xc2, 0x6a, 0xbe, 0x5e, 0x71, 0x35, 0x41, 0xbe, 0x86, 0xd2, 0xa6, 0x94, 0x4c, 0x48, 0x41, 0x8b,
0x63, 0x8f, 0xe7, 0x1b, 0xd3, 0x20, 0x37, 0x06, 0x93, 0x23, 0xa8, 0xa0, 0xfd, 0xed, 0xa8, 0x27, 0x68, 0xec, 0xd1, 0x6c, 0x63, 0x1a, 0xe4, 0xc6, 0x60, 0x72, 0x00, 0x15, 0xb4, 0xbf, 0x19, 0xf5,
0x68, 0x09, 0x25, 0xbf, 0xb8, 0xc5, 0x36, 0x13, 0x19, 0xbd, 0xc5, 0x89, 0x0e, 0xb2, 0x07, 0x95, 0x04, 0x2d, 0xa1, 0xe4, 0x97, 0x37, 0xd8, 0x66, 0x22, 0xa3, 0xb7, 0x38, 0xd6, 0x41, 0x76, 0xa0,
0xa6, 0xd7, 0x39, 0x67, 0xad, 0x88, 0x0f, 0x68, 0x19, 0x15, 0xfe, 0x74, 0xbe, 0x42, 0x84, 0x19, 0xd2, 0xf4, 0x3a, 0xa7, 0xac, 0x15, 0xf1, 0x73, 0x5a, 0x46, 0x85, 0x3f, 0x9f, 0xad, 0x10, 0x61,
0x85, 0x46, 0x4d, 0x22, 0x49, 0xb6, 0xa1, 0x84, 0xc4, 0x09, 0xa7, 0x95, 0xbb, 0x29, 0x89, 0xe5, 0x46, 0xa1, 0x51, 0x93, 0x48, 0x92, 0x4d, 0x28, 0x21, 0x71, 0xc4, 0x69, 0xe5, 0x76, 0x4a, 0x62,
0x88, 0x03, 0xcb, 0xcd, 0x5e, 0xc4, 0x47, 0xc3, 0x63, 0x2f, 0x62, 0xa1, 0xa4, 0x80, 0x47, 0x3d, 0x39, 0xe2, 0xc0, 0x62, 0xb3, 0x17, 0xf1, 0x41, 0xff, 0xd0, 0x8b, 0x58, 0x28, 0x29, 0xe0, 0x51,
0xc5, 0x23, 0x6f, 0xa1, 0xb4, 0x77, 0x35, 0xe4, 0x91, 0x14, 0xb4, 0xba, 0xe8, 0xf2, 0x6a, 0x90, 0x4f, 0xf0, 0xc8, 0x1b, 0x28, 0xed, 0x5c, 0xf6, 0x79, 0x24, 0x05, 0xad, 0xce, 0xbb, 0xbc, 0x1a,
0x31, 0x60, 0x24, 0xc8, 0x13, 0x80, 0xbd, 0x2b, 0x19, 0x79, 0xfb, 0x5c, 0x85, 0x7d, 0x19, 0x8f, 0x64, 0x0c, 0x18, 0x09, 0xf2, 0x18, 0x60, 0xe7, 0x52, 0x46, 0xde, 0x2e, 0x57, 0x61, 0x5f, 0xc4,
0x23, 0xc5, 0x21, 0x2d, 0x28, 0xbe, 0xf3, 0x4e, 0x59, 0x20, 0x68, 0x0d, 0x75, 0x37, 0x6e, 0x11, 0xe3, 0x48, 0x71, 0x48, 0x0b, 0x8a, 0x6f, 0xbd, 0x63, 0x16, 0x08, 0x5a, 0x43, 0xdd, 0x8d, 0x1b,
0x58, 0x2d, 0xa0, 0x0d, 0x19, 0x69, 0x95, 0xd7, 0x87, 0x4c, 0x5e, 0xf2, 0xa8, 0xff, 0x9e, 0x77, 0x04, 0x56, 0x0b, 0x68, 0x43, 0x46, 0x5a, 0xe5, 0xf5, 0x3e, 0x93, 0x17, 0x3c, 0x3a, 0x7b, 0xc7,
0x19, 0x5d, 0xd1, 0x79, 0x9d, 0x62, 0x91, 0x17, 0x50, 0x3b, 0xe4, 0x3a, 0x78, 0x7e, 0x20, 0x59, 0xbb, 0x8c, 0x2e, 0xe9, 0xbc, 0x4e, 0xb1, 0xc8, 0x73, 0xa8, 0xed, 0x73, 0x1d, 0x3c, 0x3f, 0x90,
0x44, 0x3f, 0xc1, 0xcd, 0x4c, 0x33, 0xf1, 0x2e, 0x07, 0x9e, 0x3c, 0xe3, 0xd1, 0x40, 0xd0, 0x55, 0x2c, 0xa2, 0x77, 0x70, 0x33, 0x93, 0x4c, 0xbc, 0xcb, 0x81, 0x27, 0x4f, 0x78, 0x74, 0x2e, 0xe8,
0x44, 0x4c, 0x18, 0x2a, 0x83, 0xda, 0xac, 0x13, 0x31, 0x29, 0xe8, 0xbd, 0x45, 0x19, 0xa4, 0x41, 0x32, 0x22, 0xc6, 0x0c, 0x95, 0x41, 0x6d, 0xd6, 0x89, 0x98, 0x14, 0xf4, 0xee, 0xbc, 0x0c, 0xd2,
0x6e, 0x0c, 0x26, 0x14, 0x4a, 0xed, 0xf3, 0x41, 0xdb, 0xff, 0x23, 0xa3, 0x64, 0xdd, 0xaa, 0xe7, 0x20, 0x37, 0x06, 0x13, 0x0a, 0xa5, 0xf6, 0xe9, 0x79, 0xdb, 0xff, 0x13, 0xa3, 0x64, 0xd5, 0xaa,
0xdd, 0x98, 0x24, 0xaf, 0x20, 0xdf, 0x6e, 0xef, 0xd3, 0x1f, 0xa3, 0xb6, 0x87, 0x19, 0xda, 0xda, 0xe7, 0xdd, 0x98, 0x24, 0x2f, 0x21, 0xdf, 0x6e, 0xef, 0xd2, 0x9f, 0xa2, 0xb6, 0x07, 0x19, 0xda,
0xfb, 0xae, 0x42, 0x11, 0x02, 0x85, 0x13, 0xaf, 0x27, 0xe8, 0x1a, 0xee, 0x0b, 0xd7, 0xe4, 0x01, 0xda, 0xbb, 0xae, 0x42, 0x11, 0x02, 0x85, 0x23, 0xaf, 0x27, 0xe8, 0x0a, 0xee, 0x0b, 0xd7, 0xe4,
0x14, 0x4f, 0xbc, 0xa8, 0xc7, 0x24, 0xbd, 0x8f, 0x3e, 0x1b, 0x8a, 0xbc, 0x81, 0xd2, 0x87, 0xc0, 0x3e, 0x14, 0x8f, 0xbc, 0xa8, 0xc7, 0x24, 0xbd, 0x87, 0x3e, 0x1b, 0x8a, 0xbc, 0x86, 0xd2, 0xfb,
0x1f, 0xf8, 0x52, 0xd0, 0x07, 0x8b, 0x2e, 0xa7, 0x06, 0x1d, 0x0d, 0xa5, 0x1b, 0xe3, 0xd5, 0x6e, 0xc0, 0x3f, 0xf7, 0xa5, 0xa0, 0xf7, 0xe7, 0x5d, 0x4e, 0x0d, 0x3a, 0xe8, 0x4b, 0x37, 0xc6, 0xab,
0x31, 0xde, 0x2c, 0xa2, 0x3f, 0x41, 0x9d, 0x31, 0xa9, 0xbe, 0x98, 0x70, 0x51, 0xba, 0x6e, 0xd5, 0xdd, 0x62, 0xbc, 0x59, 0x44, 0x7f, 0x86, 0x3a, 0x63, 0x52, 0x7d, 0x31, 0xe1, 0xa2, 0x74, 0xd5,
0xcb, 0x6e, 0x4c, 0xaa, 0xad, 0x1d, 0x8f, 0x82, 0x80, 0x3e, 0x44, 0x36, 0xae, 0xf5, 0xd9, 0xab, 0xaa, 0x97, 0xdd, 0x98, 0x54, 0x5b, 0x3b, 0x1c, 0x04, 0x01, 0x7d, 0x80, 0x6c, 0x5c, 0xeb, 0xb3,
0x34, 0x38, 0x1e, 0x89, 0x73, 0x6a, 0xe3, 0x97, 0x14, 0x67, 0xf2, 0xfd, 0x1d, 0xf7, 0xba, 0xf4, 0x57, 0x69, 0x70, 0x38, 0x10, 0xa7, 0xd4, 0xc6, 0x2f, 0x29, 0xce, 0xf8, 0xfb, 0x5b, 0xee, 0x75,
0x51, 0xfa, 0xbb, 0xe2, 0x90, 0x03, 0x58, 0x6e, 0x63, 0x5b, 0x3a, 0xc6, 0x66, 0x44, 0x1f, 0xa3, 0xe9, 0xc3, 0xf4, 0x77, 0xc5, 0x21, 0x7b, 0xb0, 0xd8, 0xc6, 0xb6, 0x74, 0x88, 0xcd, 0x88, 0x3e,
0x1f, 0x2f, 0x1b, 0xaa, 0x73, 0x35, 0xe2, 0xce, 0xa5, 0x7c, 0x48, 0x37, 0xaf, 0x86, 0x06, 0xbb, 0x42, 0x3f, 0x5e, 0x34, 0x54, 0xe7, 0x6a, 0xc4, 0x9d, 0x4b, 0xf9, 0x90, 0x6e, 0x5e, 0x0d, 0x0d,
0x53, 0xa2, 0x71, 0x5d, 0xfd, 0x74, 0x52, 0x57, 0x6d, 0x28, 0xff, 0x5a, 0x25, 0xb9, 0x62, 0x3f, 0x76, 0x27, 0x44, 0xe3, 0xba, 0xfa, 0xd9, 0xb8, 0xae, 0xda, 0x50, 0xfe, 0x8d, 0x4a, 0x72, 0xc5,
0x41, 0x76, 0x42, 0xab, 0x64, 0xda, 0x0e, 0x43, 0x2e, 0x3d, 0x5d, 0x77, 0x9f, 0x62, 0xb8, 0xd3, 0x7e, 0x8c, 0xec, 0x84, 0x56, 0xc9, 0xb4, 0x19, 0x86, 0x5c, 0x7a, 0xba, 0xee, 0x3e, 0xc1, 0x70,
0x2c, 0xfb, 0x57, 0x40, 0x66, 0xab, 0x90, 0xb2, 0xd2, 0x67, 0xe3, 0xb8, 0x7a, 0xf7, 0xd9, 0x58, 0xa7, 0x59, 0xe4, 0x6b, 0xb8, 0xff, 0xd1, 0x97, 0xa7, 0x87, 0x11, 0x1f, 0xb2, 0xd0, 0x0b, 0x3b,
0x15, 0xa2, 0x0b, 0x2f, 0x18, 0xc5, 0x35, 0x54, 0x13, 0x5f, 0xe7, 0xbe, 0xb2, 0xec, 0x6f, 0x60, 0x2c, 0xae, 0xe8, 0x74, 0x15, 0xdd, 0xc8, 0xf8, 0x6a, 0xff, 0x1a, 0xc8, 0x74, 0xf5, 0x52, 0xbb,
0x65, 0xba, 0x40, 0xdc, 0x49, 0xfa, 0x0d, 0x54, 0x53, 0xb7, 0xe0, 0x2e, 0xa2, 0xce, 0xbf, 0x2d, 0x3b, 0x63, 0xa3, 0xb8, 0xea, 0x9f, 0xb1, 0x91, 0x2a, 0x60, 0x43, 0x2f, 0x18, 0xc4, 0xb5, 0x57,
0xa8, 0xa6, 0xae, 0x2a, 0x26, 0xd5, 0x78, 0xc8, 0x8c, 0x30, 0xae, 0xc9, 0x0e, 0x2c, 0x6d, 0x4b, 0x13, 0xdf, 0xe6, 0xbe, 0xb1, 0xec, 0xef, 0x60, 0x69, 0xb2, 0xb0, 0xdc, 0x4a, 0xfa, 0x35, 0x54,
0x19, 0xa9, 0x96, 0xa3, 0xf2, 0xf2, 0xe7, 0x37, 0x5e, 0xf8, 0x06, 0xc2, 0xf5, 0x95, 0xd4, 0xa2, 0x53, 0xb7, 0xe7, 0x36, 0xa2, 0xce, 0xbf, 0x2d, 0xa8, 0xa6, 0xae, 0x38, 0x26, 0xe3, 0xa8, 0xcf,
0x2a, 0x88, 0xbb, 0x4c, 0x48, 0x3f, 0xc4, 0x90, 0x61, 0x87, 0xa8, 0xb8, 0x69, 0x96, 0xfd, 0x15, 0x8c, 0x30, 0xae, 0xc9, 0x16, 0x2c, 0x6c, 0x4a, 0x19, 0xa9, 0x56, 0xa5, 0xf2, 0xf9, 0x97, 0xd7,
0xc0, 0x44, 0xec, 0x4e, 0x3e, 0xfc, 0xd3, 0x82, 0x7b, 0x33, 0x55, 0x6d, 0xae, 0x27, 0xfb, 0xd3, 0x16, 0x8a, 0x06, 0xc2, 0xf5, 0x55, 0xd6, 0xa2, 0x2a, 0xf8, 0xdb, 0x4c, 0x48, 0x3f, 0xc4, 0x50,
0x9e, 0x6c, 0xde, 0xb2, 0x42, 0xce, 0xfa, 0xf3, 0x7f, 0xec, 0xf6, 0x10, 0x8a, 0xba, 0x95, 0xcc, 0x63, 0x67, 0xa9, 0xb8, 0x69, 0x96, 0xfd, 0x0d, 0xc0, 0x58, 0xec, 0x56, 0x3e, 0xfc, 0xd3, 0x82,
0xdd, 0xa1, 0x0d, 0xe5, 0x5d, 0x5f, 0x78, 0xa7, 0x01, 0xeb, 0xa2, 0x68, 0xd9, 0x4d, 0x68, 0xec, 0xbb, 0x53, 0xd5, 0x70, 0xa6, 0x27, 0xbb, 0x93, 0x9e, 0xac, 0xdf, 0xb0, 0xb2, 0x4e, 0xfb, 0xf3,
0x63, 0xb8, 0x7b, 0x1d, 0x3d, 0x4d, 0x38, 0xba, 0x66, 0x90, 0x15, 0xc8, 0x25, 0x33, 0x50, 0xee, 0x23, 0x76, 0xbb, 0x0f, 0x45, 0xdd, 0x82, 0x66, 0xee, 0xd0, 0x86, 0xf2, 0xb6, 0x2f, 0xbc, 0xe3,
0x60, 0x57, 0x81, 0x55, 0x03, 0xd7, 0xae, 0x56, 0x5c, 0x4d, 0x38, 0x2d, 0x28, 0xea, 0x2a, 0x34, 0x80, 0x75, 0x51, 0xb4, 0xec, 0x26, 0x34, 0xf6, 0x3f, 0xdc, 0xbd, 0x8e, 0x9e, 0x26, 0x1c, 0x5d,
0x83, 0xb7, 0xa1, 0xdc, 0xf2, 0x03, 0x86, 0x73, 0x80, 0xde, 0x73, 0x42, 0x2b, 0xf7, 0xf6, 0xc2, 0x6b, 0xc8, 0x12, 0xe4, 0x92, 0xd9, 0x29, 0xb7, 0xb7, 0xad, 0xc0, 0xaa, 0xf1, 0x6b, 0x57, 0x2b,
0x0b, 0x63, 0x56, 0x2d, 0x9d, 0xad, 0x54, 0xbb, 0x57, 0x7e, 0xe0, 0x64, 0x60, 0xfc, 0xc0, 0x79, 0xae, 0x26, 0x9c, 0x16, 0x14, 0x75, 0xf5, 0x9a, 0xc2, 0xdb, 0x50, 0x6e, 0xf9, 0x01, 0xc3, 0xf9,
0xe0, 0x01, 0x14, 0x5b, 0x3c, 0x1a, 0x78, 0xd2, 0x28, 0x33, 0x94, 0xe3, 0xc0, 0xca, 0x41, 0x28, 0x41, 0xef, 0x39, 0xa1, 0x95, 0x7b, 0x3b, 0xe1, 0xd0, 0x98, 0x55, 0x4b, 0x67, 0x23, 0x35, 0x26,
0x86, 0xac, 0x23, 0xb3, 0xc7, 0xc6, 0x23, 0xf8, 0x24, 0xc1, 0x98, 0x81, 0x31, 0x35, 0xf7, 0x58, 0x28, 0x3f, 0x70, 0xa2, 0x30, 0x7e, 0xe0, 0x1c, 0x71, 0x1f, 0x8a, 0x2d, 0x1e, 0x9d, 0x7b, 0xd2,
0x77, 0x9f, 0x7b, 0xfe, 0x61, 0x41, 0x25, 0xa9, 0x6c, 0xa4, 0x09, 0x45, 0x3c, 0x8d, 0x78, 0xfa, 0x28, 0x33, 0x94, 0xe3, 0xc0, 0xd2, 0x5e, 0x28, 0xfa, 0xac, 0x23, 0xb3, 0xc7, 0xcd, 0x03, 0xb8,
0x7c, 0x75, 0x43, 0x29, 0x6c, 0x7c, 0x44, 0xb4, 0xe9, 0x30, 0x5a, 0xd4, 0xfe, 0x1e, 0xaa, 0x29, 0x93, 0x60, 0xcc, 0xa0, 0x99, 0x9a, 0x97, 0xac, 0xdb, 0xcf, 0x4b, 0xff, 0xb0, 0xa0, 0x92, 0x54,
0xf6, 0x9c, 0x04, 0xd8, 0x4c, 0x27, 0x40, 0x66, 0x6b, 0xd0, 0x46, 0xd2, 0xe9, 0xb1, 0x0b, 0x45, 0x44, 0xd2, 0x84, 0x22, 0x9e, 0x46, 0x3c, 0xb5, 0xbe, 0xbc, 0xa6, 0x84, 0x36, 0x3e, 0x20, 0xda,
0xcd, 0x9c, 0x1b, 0x56, 0x02, 0x85, 0x7d, 0x2f, 0xd2, 0xa9, 0x91, 0x77, 0x71, 0xad, 0x78, 0x6d, 0x74, 0x26, 0x2d, 0x6a, 0x7f, 0x84, 0x6a, 0x8a, 0x3d, 0x23, 0x01, 0xd6, 0xd3, 0x09, 0x90, 0xd9,
0x7e, 0x26, 0xf1, 0x78, 0xf2, 0x2e, 0xae, 0x9d, 0x7f, 0x59, 0x50, 0x33, 0xa3, 0xa4, 0x89, 0x20, 0x52, 0xb4, 0x91, 0x74, 0x7a, 0x6c, 0x43, 0x51, 0x33, 0x67, 0x86, 0x95, 0x40, 0x61, 0xd7, 0x8b,
0x83, 0x55, 0x7d, 0x43, 0x59, 0x14, 0xf3, 0x8c, 0xff, 0x6f, 0x16, 0x84, 0x32, 0x86, 0x36, 0xae, 0x74, 0x6a, 0xe4, 0x5d, 0x5c, 0x2b, 0x5e, 0x9b, 0x9f, 0x48, 0x3c, 0x9e, 0xbc, 0x8b, 0x6b, 0xe7,
0xcb, 0xea, 0x68, 0xcc, 0xa8, 0xb4, 0x9b, 0x70, 0x7f, 0x2e, 0xf4, 0x4e, 0x57, 0xe4, 0x25, 0xdc, 0x5f, 0x16, 0xd4, 0xcc, 0x08, 0x6a, 0x22, 0xc8, 0x60, 0x59, 0xdf, 0x50, 0x16, 0x25, 0x55, 0x4d,
0x9b, 0x0c, 0xc9, 0xd9, 0x79, 0xb2, 0x06, 0x24, 0x0d, 0x33, 0x43, 0xf4, 0x53, 0xa8, 0xaa, 0x47, 0xfb, 0xff, 0x7a, 0x4e, 0x28, 0x63, 0x68, 0xe3, 0xaa, 0xac, 0x8e, 0xc6, 0x94, 0x4a, 0xbb, 0x09,
0x47, 0xb6, 0x98, 0x03, 0xcb, 0x1a, 0x60, 0x22, 0x43, 0xa0, 0xd0, 0x67, 0x63, 0x9d, 0x0d, 0x15, 0xf7, 0x66, 0x42, 0x6f, 0x75, 0x45, 0x5e, 0xc0, 0xdd, 0xf1, 0x70, 0x9d, 0x9d, 0x27, 0x2b, 0x40,
0x17, 0xd7, 0xce, 0xdf, 0x2c, 0xf5, 0x76, 0x18, 0x8e, 0xe4, 0x7b, 0x26, 0x84, 0xd7, 0x53, 0x09, 0xd2, 0x30, 0x33, 0x7c, 0x3f, 0x81, 0xaa, 0x7a, 0xac, 0x64, 0x8b, 0x39, 0xb0, 0xa8, 0x01, 0x26,
0x58, 0x38, 0x08, 0x7d, 0x69, 0xb2, 0xef, 0xb3, 0xac, 0x37, 0xc4, 0x70, 0x24, 0x15, 0xcc, 0x48, 0x32, 0x04, 0x0a, 0x67, 0x6c, 0xa4, 0xb3, 0xa1, 0xe2, 0xe2, 0xda, 0xf9, 0xbb, 0xa5, 0xde, 0x1c,
0xed, 0xff, 0xc8, 0x45, 0x29, 0xb2, 0x05, 0x85, 0x5d, 0x4f, 0x7a, 0x26, 0x17, 0x32, 0x26, 0x26, 0xfd, 0x81, 0x7c, 0xc7, 0x84, 0xf0, 0x7a, 0x2a, 0x01, 0x0b, 0x7b, 0xa1, 0x2f, 0x4d, 0xf6, 0x7d,
0x85, 0x48, 0x09, 0x2a, 0x72, 0xa7, 0xa4, 0x1e, 0x4a, 0xc3, 0x91, 0x74, 0x5e, 0xc0, 0xea, 0x75, 0x9e, 0xf5, 0xf6, 0xe8, 0x0f, 0xa4, 0x82, 0x19, 0xa9, 0xdd, 0x9f, 0xb8, 0x28, 0x45, 0x36, 0xa0,
0xed, 0x73, 0x5c, 0xfb, 0x12, 0xaa, 0x29, 0x2d, 0x78, 0x6f, 0x8f, 0x5a, 0x08, 0x28, 0xbb, 0x6a, 0xb0, 0xed, 0x49, 0xcf, 0xe4, 0x42, 0xc6, 0xa4, 0xa5, 0x10, 0x29, 0x41, 0x45, 0x6e, 0x95, 0xd4,
0xa9, 0x7c, 0x4d, 0x36, 0xb2, 0xac, 0x6d, 0x38, 0x9f, 0x40, 0x0d, 0x55, 0x27, 0x11, 0xfc, 0x53, 0x03, 0xab, 0x3f, 0x90, 0xce, 0x73, 0x58, 0xbe, 0xaa, 0x7d, 0x86, 0x6b, 0x5f, 0x41, 0x35, 0xa5,
0x0e, 0x4a, 0xb1, 0x8a, 0xad, 0x29, 0xbf, 0x9f, 0x65, 0xf9, 0x3d, 0xeb, 0xf2, 0x6b, 0x28, 0xa8, 0x05, 0xef, 0xed, 0x41, 0x0b, 0x01, 0x65, 0x57, 0x2d, 0x95, 0xaf, 0xc9, 0x46, 0x16, 0xb5, 0x0d,
0xfa, 0x61, 0x5c, 0xce, 0x18, 0x37, 0x5a, 0xdd, 0x94, 0x98, 0x82, 0x93, 0x6f, 0xa1, 0xe8, 0x32, 0xe7, 0x0e, 0xd4, 0x50, 0x75, 0x12, 0xc1, 0x3f, 0xe7, 0xa0, 0x14, 0xab, 0xd8, 0x98, 0xf0, 0xfb,
0xa1, 0x46, 0x23, 0xfd, 0x88, 0x78, 0x3e, 0x5f, 0x50, 0x63, 0x26, 0xc2, 0x46, 0x48, 0x89, 0xb7, 0x69, 0x96, 0xdf, 0xd3, 0x2e, 0xbf, 0x82, 0x82, 0xaa, 0x1f, 0xc6, 0xe5, 0x8c, 0x31, 0xa5, 0xd5,
0xfd, 0x5e, 0xe8, 0x05, 0xb4, 0xb0, 0x48, 0x5c, 0x63, 0x52, 0xe2, 0x9a, 0x31, 0x09, 0xf7, 0x5f, 0x4d, 0x89, 0x29, 0x38, 0xf9, 0x1e, 0x8a, 0x2e, 0x13, 0x6a, 0xa4, 0xd2, 0x8f, 0x8f, 0x67, 0xb3,
0x2c, 0xa8, 0x2e, 0x0c, 0xf5, 0xe2, 0x67, 0xde, 0xcc, 0xd3, 0x33, 0xff, 0x3f, 0x3e, 0x3d, 0xff, 0x05, 0x35, 0x66, 0x2c, 0x6c, 0x84, 0x94, 0x78, 0xdb, 0xef, 0x85, 0x5e, 0x40, 0x0b, 0xf3, 0xc4,
0x9c, 0x9b, 0x56, 0x84, 0x53, 0x92, 0xba, 0x4f, 0x43, 0xee, 0x87, 0xd2, 0xa4, 0x6c, 0x8a, 0xa3, 0x35, 0x26, 0x25, 0xae, 0x19, 0xe3, 0x70, 0xff, 0xd5, 0x82, 0xea, 0xdc, 0x50, 0xcf, 0x7f, 0x1e,
0x36, 0xda, 0x1c, 0x74, 0x4d, 0xd1, 0x57, 0x4b, 0x75, 0xcd, 0x0e, 0xb9, 0xe2, 0x55, 0x31, 0x0d, 0x4e, 0x3d, 0x59, 0xf3, 0xff, 0xe7, 0x93, 0xf5, 0x2f, 0xb9, 0x49, 0x45, 0x38, 0x5d, 0xa9, 0xfb,
0x34, 0x31, 0x29, 0xe9, 0x79, 0x53, 0xd2, 0x55, 0x6a, 0x7c, 0x10, 0x2c, 0xc2, 0xc0, 0x55, 0x5c, 0xd4, 0xe7, 0x7e, 0x28, 0x4d, 0xca, 0xa6, 0x38, 0x6a, 0xa3, 0xcd, 0xf3, 0xae, 0x29, 0xfa, 0x6a,
0x5c, 0xab, 0x2a, 0x7e, 0xc8, 0x91, 0xbb, 0x84, 0xc2, 0x86, 0x42, 0x2b, 0x97, 0x5d, 0x5a, 0xd4, 0xa9, 0xae, 0xd9, 0x3e, 0x57, 0xbc, 0x2a, 0xa6, 0x81, 0x26, 0xc6, 0x25, 0x3d, 0x6f, 0x4a, 0xba,
0xe1, 0x68, 0x5e, 0xc6, 0x56, 0x2e, 0xbb, 0xb4, 0x94, 0x58, 0xb9, 0x44, 0x2b, 0x27, 0x72, 0x4c, 0x4a, 0x8d, 0xf7, 0x82, 0x45, 0x18, 0xb8, 0x8a, 0x8b, 0x6b, 0x55, 0xc5, 0xf7, 0x39, 0x72, 0x17,
0xcb, 0x3a, 0x01, 0x4f, 0xe4, 0x58, 0xb5, 0x19, 0x97, 0x07, 0xc1, 0xa9, 0xd7, 0xe9, 0xd3, 0x8a, 0x50, 0xd8, 0x50, 0x68, 0xe5, 0xa2, 0x4b, 0x8b, 0x3a, 0x1c, 0xcd, 0x8b, 0xd8, 0xca, 0x45, 0x97,
0xee, 0x6f, 0x31, 0xad, 0xe6, 0x49, 0x15, 0x73, 0xdf, 0x0b, 0xf0, 0xe5, 0x51, 0x76, 0x63, 0xd2, 0x96, 0x12, 0x2b, 0x17, 0x68, 0xe5, 0x48, 0x8e, 0x68, 0x59, 0x27, 0xe0, 0x91, 0x1c, 0xa9, 0x36,
0xd9, 0x86, 0x4a, 0x92, 0x2a, 0xaa, 0x73, 0xb5, 0xba, 0x78, 0x14, 0x35, 0x37, 0xd7, 0xea, 0xc6, 0xe3, 0xf2, 0x20, 0x38, 0xf6, 0x3a, 0x67, 0xb4, 0xa2, 0xfb, 0x5b, 0x4c, 0xab, 0x39, 0x54, 0xc5,
0x59, 0x9e, 0x9b, 0xcd, 0xf2, 0x7c, 0x2a, 0xcb, 0xb7, 0xa0, 0x36, 0x95, 0x34, 0x0a, 0xe4, 0xf2, 0xdc, 0xf7, 0x02, 0x7c, 0xb1, 0x94, 0xdd, 0x98, 0x74, 0x36, 0xa1, 0x92, 0xa4, 0x8a, 0xea, 0x5c,
0x4b, 0x61, 0x14, 0xe1, 0x5a, 0xf1, 0x9a, 0x3c, 0xd0, 0x6f, 0xeb, 0x9a, 0x8b, 0x6b, 0xe7, 0x39, 0xad, 0x2e, 0x1e, 0x45, 0xcd, 0xcd, 0xb5, 0xba, 0x71, 0x96, 0xe7, 0xa6, 0xb3, 0x3c, 0x9f, 0xca,
0xd4, 0xa6, 0xd2, 0x65, 0x5e, 0x5d, 0x76, 0x9e, 0x41, 0xad, 0x2d, 0x3d, 0x39, 0x5a, 0xf0, 0x67, 0xf2, 0x0d, 0xa8, 0x4d, 0x24, 0x8d, 0x02, 0xb9, 0xfc, 0x42, 0x18, 0x45, 0xb8, 0x56, 0xbc, 0x26,
0xc8, 0x7f, 0x2c, 0x58, 0x89, 0x31, 0xa6, 0xf2, 0xfc, 0x02, 0xca, 0x17, 0x2c, 0x92, 0xec, 0x2a, 0x0f, 0xf4, 0x9b, 0xbc, 0xe6, 0xe2, 0xda, 0x79, 0x06, 0xb5, 0x89, 0x74, 0x99, 0x55, 0x97, 0x9d,
0xe9, 0x45, 0x74, 0x76, 0x9c, 0xfd, 0x88, 0x08, 0x37, 0x41, 0x92, 0xaf, 0xa1, 0x2c, 0x50, 0x0f, 0xa7, 0x50, 0x6b, 0x4b, 0x4f, 0x0e, 0xe6, 0xfc, 0x89, 0xf2, 0x5f, 0x0b, 0x96, 0x62, 0x8c, 0xa9,
0x8b, 0xe7, 0x98, 0x27, 0x59, 0x52, 0xc6, 0x5e, 0x82, 0x27, 0x1b, 0x50, 0x08, 0x78, 0x4f, 0xe0, 0x3c, 0xbf, 0x82, 0xf2, 0x90, 0x45, 0x92, 0x5d, 0x26, 0xbd, 0x88, 0x4e, 0x8f, 0xc1, 0x1f, 0x10,
0xb9, 0x57, 0x37, 0x1f, 0x65, 0xc9, 0xbd, 0xe3, 0x3d, 0x17, 0x81, 0xe4, 0x2d, 0x94, 0x2f, 0xbd, 0xe1, 0x26, 0x48, 0xf2, 0x2d, 0x94, 0x05, 0xea, 0x61, 0xf1, 0x1c, 0xf3, 0x38, 0x4b, 0xca, 0xd8,
0x28, 0xf4, 0xc3, 0x5e, 0xfc, 0x26, 0x7f, 0x9a, 0x25, 0xf4, 0xbd, 0xc6, 0xb9, 0x89, 0x80, 0x53, 0x4b, 0xf0, 0x64, 0x0d, 0x0a, 0x01, 0xef, 0x09, 0x3c, 0xf7, 0xea, 0xfa, 0xc3, 0x2c, 0xb9, 0xb7,
0x53, 0x97, 0xe8, 0x8c, 0x9b, 0x98, 0x38, 0xbf, 0x51, 0xb9, 0xac, 0x48, 0xe3, 0xfe, 0x01, 0xd4, 0xbc, 0xe7, 0x22, 0x90, 0xbc, 0x81, 0xf2, 0x85, 0x17, 0x85, 0x7e, 0xd8, 0x8b, 0xdf, 0xf2, 0x4f,
0xf4, 0x7d, 0xf8, 0xc8, 0x22, 0xa1, 0xa6, 0x42, 0x6b, 0xd1, 0x9d, 0xdd, 0x49, 0x43, 0xdd, 0x69, 0xb2, 0x84, 0x3e, 0x6a, 0x9c, 0x9b, 0x08, 0x38, 0x35, 0x75, 0x89, 0x4e, 0xb8, 0x89, 0x89, 0xf3,
0x49, 0xe7, 0x07, 0xd3, 0xee, 0x62, 0x86, 0xca, 0xa5, 0xa1, 0xd7, 0xe9, 0x7b, 0xbd, 0xf8, 0x9c, 0x5b, 0x95, 0xcb, 0x8a, 0x34, 0xee, 0xef, 0x41, 0x4d, 0xdf, 0x87, 0x0f, 0x2c, 0x12, 0x6a, 0x2a,
0x62, 0x52, 0x7d, 0xb9, 0x30, 0xf6, 0xf4, 0xb5, 0x8d, 0x49, 0x95, 0x9b, 0x11, 0xbb, 0xf0, 0xc5, 0xb4, 0xe6, 0xdd, 0xd9, 0xad, 0x34, 0xd4, 0x9d, 0x94, 0x74, 0x3e, 0x99, 0x76, 0x17, 0x33, 0x54,
0x64, 0x40, 0x4d, 0xe8, 0xcd, 0xbf, 0x96, 0x00, 0x9a, 0xc9, 0x7e, 0xc8, 0x31, 0x2c, 0xa1, 0x3d, 0x2e, 0xf5, 0xbd, 0xce, 0x99, 0xd7, 0x8b, 0xcf, 0x29, 0x26, 0xd5, 0x97, 0xa1, 0xb1, 0xa7, 0xaf,
0xe2, 0x2c, 0x6c, 0x9e, 0xe8, 0xb7, 0xfd, 0xfc, 0x16, 0x0d, 0x96, 0x7c, 0x54, 0xc9, 0x8f, 0x43, 0x6d, 0x4c, 0xaa, 0xdc, 0x8c, 0xd8, 0xd0, 0x17, 0xe3, 0x01, 0x35, 0xa1, 0xd7, 0xff, 0x56, 0x02,
0x0f, 0x79, 0x91, 0x55, 0x26, 0xd2, 0x73, 0x93, 0xfd, 0xf2, 0x06, 0x94, 0xd1, 0xfb, 0x01, 0x8a, 0x68, 0x26, 0xfb, 0x21, 0x87, 0xb0, 0x80, 0xf6, 0x88, 0x33, 0xb7, 0x79, 0xa2, 0xdf, 0xf6, 0xb3,
0x3a, 0x0b, 0x48, 0x56, 0x2d, 0x4c, 0xe7, 0xad, 0xfd, 0x62, 0x31, 0x48, 0x2b, 0xfd, 0xdc, 0x22, 0x1b, 0x34, 0x58, 0xf2, 0x41, 0x25, 0x3f, 0x0e, 0x3d, 0xe4, 0x79, 0x56, 0x99, 0x48, 0xcf, 0x4d,
0xae, 0xa9, 0x94, 0xc4, 0x59, 0xd0, 0x0a, 0xcd, 0x8d, 0xc9, 0x0a, 0xc0, 0x54, 0xd7, 0xa9, 0x5b, 0xf6, 0x8b, 0x6b, 0x50, 0x46, 0xef, 0x7b, 0x28, 0xea, 0x2c, 0x20, 0x59, 0xb5, 0x30, 0x9d, 0xb7,
0xe4, 0x3b, 0x28, 0xea, 0x5a, 0x47, 0x3e, 0x9d, 0x2f, 0x10, 0xeb, 0x5b, 0xfc, 0xb9, 0x6e, 0x7d, 0xf6, 0xf3, 0xf9, 0x20, 0xad, 0xf4, 0x0b, 0x8b, 0xb8, 0xa6, 0x52, 0x12, 0x67, 0x4e, 0x2b, 0x34,
0x6e, 0x91, 0xf7, 0x50, 0x50, 0x4d, 0x9e, 0x64, 0x74, 0xac, 0xd4, 0x84, 0x60, 0x3b, 0x8b, 0x20, 0x37, 0x26, 0x2b, 0x00, 0x13, 0x5d, 0xa7, 0x6e, 0x91, 0x1f, 0xa0, 0xa8, 0x6b, 0x1d, 0xf9, 0x6c,
0x26, 0x8a, 0x3f, 0x00, 0x4c, 0x46, 0x0d, 0x92, 0xf1, 0xcf, 0xca, 0xcc, 0xcc, 0x62, 0xd7, 0x6f, 0xb6, 0x40, 0xac, 0x6f, 0xfe, 0xe7, 0xba, 0xf5, 0x85, 0x45, 0xde, 0x41, 0x41, 0x35, 0x79, 0x92,
0x06, 0x1a, 0x03, 0xef, 0x55, 0x9f, 0x3d, 0xe3, 0x24, 0xb3, 0xc3, 0x26, 0xd7, 0xc8, 0x76, 0x16, 0xd1, 0xb1, 0x52, 0x13, 0x82, 0xed, 0xcc, 0x83, 0x98, 0x28, 0x7e, 0x02, 0x18, 0x8f, 0x1a, 0x24,
0x41, 0x8c, 0xba, 0x73, 0xa8, 0x4d, 0xfd, 0xf3, 0x4a, 0x7e, 0x96, 0xed, 0xe4, 0xf5, 0x3f, 0x72, 0xe3, 0x1f, 0x99, 0xa9, 0x99, 0xc5, 0xae, 0x5f, 0x0f, 0x34, 0x06, 0xde, 0xa9, 0x3e, 0x7b, 0xc2,
0xed, 0x57, 0xb7, 0xc2, 0x1a, 0x4b, 0x32, 0x3d, 0xab, 0x99, 0xcf, 0xa4, 0x71, 0x93, 0xdf, 0xd3, 0x49, 0x66, 0x87, 0x4d, 0xae, 0x91, 0xed, 0xcc, 0x83, 0x18, 0x75, 0xa7, 0x50, 0x9b, 0xf8, 0xc7,
0xff, 0xa2, 0xda, 0x1b, 0xb7, 0xc6, 0x6b, 0xab, 0x3b, 0x85, 0xdf, 0xe6, 0x86, 0xa7, 0xa7, 0x45, 0x96, 0xfc, 0x22, 0xdb, 0xc9, 0xab, 0x7f, 0x00, 0xdb, 0x2f, 0x6f, 0x84, 0x35, 0x96, 0x64, 0x7a,
0xfc, 0x43, 0xfa, 0xcb, 0xff, 0x06, 0x00, 0x00, 0xff, 0xff, 0xe3, 0x77, 0x0e, 0x2f, 0x2e, 0x17, 0x56, 0x33, 0x9f, 0x49, 0xe3, 0x3a, 0xbf, 0x27, 0xff, 0x7d, 0xb5, 0xd7, 0x6e, 0x8c, 0xd7, 0x56,
0x00, 0x00, 0xb7, 0x0a, 0xbf, 0xcb, 0xf5, 0x8f, 0x8f, 0x8b, 0xf8, 0x47, 0xf6, 0x57, 0xff, 0x0b, 0x00, 0x00,
0xff, 0xff, 0xf1, 0x59, 0xad, 0xb5, 0x66, 0x17, 0x00, 0x00,
} }
// Reference imports to suppress errors if they are not otherwise used. // Reference imports to suppress errors if they are not otherwise used.

View File

@ -80,6 +80,7 @@ message BuildOptions {
string Ref = 29; string Ref = 29;
string GroupRef = 30; string GroupRef = 30;
repeated string Annotations = 31; repeated string Annotations = 31;
bool WithProvenanceResponse = 32;
} }
message ExportEntry { message ExportEntry {

View File

@ -13,20 +13,20 @@ Build from a file
### Options ### Options
| Name | Type | Default | Description | | Name | Type | Default | Description |
|:---------------------------------|:--------------|:--------|:-----------------------------------------------------------------------------------------| |:------------------------------------|:--------------|:--------|:-----------------------------------------------------------------------------------------|
| [`--builder`](#builder) | `string` | | Override the configured builder instance | | [`--builder`](#builder) | `string` | | Override the configured builder instance |
| [`-f`](#file), [`--file`](#file) | `stringArray` | | Build definition file | | [`-f`](#file), [`--file`](#file) | `stringArray` | | Build definition file |
| `--load` | | | Shorthand for `--set=*.output=type=docker` | | `--load` | | | Shorthand for `--set=*.output=type=docker` |
| `--metadata-file` | `string` | | Write build result metadata to the file | | [`--metadata-file`](#metadata-file) | `string` | | Write build result metadata to a file |
| [`--no-cache`](#no-cache) | | | Do not use cache when building the image | | [`--no-cache`](#no-cache) | | | Do not use cache when building the image |
| [`--print`](#print) | | | Print the options without building | | [`--print`](#print) | | | Print the options without building |
| [`--progress`](#progress) | `string` | `auto` | Set type of progress output (`auto`, `plain`, `tty`). Use plain to show container output | | [`--progress`](#progress) | `string` | `auto` | Set type of progress output (`auto`, `plain`, `tty`). Use plain to show container output |
| [`--provenance`](#provenance) | `string` | | Shorthand for `--set=*.attest=type=provenance` | | [`--provenance`](#provenance) | `string` | | Shorthand for `--set=*.attest=type=provenance` |
| [`--pull`](#pull) | | | Always attempt to pull all referenced images | | [`--pull`](#pull) | | | Always attempt to pull all referenced images |
| `--push` | | | Shorthand for `--set=*.output=type=registry` | | `--push` | | | Shorthand for `--set=*.output=type=registry` |
| [`--sbom`](#sbom) | `string` | | Shorthand for `--set=*.attest=type=sbom` | | [`--sbom`](#sbom) | `string` | | Shorthand for `--set=*.attest=type=sbom` |
| [`--set`](#set) | `stringArray` | | Override target value (e.g., `targetpattern.key=value`) | | [`--set`](#set) | `stringArray` | | Override target value (e.g., `targetpattern.key=value`) |
<!---MARKER_GEN_END--> <!---MARKER_GEN_END-->
@ -90,6 +90,77 @@ $ docker buildx bake -f docker-bake.dev.hcl db webapp-release
See the [Bake file reference](https://docs.docker.com/build/bake/reference/) See the [Bake file reference](https://docs.docker.com/build/bake/reference/)
for more details. for more details.
### <a name="metadata-file"></a> Write build results metadata to a file (--metadata-file)
Similar to [`buildx build --metadata-file`](buildx_build.md#metadata-file) but
writes a map of results for each target such as:
```hcl
# docker-bake.hcl
group "default" {
targets = ["db", "webapp-dev"]
}
target "db" {
dockerfile = "Dockerfile.db"
tags = ["docker.io/username/db"]
}
target "webapp-dev" {
dockerfile = "Dockerfile.webapp"
tags = ["docker.io/username/webapp"]
}
```
```console
$ docker buildx bake --load --metadata-file metadata.json .
$ cat metadata.json
```
```json
{
"db": {
"buildx.build.provenance": {},
"buildx.build.ref": "mybuilder/mybuilder0/0fjb6ubs52xx3vygf6fgdl611",
"containerimage.config.digest": "sha256:2937f66a9722f7f4a2df583de2f8cb97fc9196059a410e7f00072fc918930e66",
"containerimage.descriptor": {
"annotations": {
"config.digest": "sha256:2937f66a9722f7f4a2df583de2f8cb97fc9196059a410e7f00072fc918930e66",
"org.opencontainers.image.created": "2022-02-08T21:28:03Z"
},
"digest": "sha256:19ffeab6f8bc9293ac2c3fdf94ebe28396254c993aea0b5a542cfb02e0883fa3",
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 506
},
"containerimage.digest": "sha256:19ffeab6f8bc9293ac2c3fdf94ebe28396254c993aea0b5a542cfb02e0883fa3"
},
"webapp-dev": {
"buildx.build.provenance": {},
"buildx.build.ref": "mybuilder/mybuilder0/kamngmcgyzebqxwu98b4lfv3n",
"containerimage.config.digest": "sha256:9651cc2b3c508f697c9c43b67b64c8359c2865c019e680aac1c11f4b875b67e0",
"containerimage.descriptor": {
"annotations": {
"config.digest": "sha256:9651cc2b3c508f697c9c43b67b64c8359c2865c019e680aac1c11f4b875b67e0",
"org.opencontainers.image.created": "2022-02-08T21:28:15Z"
},
"digest": "sha256:6d9ac9237a84afe1516540f40a0fafdc86859b2141954b4d643af7066d598b74",
"mediaType": "application/vnd.oci.image.manifest.v1+json",
"size": 506
},
"containerimage.digest": "sha256:6d9ac9237a84afe1516540f40a0fafdc86859b2141954b4d643af7066d598b74"
}
}
```
> **Note**
>
> Build record [provenance](https://docs.docker.com/build/attestations/slsa-provenance/#provenance-attestation-example)
> (`buildx.build.provenance`) includes minimal provenance by default. Set the
> `BUILDX_METADATA_PROVENANCE` environment variable to customize this behavior:
> * `min` sets minimal provenance (default).
> * `max` sets full provenance.
> * `disabled`, `false` or `0` does not set any provenance.
### <a name="no-cache"></a> Don't use cache when building the image (--no-cache) ### <a name="no-cache"></a> Don't use cache when building the image (--no-cache)
Same as `build --no-cache`. Don't use cache when building the image. Same as `build --no-cache`. Don't use cache when building the image.

View File

@ -27,10 +27,10 @@ Start a build
| [`--cgroup-parent`](https://docs.docker.com/reference/cli/docker/image/build/#cgroup-parent) | `string` | | Set the parent cgroup for the `RUN` instructions during build | | [`--cgroup-parent`](https://docs.docker.com/reference/cli/docker/image/build/#cgroup-parent) | `string` | | Set the parent cgroup for the `RUN` instructions during build |
| `--detach` | | | Detach buildx server (supported only on linux) (EXPERIMENTAL) | | `--detach` | | | Detach buildx server (supported only on linux) (EXPERIMENTAL) |
| [`-f`](https://docs.docker.com/reference/cli/docker/image/build/#file), [`--file`](https://docs.docker.com/reference/cli/docker/image/build/#file) | `string` | | Name of the Dockerfile (default: `PATH/Dockerfile`) | | [`-f`](https://docs.docker.com/reference/cli/docker/image/build/#file), [`--file`](https://docs.docker.com/reference/cli/docker/image/build/#file) | `string` | | Name of the Dockerfile (default: `PATH/Dockerfile`) |
| `--iidfile` | `string` | | Write the image ID to the file | | `--iidfile` | `string` | | Write the image ID to a file |
| `--label` | `stringArray` | | Set metadata for an image | | `--label` | `stringArray` | | Set metadata for an image |
| [`--load`](#load) | | | Shorthand for `--output=type=docker` | | [`--load`](#load) | | | Shorthand for `--output=type=docker` |
| [`--metadata-file`](#metadata-file) | `string` | | Write build result metadata to the file | | [`--metadata-file`](#metadata-file) | `string` | | Write build result metadata to a file |
| `--network` | `string` | `default` | Set the networking mode for the `RUN` instructions during build | | `--network` | `string` | `default` | Set the networking mode for the `RUN` instructions during build |
| `--no-cache` | | | Do not use cache when building the image | | `--no-cache` | | | Do not use cache when building the image |
| [`--no-cache-filter`](#no-cache-filter) | `stringArray` | | Do not cache specified stages | | [`--no-cache-filter`](#no-cache-filter) | `stringArray` | | Do not cache specified stages |
@ -314,7 +314,7 @@ More info about cache exporters and available attributes: https://github.com/mob
Shorthand for [`--output=type=docker`](#docker). Will automatically load the Shorthand for [`--output=type=docker`](#docker). Will automatically load the
single-platform build result to `docker images`. single-platform build result to `docker images`.
### <a name="metadata-file"></a> Write build result metadata to the file (--metadata-file) ### <a name="metadata-file"></a> Write build result metadata to a file (--metadata-file)
To output build metadata such as the image digest, pass the `--metadata-file` flag. To output build metadata such as the image digest, pass the `--metadata-file` flag.
The metadata will be written as a JSON object to the specified file. The The metadata will be written as a JSON object to the specified file. The
@ -327,6 +327,7 @@ $ cat metadata.json
```json ```json
{ {
"buildx.build.provenance": {},
"buildx.build.ref": "mybuilder/mybuilder0/0fjb6ubs52xx3vygf6fgdl611", "buildx.build.ref": "mybuilder/mybuilder0/0fjb6ubs52xx3vygf6fgdl611",
"containerimage.config.digest": "sha256:2937f66a9722f7f4a2df583de2f8cb97fc9196059a410e7f00072fc918930e66", "containerimage.config.digest": "sha256:2937f66a9722f7f4a2df583de2f8cb97fc9196059a410e7f00072fc918930e66",
"containerimage.descriptor": { "containerimage.descriptor": {
@ -342,6 +343,15 @@ $ cat metadata.json
} }
``` ```
> **Note**
>
> Build record [provenance](https://docs.docker.com/build/attestations/slsa-provenance/#provenance-attestation-example)
> (`buildx.build.provenance`) includes minimal provenance by default. Set the
> `BUILDX_METADATA_PROVENANCE` environment variable to customize this behavior:
> * `min` sets minimal provenance (default).
> * `max` sets full provenance.
> * `disabled`, `false` or `0` does not set any provenance.
### <a name="no-cache-filter"></a> Ignore build cache for specific stages (--no-cache-filter) ### <a name="no-cache-filter"></a> Ignore build cache for specific stages (--no-cache-filter)
The `--no-cache-filter` lets you specify one or more stages of a multi-stage The `--no-cache-filter` lets you specify one or more stages of a multi-stage

View File

@ -23,10 +23,10 @@ Start a build
| [`--cgroup-parent`](https://docs.docker.com/reference/cli/docker/image/build/#cgroup-parent) | `string` | | Set the parent cgroup for the `RUN` instructions during build | | [`--cgroup-parent`](https://docs.docker.com/reference/cli/docker/image/build/#cgroup-parent) | `string` | | Set the parent cgroup for the `RUN` instructions during build |
| `--detach` | | | Detach buildx server (supported only on linux) (EXPERIMENTAL) | | `--detach` | | | Detach buildx server (supported only on linux) (EXPERIMENTAL) |
| [`-f`](https://docs.docker.com/reference/cli/docker/image/build/#file), [`--file`](https://docs.docker.com/reference/cli/docker/image/build/#file) | `string` | | Name of the Dockerfile (default: `PATH/Dockerfile`) | | [`-f`](https://docs.docker.com/reference/cli/docker/image/build/#file), [`--file`](https://docs.docker.com/reference/cli/docker/image/build/#file) | `string` | | Name of the Dockerfile (default: `PATH/Dockerfile`) |
| `--iidfile` | `string` | | Write the image ID to the file | | `--iidfile` | `string` | | Write the image ID to a file |
| `--label` | `stringArray` | | Set metadata for an image | | `--label` | `stringArray` | | Set metadata for an image |
| `--load` | | | Shorthand for `--output=type=docker` | | `--load` | | | Shorthand for `--output=type=docker` |
| `--metadata-file` | `string` | | Write build result metadata to the file | | `--metadata-file` | `string` | | Write build result metadata to a file |
| `--network` | `string` | `default` | Set the networking mode for the `RUN` instructions during build | | `--network` | `string` | `default` | Set the networking mode for the `RUN` instructions during build |
| `--no-cache` | | | Do not use cache when building the image | | `--no-cache` | | | Do not use cache when building the image |
| `--no-cache-filter` | `stringArray` | | Do not cache specified stages | | `--no-cache-filter` | `stringArray` | | Do not cache specified stages |

View File

@ -10,6 +10,7 @@ import (
"github.com/containerd/continuity/fs/fstest" "github.com/containerd/continuity/fs/fstest"
"github.com/docker/buildx/util/gitutil" "github.com/docker/buildx/util/gitutil"
"github.com/moby/buildkit/identity" "github.com/moby/buildkit/identity"
provenancetypes "github.com/moby/buildkit/solver/llbsolver/provenance/types"
"github.com/moby/buildkit/util/contentutil" "github.com/moby/buildkit/util/contentutil"
"github.com/moby/buildkit/util/testutil" "github.com/moby/buildkit/util/testutil"
"github.com/moby/buildkit/util/testutil/integration" "github.com/moby/buildkit/util/testutil/integration"
@ -41,7 +42,7 @@ var bakeTests = []func(t *testing.T, sb integration.Sandbox){
testBakeEmpty, testBakeEmpty,
testBakeShmSize, testBakeShmSize,
testBakeUlimits, testBakeUlimits,
testBakeRefs, testBakeMetadata,
testBakeMultiExporters, testBakeMultiExporters,
testBakeLoadPush, testBakeLoadPush,
} }
@ -632,7 +633,19 @@ target "default" {
require.Contains(t, string(dt), `1024`) require.Contains(t, string(dt), `1024`)
} }
func testBakeRefs(t *testing.T, sb integration.Sandbox) { func testBakeMetadata(t *testing.T, sb integration.Sandbox) {
t.Run("max", func(t *testing.T) {
bakeMetadata(t, sb, "max")
})
t.Run("min", func(t *testing.T) {
bakeMetadata(t, sb, "min")
})
t.Run("disabled", func(t *testing.T) {
bakeMetadata(t, sb, "disabled")
})
}
func bakeMetadata(t *testing.T, sb integration.Sandbox, metadataMode string) {
dockerfile := []byte(` dockerfile := []byte(`
FROM scratch FROM scratch
COPY foo /foo COPY foo /foo
@ -656,7 +669,12 @@ target "default" {
outFlag += ",dest=" + dirDest + "/image.tar" outFlag += ",dest=" + dirDest + "/image.tar"
} }
cmd := buildxCmd(sb, withDir(dir), withArgs("bake", "--metadata-file", filepath.Join(dirDest, "md.json"), "--set", outFlag)) cmd := buildxCmd(
sb,
withDir(dir),
withArgs("bake", "--metadata-file", filepath.Join(dirDest, "md.json"), "--set", outFlag),
withEnv("BUILDX_METADATA_PROVENANCE="+metadataMode),
)
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
require.NoError(t, err, out) require.NoError(t, err, out)
@ -665,7 +683,8 @@ target "default" {
type mdT struct { type mdT struct {
Default struct { Default struct {
BuildRef string `json:"buildx.build.ref"` BuildRef string `json:"buildx.build.ref"`
BuildProvenance map[string]interface{} `json:"buildx.build.provenance"`
} `json:"default"` } `json:"default"`
} }
var md mdT var md mdT
@ -673,6 +692,18 @@ target "default" {
require.NoError(t, err) require.NoError(t, err)
require.NotEmpty(t, md.Default.BuildRef) require.NotEmpty(t, md.Default.BuildRef)
if metadataMode == "disabled" {
require.Empty(t, md.Default.BuildProvenance)
return
}
require.NotEmpty(t, md.Default.BuildProvenance)
dtprv, err := json.Marshal(md.Default.BuildProvenance)
require.NoError(t, err)
var prv provenancetypes.ProvenancePredicate
require.NoError(t, json.Unmarshal(dtprv, &prv))
require.Equal(t, provenancetypes.BuildKitBuildType, prv.BuildType)
} }
func testBakeMultiExporters(t *testing.T, sb integration.Sandbox) { func testBakeMultiExporters(t *testing.T, sb integration.Sandbox) {

View File

@ -17,6 +17,7 @@ import (
"github.com/containerd/continuity/fs/fstest" "github.com/containerd/continuity/fs/fstest"
"github.com/creack/pty" "github.com/creack/pty"
"github.com/moby/buildkit/identity" "github.com/moby/buildkit/identity"
provenancetypes "github.com/moby/buildkit/solver/llbsolver/provenance/types"
"github.com/moby/buildkit/util/appdefaults" "github.com/moby/buildkit/util/appdefaults"
"github.com/moby/buildkit/util/contentutil" "github.com/moby/buildkit/util/contentutil"
"github.com/moby/buildkit/util/testutil" "github.com/moby/buildkit/util/testutil"
@ -55,7 +56,7 @@ var buildTests = []func(t *testing.T, sb integration.Sandbox){
testBuildNetworkModeBridge, testBuildNetworkModeBridge,
testBuildShmSize, testBuildShmSize,
testBuildUlimit, testBuildUlimit,
testBuildRef, testBuildMetadata,
testBuildMultiExporters, testBuildMultiExporters,
testBuildLoadPush, testBuildLoadPush,
testBuildSecret, testBuildSecret,
@ -555,7 +556,19 @@ COPY --from=build /ulimit /
require.Contains(t, string(dt), `1024`) require.Contains(t, string(dt), `1024`)
} }
func testBuildRef(t *testing.T, sb integration.Sandbox) { func testBuildMetadata(t *testing.T, sb integration.Sandbox) {
t.Run("max", func(t *testing.T) {
buildMetadata(t, sb, "max")
})
t.Run("min", func(t *testing.T) {
buildMetadata(t, sb, "min")
})
t.Run("disabled", func(t *testing.T) {
buildMetadata(t, sb, "disabled")
})
}
func buildMetadata(t *testing.T, sb integration.Sandbox, metadataMode string) {
dir := createTestProject(t) dir := createTestProject(t)
dirDest := t.TempDir() dirDest := t.TempDir()
@ -565,7 +578,11 @@ func testBuildRef(t *testing.T, sb integration.Sandbox) {
outFlag += ",dest=" + dirDest + "/image.tar" outFlag += ",dest=" + dirDest + "/image.tar"
} }
cmd := buildxCmd(sb, withArgs("build", outFlag, "--metadata-file", filepath.Join(dirDest, "md.json"), dir)) cmd := buildxCmd(
sb,
withArgs("build", outFlag, "--metadata-file", filepath.Join(dirDest, "md.json"), dir),
withEnv("BUILDX_METADATA_PROVENANCE="+metadataMode),
)
out, err := cmd.CombinedOutput() out, err := cmd.CombinedOutput()
require.NoError(t, err, string(out)) require.NoError(t, err, string(out))
@ -573,13 +590,26 @@ func testBuildRef(t *testing.T, sb integration.Sandbox) {
require.NoError(t, err) require.NoError(t, err)
type mdT struct { type mdT struct {
BuildRef string `json:"buildx.build.ref"` BuildRef string `json:"buildx.build.ref"`
BuildProvenance map[string]interface{} `json:"buildx.build.provenance"`
} }
var md mdT var md mdT
err = json.Unmarshal(dt, &md) err = json.Unmarshal(dt, &md)
require.NoError(t, err) require.NoError(t, err)
require.NotEmpty(t, md.BuildRef) require.NotEmpty(t, md.BuildRef)
if metadataMode == "disabled" {
require.Empty(t, md.BuildProvenance)
return
}
require.NotEmpty(t, md.BuildProvenance)
dtprv, err := json.Marshal(md.BuildProvenance)
require.NoError(t, err)
var prv provenancetypes.ProvenancePredicate
require.NoError(t, json.Unmarshal(dtprv, &prv))
require.Equal(t, provenancetypes.BuildKitBuildType, prv.BuildType)
} }
func testBuildMultiExporters(t *testing.T, sb integration.Sandbox) { func testBuildMultiExporters(t *testing.T, sb integration.Sandbox) {

35
util/confutil/metadata.go Normal file
View File

@ -0,0 +1,35 @@
package confutil
import (
"os"
"strconv"
)
// MetadataProvenanceMode is the type for setting provenance in the metdata file
type MetadataProvenanceMode int
const (
// MetadataProvenanceModeMin sets minimal provenance (default)
MetadataProvenanceModeMin MetadataProvenanceMode = iota
// MetadataProvenanceModeMax sets full provenance
MetadataProvenanceModeMax
// MetadataProvenanceModeDisabled doesn't set provenance
MetadataProvenanceModeDisabled
)
// MetadataProvenance returns the provenance mode to set in the metadata file
func MetadataProvenance() MetadataProvenanceMode {
bmp := os.Getenv("BUILDX_METADATA_PROVENANCE")
switch bmp {
case "min":
return MetadataProvenanceModeMin
case "max":
return MetadataProvenanceModeMax
case "disabled":
return MetadataProvenanceModeDisabled
}
if ok, err := strconv.ParseBool(bmp); err == nil && !ok {
return MetadataProvenanceModeDisabled
}
return MetadataProvenanceModeMin
}

View File

@ -0,0 +1,72 @@
package types
import (
"encoding/json"
"math"
"time"
)
type SysCPUStat struct {
User float64 `json:"user"`
Nice float64 `json:"nice"`
System float64 `json:"system"`
Idle float64 `json:"idle"`
Iowait float64 `json:"iowait"`
IRQ float64 `json:"irq"`
SoftIRQ float64 `json:"softirq"`
Steal float64 `json:"steal"`
Guest float64 `json:"guest"`
GuestNice float64 `json:"guestNice"`
}
type sysCPUStatAlias SysCPUStat // avoid recursion of MarshalJSON
func (s SysCPUStat) MarshalJSON() ([]byte, error) {
return json.Marshal(sysCPUStatAlias{
User: math.Round(s.User*1000) / 1000,
Nice: math.Round(s.Nice*1000) / 1000,
System: math.Round(s.System*1000) / 1000,
Idle: math.Round(s.Idle*1000) / 1000,
Iowait: math.Round(s.Iowait*1000) / 1000,
IRQ: math.Round(s.IRQ*1000) / 1000,
SoftIRQ: math.Round(s.SoftIRQ*1000) / 1000,
Steal: math.Round(s.Steal*1000) / 1000,
Guest: math.Round(s.Guest*1000) / 1000,
GuestNice: math.Round(s.GuestNice*1000) / 1000,
})
}
type ProcStat struct {
ContextSwitches uint64 `json:"contextSwitches"`
ProcessCreated uint64 `json:"processCreated"`
ProcessesRunning uint64 `json:"processesRunning"`
}
type SysMemoryStat struct {
Total *uint64 `json:"total"`
Free *uint64 `json:"free"`
Available *uint64 `json:"available"`
Buffers *uint64 `json:"buffers"`
Cached *uint64 `json:"cached"`
Active *uint64 `json:"active"`
Inactive *uint64 `json:"inactive"`
Swap *uint64 `json:"swap"`
Dirty *uint64 `json:"dirty"`
Writeback *uint64 `json:"writeback"`
Slab *uint64 `json:"slab"`
}
type SysSample struct {
//nolint
Timestamp_ time.Time `json:"timestamp"`
CPUStat *SysCPUStat `json:"cpuStat,omitempty"`
ProcStat *ProcStat `json:"procStat,omitempty"`
MemoryStat *SysMemoryStat `json:"memoryStat,omitempty"`
CPUPressure *Pressure `json:"cpuPressure,omitempty"`
MemoryPressure *Pressure `json:"memoryPressure,omitempty"`
IOPressure *Pressure `json:"ioPressure,omitempty"`
}
func (s *SysSample) Timestamp() time.Time {
return s.Timestamp_
}

View File

@ -0,0 +1,113 @@
package types
import (
"context"
"time"
)
type Recorder interface {
Start()
Close()
CloseAsync(func(context.Context) error) error
Wait() error
Samples() (*Samples, error)
}
type Samples struct {
Samples []*Sample `json:"samples,omitempty"`
SysCPUStat *SysCPUStat `json:"sysCPUStat,omitempty"`
}
// Sample represents a wrapper for sampled data of cgroupv2 controllers
type Sample struct {
//nolint
Timestamp_ time.Time `json:"timestamp"`
CPUStat *CPUStat `json:"cpuStat,omitempty"`
MemoryStat *MemoryStat `json:"memoryStat,omitempty"`
IOStat *IOStat `json:"ioStat,omitempty"`
PIDsStat *PIDsStat `json:"pidsStat,omitempty"`
NetStat *NetworkSample `json:"netStat,omitempty"`
}
func (s *Sample) Timestamp() time.Time {
return s.Timestamp_
}
type NetworkSample struct {
RxBytes int64 `json:"rxBytes,omitempty"`
RxPackets int64 `json:"rxPackets,omitempty"`
RxErrors int64 `json:"rxErrors,omitempty"`
RxDropped int64 `json:"rxDropped,omitempty"`
TxBytes int64 `json:"txBytes,omitempty"`
TxPackets int64 `json:"txPackets,omitempty"`
TxErrors int64 `json:"txErrors,omitempty"`
TxDropped int64 `json:"txDropped,omitempty"`
}
// CPUStat represents the sampling state of the cgroupv2 CPU controller
type CPUStat struct {
UsageNanos *uint64 `json:"usageNanos,omitempty"`
UserNanos *uint64 `json:"userNanos,omitempty"`
SystemNanos *uint64 `json:"systemNanos,omitempty"`
NrPeriods *uint32 `json:"nrPeriods,omitempty"`
NrThrottled *uint32 `json:"nrThrottled,omitempty"`
ThrottledNanos *uint64 `json:"throttledNanos,omitempty"`
Pressure *Pressure `json:"pressure,omitempty"`
}
// MemoryStat represents the sampling state of the cgroupv2 memory controller
type MemoryStat struct {
SwapBytes *uint64 `json:"swapBytes,omitempty"`
Anon *uint64 `json:"anon,omitempty"`
File *uint64 `json:"file,omitempty"`
Kernel *uint64 `json:"kernel,omitempty"`
KernelStack *uint64 `json:"kernelStack,omitempty"`
PageTables *uint64 `json:"pageTables,omitempty"`
Sock *uint64 `json:"sock,omitempty"`
Vmalloc *uint64 `json:"vmalloc,omitempty"`
Shmem *uint64 `json:"shmem,omitempty"`
FileMapped *uint64 `json:"fileMapped,omitempty"`
FileDirty *uint64 `json:"fileDirty,omitempty"`
FileWriteback *uint64 `json:"fileWriteback,omitempty"`
Slab *uint64 `json:"slab,omitempty"`
Pgscan *uint64 `json:"pgscan,omitempty"`
Pgsteal *uint64 `json:"pgsteal,omitempty"`
Pgfault *uint64 `json:"pgfault,omitempty"`
Pgmajfault *uint64 `json:"pgmajfault,omitempty"`
Peak *uint64 `json:"peak,omitempty"`
LowEvents uint64 `json:"lowEvents,omitempty"`
HighEvents uint64 `json:"highEvents,omitempty"`
MaxEvents uint64 `json:"maxEvents,omitempty"`
OomEvents uint64 `json:"oomEvents,omitempty"`
OomKillEvents uint64 `json:"oomKillEvents,omitempty"`
Pressure *Pressure `json:"pressure,omitempty"`
}
// IOStat represents the sampling state of the cgroupv2 IO controller
type IOStat struct {
ReadBytes *uint64 `json:"readBytes,omitempty"`
WriteBytes *uint64 `json:"writeBytes,omitempty"`
DiscardBytes *uint64 `json:"discardBytes,omitempty"`
ReadIOs *uint64 `json:"readIOs,omitempty"`
WriteIOs *uint64 `json:"writeIOs,omitempty"`
DiscardIOs *uint64 `json:"discardIOs,omitempty"`
Pressure *Pressure `json:"pressure,omitempty"`
}
// PIDsStat represents the sampling state of the cgroupv2 PIDs controller
type PIDsStat struct {
Current *uint64 `json:"current,omitempty"`
}
// Pressure represents the sampling state of pressure files
type Pressure struct {
Some *PressureValues `json:"some"`
Full *PressureValues `json:"full"`
}
type PressureValues struct {
Avg10 *float64 `json:"avg10"`
Avg60 *float64 `json:"avg60"`
Avg300 *float64 `json:"avg300"`
Total *uint64 `json:"total"`
}

View File

@ -0,0 +1,116 @@
package types
import (
slsa02 "github.com/in-toto/in-toto-golang/in_toto/slsa_provenance/v0.2"
resourcestypes "github.com/moby/buildkit/executor/resources/types"
"github.com/moby/buildkit/solver/pb"
digest "github.com/opencontainers/go-digest"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
)
const (
BuildKitBuildType = "https://mobyproject.org/buildkit@v1"
)
type BuildConfig struct {
Definition []BuildStep `json:"llbDefinition,omitempty"`
DigestMapping map[digest.Digest]string `json:"digestMapping,omitempty"`
}
type BuildStep struct {
ID string `json:"id,omitempty"`
Op pb.Op `json:"op,omitempty"`
Inputs []string `json:"inputs,omitempty"`
ResourceUsage *resourcestypes.Samples `json:"resourceUsage,omitempty"`
}
type Source struct {
Locations map[string]*pb.Locations `json:"locations,omitempty"`
Infos []SourceInfo `json:"infos,omitempty"`
}
type SourceInfo struct {
Filename string `json:"filename,omitempty"`
Language string `json:"language,omitempty"`
Data []byte `json:"data,omitempty"`
Definition []BuildStep `json:"llbDefinition,omitempty"`
DigestMapping map[digest.Digest]string `json:"digestMapping,omitempty"`
}
type ImageSource struct {
Ref string
Platform *ocispecs.Platform
Digest digest.Digest
Local bool
}
type GitSource struct {
URL string
Commit string
}
type HTTPSource struct {
URL string
Digest digest.Digest
}
type LocalSource struct {
Name string `json:"name"`
}
type Secret struct {
ID string `json:"id"`
Optional bool `json:"optional,omitempty"`
}
type SSH struct {
ID string `json:"id"`
Optional bool `json:"optional,omitempty"`
}
type Sources struct {
Images []ImageSource
Git []GitSource
HTTP []HTTPSource
Local []LocalSource
}
type ProvenancePredicate struct {
slsa02.ProvenancePredicate
Invocation ProvenanceInvocation `json:"invocation,omitempty"`
BuildConfig *BuildConfig `json:"buildConfig,omitempty"`
Metadata *ProvenanceMetadata `json:"metadata,omitempty"`
}
type ProvenanceInvocation struct {
ConfigSource slsa02.ConfigSource `json:"configSource,omitempty"`
Parameters Parameters `json:"parameters,omitempty"`
Environment Environment `json:"environment,omitempty"`
}
type Parameters struct {
Frontend string `json:"frontend,omitempty"`
Args map[string]string `json:"args,omitempty"`
Secrets []*Secret `json:"secrets,omitempty"`
SSH []*SSH `json:"ssh,omitempty"`
Locals []*LocalSource `json:"locals,omitempty"`
// TODO: select export attributes
// TODO: frontend inputs
}
type Environment struct {
Platform string `json:"platform"`
}
type ProvenanceMetadata struct {
slsa02.ProvenanceMetadata
BuildKitMetadata BuildKitMetadata `json:"https://mobyproject.org/buildkit@v1#metadata,omitempty"`
Hermetic bool `json:"https://mobyproject.org/buildkit@v1#hermetic,omitempty"`
}
type BuildKitMetadata struct {
VCS map[string]string `json:"vcs,omitempty"`
Source *Source `json:"source,omitempty"`
Layers map[string][][]ocispecs.Descriptor `json:"layers,omitempty"`
SysUsage []*resourcestypes.SysSample `json:"sysUsage,omitempty"`
}

2
vendor/modules.txt vendored
View File

@ -528,6 +528,7 @@ github.com/moby/buildkit/client/llb
github.com/moby/buildkit/client/llb/sourceresolver github.com/moby/buildkit/client/llb/sourceresolver
github.com/moby/buildkit/client/ociindex github.com/moby/buildkit/client/ociindex
github.com/moby/buildkit/cmd/buildkitd/config github.com/moby/buildkit/cmd/buildkitd/config
github.com/moby/buildkit/executor/resources/types
github.com/moby/buildkit/exporter/containerimage/exptypes github.com/moby/buildkit/exporter/containerimage/exptypes
github.com/moby/buildkit/exporter/exptypes github.com/moby/buildkit/exporter/exptypes
github.com/moby/buildkit/frontend/attestations github.com/moby/buildkit/frontend/attestations
@ -552,6 +553,7 @@ github.com/moby/buildkit/session/sshforward/sshprovider
github.com/moby/buildkit/session/upload github.com/moby/buildkit/session/upload
github.com/moby/buildkit/session/upload/uploadprovider github.com/moby/buildkit/session/upload/uploadprovider
github.com/moby/buildkit/solver/errdefs github.com/moby/buildkit/solver/errdefs
github.com/moby/buildkit/solver/llbsolver/provenance/types
github.com/moby/buildkit/solver/pb github.com/moby/buildkit/solver/pb
github.com/moby/buildkit/solver/result github.com/moby/buildkit/solver/result
github.com/moby/buildkit/source/types github.com/moby/buildkit/source/types