From d81928a72fe63961b5ee9552a18337b3d00ee1d0 Mon Sep 17 00:00:00 2001 From: Justin Chadwell Date: Wed, 7 Dec 2022 14:08:50 +0000 Subject: [PATCH 1/4] solver: delete caps for additional oci properties We don't need multiple caps for a single feature - the caps that these were copied by were addded over time, we don't immediately need all of them to start with, only the main feature one is initially required. Signed-off-by: Justin Chadwell --- client/llb/source.go | 7 ++----- solver/pb/caps.go | 16 +--------------- 2 files changed, 3 insertions(+), 20 deletions(-) diff --git a/client/llb/source.go b/client/llb/source.go index e0b4363483c7..0c93b85334b1 100644 --- a/client/llb/source.go +++ b/client/llb/source.go @@ -464,12 +464,9 @@ func OCILayout(store string, digest digest.Digest, opts ...OCILayoutOption) Stat attrs := map[string]string{} if gi.sessionID != "" { attrs[pb.AttrOCILayoutSessionID] = gi.sessionID - addCap(&gi.Constraints, pb.CapSourceOCILayoutSessionID) } - - if ll := gi.layerLimit; ll != nil { - attrs[pb.AttrOCILayoutLayerLimit] = strconv.FormatInt(int64(*ll), 10) - addCap(&gi.Constraints, pb.CapSourceOCILayoutLayerLimit) + if gi.layerLimit != nil { + attrs[pb.AttrOCILayoutLayerLimit] = strconv.FormatInt(int64(*gi.layerLimit), 10) } addCap(&gi.Constraints, pb.CapSourceOCILayout) diff --git a/solver/pb/caps.go b/solver/pb/caps.go index 39918a4690c4..8e177f1d0fb9 100644 --- a/solver/pb/caps.go +++ b/solver/pb/caps.go @@ -35,9 +35,7 @@ const ( CapSourceHTTPPerm apicaps.CapID = "source.http.perm" CapSourceHTTPUIDGID apicaps.CapID = "soruce.http.uidgid" - CapSourceOCILayout apicaps.CapID = "source.ocilayout" - CapSourceOCILayoutSessionID apicaps.CapID = "source.ocilayout.sessionid" - CapSourceOCILayoutLayerLimit apicaps.CapID = "source.ocilayout.layerlimit" + CapSourceOCILayout apicaps.CapID = "source.ocilayout" CapBuildOpLLBFileName apicaps.CapID = "source.buildop.llbfilename" @@ -221,18 +219,6 @@ func init() { Status: apicaps.CapStatusExperimental, }) - Caps.Init(apicaps.Cap{ - ID: CapSourceOCILayoutSessionID, - Enabled: true, - Status: apicaps.CapStatusExperimental, - }) - - Caps.Init(apicaps.Cap{ - ID: CapSourceOCILayoutLayerLimit, - Enabled: true, - Status: apicaps.CapStatusExperimental, - }) - Caps.Init(apicaps.Cap{ ID: CapSourceHTTPUIDGID, Enabled: true, From ea0cb97532bb1c66d83aae53853bbe338ec957b9 Mon Sep 17 00:00:00 2001 From: Justin Chadwell Date: Wed, 7 Dec 2022 14:11:00 +0000 Subject: [PATCH 2/4] dockerfile: remove unneccessary session id attachment SessionID is only used by the OCI resolver, so it shouldn't be included for normal docker image resolution. Signed-off-by: Justin Chadwell --- frontend/dockerfile/builder/build.go | 1 - 1 file changed, 1 deletion(-) diff --git a/frontend/dockerfile/builder/build.go b/frontend/dockerfile/builder/build.go index d1be3cedf7bc..6c0de2336874 100644 --- a/frontend/dockerfile/builder/build.go +++ b/frontend/dockerfile/builder/build.go @@ -928,7 +928,6 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string, ResolveMode: resolveMode, LogName: fmt.Sprintf("[context %s] load metadata for %s", name, ref), ResolverType: llb.ResolverTypeRegistry, - SessionID: sessionID, }) if err != nil { return nil, nil, err From a925cd7c4c25bcebd1260a1e17ab093a3bd96180 Mon Sep 17 00:00:00 2001 From: Justin Chadwell Date: Wed, 7 Dec 2022 14:12:34 +0000 Subject: [PATCH 3/4] solver: attach store id as explicit property of source This breaking api change refactors the LLB API to prevent reference mangling and demangling throughout OCI access. Once the session and store IDs have been determined in the dockerfile frontend, we keep them the same, and attach them as additional properties. This has the additional effect of making the actual reference used in the image resolution arbitrary, since we only parse and access the digest. The rest of the name can be selected to optimize for log readability. Signed-off-by: Justin Chadwell --- client/client_test.go | 19 +- client/llb/resolver.go | 17 +- client/llb/source.go | 14 +- frontend/dockerfile/builder/build.go | 13 +- frontend/gateway/gateway.go | 6 +- frontend/gateway/grpcclient/client.go | 10 +- frontend/gateway/pb/gateway.pb.go | 344 +++++++++++++++----------- frontend/gateway/pb/gateway.proto | 1 + solver/llbsolver/provenance.go | 2 +- solver/pb/attr.go | 1 + source/containerimage/ocilayout.go | 25 +- source/containerimage/pull.go | 28 +-- source/identifier.go | 24 +- 13 files changed, 284 insertions(+), 220 deletions(-) diff --git a/client/client_test.go b/client/client_test.go index c364d94f671e..04263ce45e84 100644 --- a/client/client_test.go +++ b/client/client_test.go @@ -1773,11 +1773,11 @@ func testOCILayoutSource(t *testing.T, sb integration.Sandbox) { require.NoError(t, err) // reference the OCI Layout in a build - // note that the key does not need to be the directory name, just something unique. - // since we are doing just one build with one remote here, we can give it any old ID, - // even something really imaginative, like "one" - csID := "one" - st = llb.OCILayout(csID, digest) + // note that the key does not need to be the directory name, just something + // unique. since we are doing just one build with one remote here, we can + // give it any ID + csID := "my-content-store" + st = llb.OCILayout(fmt.Sprintf("not/real@%s", digest), llb.OCIStore("", csID)) def, err = st.Marshal(context.TODO()) require.NoError(t, err) @@ -1902,12 +1902,7 @@ func testOCILayoutPlatformSource(t *testing.T, sb integration.Sandbox) { store, err := local.NewStore(dir) require.NoError(t, err) - - // reference the OCI Layout in a build - // note that the key does not need to be the directory name, just something unique. - // since we are doing just one build with one remote here, we can give it any old ID, - // even something really imaginative, like "one" - csID := "one" + csID := "my-content-store" destDir := t.TempDir() @@ -1917,7 +1912,7 @@ func testOCILayoutPlatformSource(t *testing.T, sb integration.Sandbox) { Platforms: make([]exptypes.Platform, len(platformsToTest)), } for i, platform := range platformsToTest { - st := llb.OCILayout(csID, digest) + st := llb.OCILayout(fmt.Sprintf("not/real@%s", digest), llb.OCIStore("", csID)) def, err := st.Marshal(ctx, llb.Platform(platforms.MustParse(platform))) if err != nil { diff --git a/client/llb/resolver.go b/client/llb/resolver.go index 84eaa6bd7757..b3b9cdf751c7 100644 --- a/client/llb/resolver.go +++ b/client/llb/resolver.go @@ -42,9 +42,16 @@ const ( ) type ResolveImageConfigOpt struct { - Platform *ocispecs.Platform - ResolveMode string - LogName string - ResolverType // default is ResolverTypeRegistry - SessionID string + ResolverType + + Platform *ocispecs.Platform + ResolveMode string + LogName string + + Store ResolveImageConfigOptStore +} + +type ResolveImageConfigOptStore struct { + SessionID string + StoreID string } diff --git a/client/llb/source.go b/client/llb/source.go index 0c93b85334b1..27c8c1b617f2 100644 --- a/client/llb/source.go +++ b/client/llb/source.go @@ -4,7 +4,6 @@ import ( "context" _ "crypto/sha256" // for opencontainers/go-digest "encoding/json" - "fmt" "os" "strconv" "strings" @@ -455,7 +454,7 @@ func Differ(t DiffType, required bool) LocalOption { }) } -func OCILayout(store string, digest digest.Digest, opts ...OCILayoutOption) State { +func OCILayout(ref string, opts ...OCILayoutOption) State { gi := &OCILayoutInfo{} for _, o := range opts { @@ -465,13 +464,16 @@ func OCILayout(store string, digest digest.Digest, opts ...OCILayoutOption) Stat if gi.sessionID != "" { attrs[pb.AttrOCILayoutSessionID] = gi.sessionID } + if gi.storeID != "" { + attrs[pb.AttrOCILayoutStoreID] = gi.storeID + } if gi.layerLimit != nil { attrs[pb.AttrOCILayoutLayerLimit] = strconv.FormatInt(int64(*gi.layerLimit), 10) } addCap(&gi.Constraints, pb.CapSourceOCILayout) - source := NewSource(fmt.Sprintf("oci-layout://%s@%s", store, digest), attrs, gi.Constraints) + source := NewSource("oci-layout://"+ref, attrs, gi.Constraints) return NewState(source.Output()) } @@ -485,9 +487,10 @@ func (fn ociLayoutOptionFunc) SetOCILayoutOption(li *OCILayoutInfo) { fn(li) } -func OCISessionID(id string) OCILayoutOption { +func OCIStore(sessionID string, storeID string) OCILayoutOption { return ociLayoutOptionFunc(func(oi *OCILayoutInfo) { - oi.sessionID = id + oi.sessionID = sessionID + oi.storeID = storeID }) } @@ -500,6 +503,7 @@ func OCILayerLimit(limit int) OCILayoutOption { type OCILayoutInfo struct { constraintsWrapper sessionID string + storeID string layerLimit *int } diff --git a/frontend/dockerfile/builder/build.go b/frontend/dockerfile/builder/build.go index 6c0de2336874..cd0b8fe0419a 100644 --- a/frontend/dockerfile/builder/build.go +++ b/frontend/dockerfile/builder/build.go @@ -979,14 +979,16 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string, return nil, nil, errors.Errorf("oci-layout reference %q does not have digest", ref.String()) } - // We use store id as the host here, the image name will be ignored - // (since image lookup is not currently supported) - id := fmt.Sprintf("%s/image@%s", named.Name(), digested.Digest()) + id := fmt.Sprintf("foo/bar@%s", digested.Digest()) _, data, err := c.ResolveImageConfig(ctx, id, llb.ResolveImageConfigOpt{ Platform: platform, ResolveMode: resolveMode, LogName: fmt.Sprintf("[context %s] load metadata for %s", name, ref), ResolverType: llb.ResolverTypeOCILayout, + Store: llb.ResolveImageConfigOptStore{ + SessionID: sessionID, + StoreID: named.Name(), + }, }) if err != nil { return nil, nil, err @@ -999,14 +1001,13 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string, ociOpt := []llb.OCILayoutOption{ llb.WithCustomName("[context " + name + "] OCI load from client"), - llb.OCISessionID(c.BuildOpts().SessionID), + llb.OCIStore(c.BuildOpts().SessionID, named.Name()), } if platform != nil { ociOpt = append(ociOpt, llb.Platform(*platform)) } st := llb.OCILayout( - named.Name(), - digested.Digest(), + id, ociOpt..., ) st, err = st.WithImageConfig(data) diff --git a/frontend/gateway/gateway.go b/frontend/gateway/gateway.go index b96015550a94..a9695307752f 100644 --- a/frontend/gateway/gateway.go +++ b/frontend/gateway/gateway.go @@ -541,10 +541,14 @@ func (lbf *llbBridgeForwarder) ResolveImageConfig(ctx context.Context, req *pb.R } } dgst, dt, err := lbf.llbBridge.ResolveImageConfig(ctx, req.Ref, llb.ResolveImageConfigOpt{ + ResolverType: llb.ResolverType(req.ResolverType), Platform: platform, ResolveMode: req.ResolveMode, LogName: req.LogName, - ResolverType: llb.ResolverType(req.ResolverType), + Store: llb.ResolveImageConfigOptStore{ + SessionID: req.SessionID, + StoreID: req.StoreID, + }, }) if err != nil { return nil, err diff --git a/frontend/gateway/grpcclient/client.go b/frontend/gateway/grpcclient/client.go index 70064e5cf47f..b8b2414f80a2 100644 --- a/frontend/gateway/grpcclient/client.go +++ b/frontend/gateway/grpcclient/client.go @@ -488,7 +488,15 @@ func (c *grpcClient) ResolveImageConfig(ctx context.Context, ref string, opt llb OSFeatures: platform.OSFeatures, } } - resp, err := c.client.ResolveImageConfig(ctx, &pb.ResolveImageConfigRequest{Ref: ref, Platform: p, ResolveMode: opt.ResolveMode, LogName: opt.LogName, ResolverType: int32(opt.ResolverType), SessionID: opt.SessionID}) + 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, + }) if err != nil { return "", nil, err } diff --git a/frontend/gateway/pb/gateway.pb.go b/frontend/gateway/pb/gateway.pb.go index 58701c874c62..7cecd77bf7c7 100644 --- a/frontend/gateway/pb/gateway.pb.go +++ b/frontend/gateway/pb/gateway.pb.go @@ -741,6 +741,7 @@ type ResolveImageConfigRequest struct { 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:"-"` @@ -821,6 +822,13 @@ func (m *ResolveImageConfigRequest) GetSessionID() string { return "" } +func (m *ResolveImageConfigRequest) GetStoreID() string { + if m != nil { + return m.StoreID + } + return "" +} + 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"` @@ -2610,157 +2618,158 @@ func init() { func init() { proto.RegisterFile("gateway.proto", fileDescriptor_f1a937782ebbded5) } var fileDescriptor_f1a937782ebbded5 = []byte{ - // 2397 bytes of a gzipped FileDescriptorProto + // 2409 bytes of a gzipped FileDescriptorProto 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x59, 0xcf, 0x6f, 0x1b, 0xc7, - 0xf5, 0xd7, 0x8a, 0x94, 0x48, 0x3e, 0xfe, 0x10, 0x3d, 0x71, 0xf2, 0x65, 0x16, 0x81, 0x23, 0xaf, - 0x13, 0x45, 0x56, 0x1c, 0xd2, 0x5f, 0xda, 0x81, 0x5c, 0xbb, 0x75, 0x62, 0xfd, 0x82, 0x14, 0x4b, + 0xf5, 0xd7, 0x8a, 0x94, 0x44, 0x3e, 0xfe, 0x10, 0x3d, 0x71, 0xf2, 0x65, 0x16, 0x81, 0x23, 0xaf, + 0x13, 0x45, 0x56, 0x1c, 0xd2, 0x5f, 0xda, 0x81, 0x5c, 0xbb, 0x75, 0x62, 0xfd, 0x82, 0x18, 0x4b, 0x36, 0x3b, 0x72, 0xe1, 0x22, 0x48, 0x81, 0xae, 0xb8, 0x43, 0x7a, 0xeb, 0xd5, 0xee, 0x76, 0x77, 0x68, 0x59, 0xc9, 0xa5, 0xbd, 0x15, 0x39, 0xf5, 0xd4, 0x5b, 0x50, 0xa0, 0x05, 0x7a, 0x6e, 0x2f, - 0xbd, 0xb5, 0xe7, 0x00, 0xbd, 0xf4, 0xd2, 0x4b, 0x0f, 0x41, 0xe1, 0x3f, 0xa2, 0x40, 0x6f, 0xc5, + 0xbd, 0xb5, 0xe7, 0x00, 0xbd, 0xf4, 0xdc, 0x43, 0x50, 0xf8, 0x1f, 0xe8, 0xad, 0x40, 0x6f, 0xc5, 0x9b, 0x99, 0x25, 0x87, 0x3f, 0xb4, 0x24, 0xeb, 0x13, 0x67, 0xde, 0xbc, 0x1f, 0x33, 0xef, 0xcd, - 0x7b, 0xef, 0x33, 0x4b, 0x28, 0x77, 0x6d, 0xce, 0xce, 0xec, 0xf3, 0x7a, 0x18, 0x05, 0x3c, 0x20, - 0x6f, 0x9f, 0x06, 0x27, 0xe7, 0xf5, 0x93, 0x9e, 0xeb, 0x39, 0xcf, 0x5d, 0x5e, 0x7f, 0xf1, 0xff, - 0xf5, 0x4e, 0x14, 0xf8, 0x9c, 0xf9, 0x8e, 0xf9, 0x51, 0xd7, 0xe5, 0xcf, 0x7a, 0x27, 0xf5, 0x76, - 0x70, 0xda, 0xe8, 0x06, 0xdd, 0xa0, 0x21, 0x24, 0x4e, 0x7a, 0x1d, 0x31, 0x13, 0x13, 0x31, 0x92, - 0x9a, 0xcc, 0xe6, 0x28, 0x7b, 0x37, 0x08, 0xba, 0x1e, 0xb3, 0x43, 0x37, 0x56, 0xc3, 0x46, 0x14, - 0xb6, 0x1b, 0x31, 0xb7, 0x79, 0x2f, 0x56, 0x32, 0x37, 0x34, 0x19, 0xdc, 0x48, 0x23, 0xd9, 0x48, - 0x23, 0x0e, 0xbc, 0x17, 0x2c, 0x6a, 0x84, 0x27, 0x8d, 0x20, 0x4c, 0xb8, 0x1b, 0x17, 0x72, 0xdb, - 0xa1, 0xdb, 0xe0, 0xe7, 0x21, 0x8b, 0x1b, 0x67, 0x41, 0xf4, 0x9c, 0x45, 0x4a, 0xe0, 0xd6, 0x85, + 0x7b, 0xef, 0x33, 0x4b, 0x28, 0x75, 0x6d, 0xce, 0xce, 0xec, 0xf3, 0x5a, 0x18, 0x05, 0x3c, 0x20, + 0x6f, 0x9f, 0x06, 0x27, 0xe7, 0xb5, 0x93, 0x9e, 0xeb, 0x39, 0xcf, 0x5d, 0x5e, 0x7b, 0xf1, 0xff, + 0xb5, 0x4e, 0x14, 0xf8, 0x9c, 0xf9, 0x8e, 0xf9, 0x51, 0xd7, 0xe5, 0xcf, 0x7a, 0x27, 0xb5, 0x76, + 0x70, 0x5a, 0xef, 0x06, 0xdd, 0xa0, 0x2e, 0x24, 0x4e, 0x7a, 0x1d, 0x31, 0x13, 0x13, 0x31, 0x92, + 0x9a, 0xcc, 0xc6, 0x28, 0x7b, 0x37, 0x08, 0xba, 0x1e, 0xb3, 0x43, 0x37, 0x56, 0xc3, 0x7a, 0x14, + 0xb6, 0xeb, 0x31, 0xb7, 0x79, 0x2f, 0x56, 0x32, 0x37, 0x34, 0x19, 0xdc, 0x48, 0x3d, 0xd9, 0x48, + 0x3d, 0x0e, 0xbc, 0x17, 0x2c, 0xaa, 0x87, 0x27, 0xf5, 0x20, 0x4c, 0xb8, 0xeb, 0x17, 0x72, 0xdb, + 0xa1, 0x5b, 0xe7, 0xe7, 0x21, 0x8b, 0xeb, 0x67, 0x41, 0xf4, 0x9c, 0x45, 0x4a, 0xe0, 0xd6, 0x85, 0x02, 0x3d, 0xee, 0x7a, 0x28, 0xd5, 0xb6, 0xc3, 0x18, 0x8d, 0xe0, 0xaf, 0x12, 0xd2, 0x8f, 0xcd, - 0x03, 0xdf, 0x8d, 0xb9, 0xeb, 0x76, 0xdd, 0x46, 0x27, 0x16, 0x32, 0xd2, 0x0a, 0x1e, 0x42, 0xb2, - 0x5b, 0x7f, 0xcb, 0xc2, 0x32, 0x65, 0x71, 0xcf, 0xe3, 0x64, 0x0d, 0xca, 0x11, 0xeb, 0xec, 0xb0, - 0x30, 0x62, 0x6d, 0x9b, 0x33, 0xa7, 0x66, 0xac, 0x1a, 0xeb, 0x85, 0xfd, 0x05, 0x3a, 0x4c, 0x26, - 0x3f, 0x82, 0x4a, 0xc4, 0x3a, 0xb1, 0xc6, 0xb8, 0xb8, 0x6a, 0xac, 0x17, 0x9b, 0x1f, 0xd6, 0x2f, - 0x0c, 0x46, 0x9d, 0xb2, 0xce, 0x91, 0x1d, 0x0e, 0x44, 0xf6, 0x17, 0xe8, 0x88, 0x12, 0xd2, 0x84, - 0x4c, 0xc4, 0x3a, 0xb5, 0x8c, 0xd0, 0x75, 0x25, 0x5d, 0xd7, 0xfe, 0x02, 0x45, 0x66, 0xb2, 0x09, - 0x59, 0xd4, 0x52, 0xcb, 0x0a, 0xa1, 0xab, 0x53, 0x37, 0xb0, 0xbf, 0x40, 0x85, 0x00, 0x79, 0x08, - 0xf9, 0x53, 0xc6, 0x6d, 0xc7, 0xe6, 0x76, 0x0d, 0x56, 0x33, 0xeb, 0xc5, 0x66, 0x23, 0x55, 0x18, - 0x1d, 0x54, 0x3f, 0x52, 0x12, 0xbb, 0x3e, 0x8f, 0xce, 0x69, 0x5f, 0x01, 0x79, 0x0a, 0x25, 0x9b, - 0x73, 0x86, 0x5e, 0x75, 0x03, 0x3f, 0xae, 0x95, 0x84, 0xc2, 0x5b, 0xd3, 0x15, 0x3e, 0xd0, 0xa4, - 0xa4, 0xd2, 0x21, 0x45, 0xe6, 0x3d, 0x28, 0x0f, 0xd9, 0x24, 0x55, 0xc8, 0x3c, 0x67, 0xe7, 0x32, - 0x30, 0x14, 0x87, 0xe4, 0x32, 0x2c, 0xbd, 0xb0, 0xbd, 0x1e, 0x13, 0x31, 0x28, 0x51, 0x39, 0xb9, - 0xbb, 0x78, 0xc7, 0x30, 0x9f, 0xc1, 0xa5, 0x31, 0xfd, 0x13, 0x14, 0xfc, 0x40, 0x57, 0x50, 0x6c, - 0x7e, 0x90, 0xb2, 0x6b, 0x5d, 0x9d, 0x66, 0x69, 0x2b, 0x0f, 0xcb, 0x91, 0x38, 0x90, 0xf5, 0x1b, - 0x03, 0xaa, 0xa3, 0xa1, 0x26, 0x07, 0x2a, 0x48, 0x86, 0x70, 0xcb, 0xc7, 0x73, 0xdc, 0x12, 0x24, - 0x28, 0xc7, 0x08, 0x15, 0xe6, 0x26, 0x14, 0xfa, 0xa4, 0x69, 0xce, 0x28, 0x68, 0x5b, 0xb4, 0x36, - 0x21, 0x43, 0x59, 0x87, 0x54, 0x60, 0xd1, 0x55, 0xf7, 0x9a, 0x2e, 0xba, 0x0e, 0x59, 0x85, 0x8c, - 0xc3, 0x3a, 0xea, 0xe8, 0x95, 0x7a, 0x78, 0x52, 0xdf, 0x61, 0x1d, 0xd7, 0x77, 0xf1, 0x88, 0x14, - 0x97, 0xac, 0xdf, 0x19, 0x98, 0x1f, 0xb8, 0x2d, 0xf2, 0xc9, 0xd0, 0x39, 0xa6, 0xdf, 0xf6, 0xb1, - 0xdd, 0x3f, 0x4d, 0xdf, 0xfd, 0xed, 0xe1, 0x48, 0x4c, 0x49, 0x01, 0xfd, 0x74, 0x3f, 0x86, 0x92, - 0x1e, 0x1b, 0xb2, 0x0f, 0x45, 0xed, 0x1e, 0xa9, 0x0d, 0xaf, 0xcd, 0x16, 0x59, 0xaa, 0x8b, 0x5a, - 0x7f, 0xc8, 0x40, 0x51, 0x5b, 0x24, 0xf7, 0x21, 0xfb, 0xdc, 0xf5, 0xa5, 0x0b, 0x2b, 0xcd, 0x8d, - 0xd9, 0x54, 0x3e, 0x74, 0x7d, 0x87, 0x0a, 0x39, 0xd2, 0xd2, 0xf2, 0x6e, 0x51, 0x6c, 0xeb, 0xf6, - 0x6c, 0x3a, 0x2e, 0x4c, 0xbe, 0x9b, 0x73, 0x94, 0x0d, 0x59, 0x34, 0x08, 0x64, 0x43, 0x9b, 0x3f, - 0x13, 0x45, 0xa3, 0x40, 0xc5, 0x98, 0xdc, 0x84, 0x37, 0x5c, 0xff, 0x49, 0xc0, 0x83, 0x56, 0xc4, - 0x1c, 0x17, 0x2f, 0xdf, 0x93, 0xf3, 0x90, 0xd5, 0x96, 0x04, 0xcb, 0xa4, 0x25, 0xd2, 0x82, 0x8a, - 0x24, 0x1f, 0xf7, 0x4e, 0x7e, 0xc6, 0xda, 0x3c, 0xae, 0x2d, 0x8b, 0xf3, 0xac, 0xa7, 0x6c, 0xe1, - 0x40, 0x17, 0xa0, 0x23, 0xf2, 0xaf, 0x95, 0xed, 0xd6, 0x9f, 0x0c, 0x28, 0x0f, 0xa9, 0x27, 0x9f, - 0x0e, 0x85, 0xea, 0xc6, 0xac, 0xdb, 0xd2, 0x82, 0xf5, 0x19, 0x2c, 0x3b, 0x6e, 0x97, 0xc5, 0x5c, - 0x84, 0xaa, 0xb0, 0xd5, 0xfc, 0xf6, 0xbb, 0x77, 0x17, 0xfe, 0xf9, 0xdd, 0xbb, 0x1b, 0x5a, 0x8b, - 0x09, 0x42, 0xe6, 0xb7, 0x03, 0x9f, 0xdb, 0xae, 0xcf, 0x22, 0xec, 0x94, 0x1f, 0x49, 0x91, 0xfa, - 0x8e, 0xf8, 0xa1, 0x4a, 0x03, 0x3a, 0xdd, 0xb7, 0x4f, 0x99, 0x88, 0x53, 0x81, 0x8a, 0xb1, 0xc5, - 0xa1, 0x4c, 0x19, 0xef, 0x45, 0x3e, 0x65, 0x3f, 0xef, 0x21, 0xd3, 0xf7, 0x92, 0x42, 0x22, 0x36, - 0x3d, 0xad, 0xa0, 0x23, 0x23, 0x55, 0x02, 0x64, 0x1d, 0x96, 0x58, 0x14, 0x05, 0x91, 0x4a, 0x1e, - 0x52, 0x97, 0x3d, 0xbb, 0x1e, 0x85, 0xed, 0xfa, 0xb1, 0xe8, 0xd9, 0x54, 0x32, 0x58, 0x55, 0xa8, - 0x24, 0x56, 0xe3, 0x30, 0xf0, 0x63, 0x66, 0xad, 0xa0, 0xeb, 0xc2, 0x1e, 0x8f, 0xd5, 0x3e, 0xac, - 0xbf, 0x1a, 0x50, 0x49, 0x28, 0x92, 0x87, 0x7c, 0x01, 0xc5, 0x41, 0x69, 0x48, 0x6a, 0xc0, 0xdd, - 0x54, 0xa7, 0xea, 0xf2, 0x5a, 0x5d, 0x51, 0x25, 0x41, 0x57, 0x67, 0x3e, 0x82, 0xea, 0x28, 0xc3, - 0x84, 0xe8, 0xbf, 0x37, 0x5c, 0x20, 0x46, 0xeb, 0x95, 0x76, 0x1b, 0xfe, 0x61, 0xc0, 0xdb, 0x94, - 0x09, 0x10, 0x72, 0x70, 0x6a, 0x77, 0xd9, 0x76, 0xe0, 0x77, 0xdc, 0x6e, 0xe2, 0xe6, 0xaa, 0x28, - 0x86, 0x89, 0x66, 0xac, 0x8b, 0xeb, 0x90, 0x6f, 0x79, 0x36, 0xef, 0x04, 0xd1, 0xa9, 0x52, 0x5e, - 0x42, 0xe5, 0x09, 0x8d, 0xf6, 0x57, 0xc9, 0x2a, 0x14, 0x95, 0xe2, 0xa3, 0xc0, 0x49, 0xc2, 0xa9, - 0x93, 0x48, 0x0d, 0x72, 0x87, 0x41, 0xf7, 0x11, 0x06, 0x5b, 0x66, 0x58, 0x32, 0x25, 0x16, 0x94, - 0x14, 0x63, 0xd4, 0xcf, 0xae, 0x25, 0x3a, 0x44, 0x23, 0xef, 0x40, 0xe1, 0x98, 0xc5, 0xb1, 0x1b, - 0xf8, 0x07, 0x3b, 0xb5, 0x65, 0x21, 0x3f, 0x20, 0x58, 0xbf, 0x30, 0xc0, 0x9c, 0x74, 0x2e, 0x15, - 0xa4, 0xcf, 0x60, 0x59, 0x5e, 0x3b, 0x79, 0xb6, 0xff, 0xed, 0xc2, 0xca, 0x5f, 0xf2, 0x16, 0x2c, - 0x4b, 0xed, 0x2a, 0xd7, 0xd4, 0xcc, 0xfa, 0xf3, 0x12, 0x94, 0x8e, 0x71, 0x03, 0x89, 0x37, 0xeb, - 0x00, 0x83, 0x20, 0xa8, 0x8b, 0x3b, 0x1a, 0x1a, 0x8d, 0x83, 0x98, 0x90, 0xdf, 0x53, 0x97, 0x44, - 0xf5, 0xa9, 0xfe, 0x9c, 0x7c, 0x0e, 0xc5, 0x64, 0xfc, 0x38, 0xe4, 0xb5, 0x8c, 0xb8, 0x65, 0x77, - 0x52, 0x6e, 0x99, 0xbe, 0x93, 0xba, 0x26, 0xaa, 0xee, 0x98, 0x46, 0x21, 0x37, 0xe0, 0x92, 0xed, - 0x79, 0xc1, 0x99, 0x4a, 0x1c, 0x91, 0x02, 0x22, 0x04, 0x79, 0x3a, 0xbe, 0x80, 0x05, 0x51, 0x23, - 0x3e, 0x88, 0x22, 0xfb, 0x1c, 0xef, 0xcc, 0xb2, 0xe0, 0x9f, 0xb4, 0x84, 0xb5, 0x69, 0xcf, 0xf5, - 0x6d, 0xaf, 0x06, 0x82, 0x47, 0x4e, 0x30, 0xe6, 0xbb, 0x2f, 0xc3, 0x20, 0xe2, 0x2c, 0x7a, 0xc0, - 0x79, 0x54, 0x2b, 0x0a, 0x67, 0x0e, 0xd1, 0x48, 0x0b, 0x4a, 0xdb, 0x76, 0xfb, 0x19, 0x3b, 0x38, - 0x45, 0x62, 0x82, 0x9f, 0xd2, 0x2a, 0x96, 0x60, 0x7f, 0x1c, 0xea, 0xc0, 0x49, 0xd7, 0x40, 0xda, - 0x50, 0x49, 0x8e, 0x2e, 0xf3, 0xb0, 0x56, 0x16, 0x3a, 0xef, 0xcd, 0xeb, 0x4a, 0x29, 0x2d, 0x4d, - 0x8c, 0xa8, 0xc4, 0x40, 0xee, 0x62, 0xca, 0xd9, 0x9c, 0xd5, 0x2a, 0xe2, 0xcc, 0xfd, 0xb9, 0x79, - 0x1f, 0xaa, 0xa3, 0xd1, 0x98, 0x07, 0xaf, 0x98, 0x3f, 0x84, 0x37, 0x26, 0x6c, 0xe1, 0xb5, 0x6a, - 0xc2, 0x1f, 0x0d, 0xb8, 0x34, 0xe6, 0x37, 0xac, 0xcb, 0x22, 0x17, 0xa5, 0x4a, 0x31, 0x26, 0x47, - 0xb0, 0x84, 0x71, 0x89, 0x55, 0x87, 0xde, 0x9c, 0x27, 0x10, 0x75, 0x21, 0x29, 0x1d, 0x26, 0xb5, - 0x98, 0x77, 0x00, 0x06, 0xc4, 0xb9, 0x50, 0xdb, 0x17, 0x50, 0x56, 0x51, 0x51, 0x09, 0x5e, 0x95, - 0xcd, 0x5e, 0x09, 0x63, 0x33, 0x1f, 0xb4, 0x8c, 0xcc, 0x9c, 0x2d, 0xc3, 0xfa, 0x0a, 0x56, 0x28, - 0xb3, 0x9d, 0x3d, 0xd7, 0x63, 0x17, 0x57, 0x46, 0xcc, 0x56, 0xd7, 0x63, 0x2d, 0x04, 0x0c, 0x49, - 0xb6, 0xaa, 0x39, 0xb9, 0x0b, 0x4b, 0xd4, 0xf6, 0xbb, 0x4c, 0x99, 0x7e, 0x2f, 0xc5, 0xb4, 0x30, - 0x82, 0xbc, 0x54, 0x8a, 0x58, 0xf7, 0xa0, 0xd0, 0xa7, 0x61, 0xad, 0x79, 0xdc, 0xe9, 0xc4, 0x4c, - 0xd6, 0xad, 0x0c, 0x55, 0x33, 0xa4, 0x1f, 0x32, 0xbf, 0xab, 0x4c, 0x67, 0xa8, 0x9a, 0x59, 0x6b, - 0x88, 0xb2, 0x93, 0x9d, 0x2b, 0xd7, 0x10, 0xc8, 0xee, 0x20, 0xaa, 0x32, 0x44, 0x82, 0x89, 0xb1, - 0xe5, 0x60, 0xab, 0xb3, 0x9d, 0x1d, 0x37, 0xba, 0xf8, 0x80, 0x35, 0xc8, 0xed, 0xb8, 0x91, 0x76, - 0xbe, 0x64, 0x4a, 0xd6, 0xb0, 0x09, 0xb6, 0xbd, 0x9e, 0x83, 0xa7, 0xe5, 0x2c, 0xf2, 0x55, 0xb5, - 0x1f, 0xa1, 0x5a, 0x9f, 0x48, 0x3f, 0x0a, 0x2b, 0x6a, 0x33, 0x37, 0x20, 0xc7, 0x7c, 0x1e, 0xb9, - 0x2c, 0xe9, 0x94, 0xa4, 0x2e, 0x1f, 0xa0, 0x75, 0xf1, 0x00, 0x15, 0x1d, 0x99, 0x26, 0x2c, 0xd6, - 0x26, 0xac, 0x20, 0x21, 0x3d, 0x10, 0x04, 0xb2, 0xda, 0x26, 0xc5, 0xd8, 0xba, 0x0b, 0xd5, 0x81, - 0xa0, 0x32, 0xbd, 0x06, 0x59, 0x84, 0x8c, 0xaa, 0x10, 0x4f, 0xb2, 0x2b, 0xd6, 0xad, 0x6b, 0xb0, - 0x92, 0x64, 0xeb, 0x85, 0x46, 0x2d, 0x02, 0xd5, 0x01, 0x93, 0x42, 0x0b, 0x65, 0x28, 0xb6, 0x5c, - 0x3f, 0x69, 0xa6, 0xd6, 0x2b, 0x03, 0x4a, 0xad, 0xc0, 0x1f, 0x34, 0xa1, 0x16, 0xac, 0x24, 0xa9, - 0xfb, 0xa0, 0x75, 0xb0, 0x6d, 0x87, 0x89, 0x0f, 0x56, 0xc7, 0xef, 0x87, 0x7a, 0xc2, 0xd7, 0x25, - 0xe3, 0x56, 0x16, 0xfb, 0x15, 0x1d, 0x15, 0x27, 0x9f, 0x42, 0xee, 0xf0, 0x70, 0x4b, 0x68, 0x5a, - 0x9c, 0x4b, 0x53, 0x22, 0x46, 0xee, 0x43, 0xee, 0xa9, 0xf8, 0xb2, 0x10, 0xab, 0x9e, 0x32, 0xe1, - 0xae, 0x4a, 0x0f, 0x49, 0x36, 0xca, 0xda, 0x41, 0xe4, 0xd0, 0x44, 0xc8, 0xfa, 0xb7, 0x01, 0xc5, - 0xa7, 0xf6, 0x00, 0xa8, 0x0d, 0x90, 0xe1, 0x6b, 0x34, 0x5a, 0x85, 0x0c, 0x2f, 0xc3, 0x92, 0xc7, - 0x5e, 0x30, 0x4f, 0xdd, 0x71, 0x39, 0x41, 0x6a, 0xfc, 0x2c, 0x88, 0x64, 0x5a, 0x97, 0xa8, 0x9c, - 0x60, 0x42, 0x38, 0x8c, 0xdb, 0xae, 0x57, 0xcb, 0xae, 0x66, 0xb0, 0x29, 0xcb, 0x19, 0x46, 0xae, - 0x17, 0x79, 0x0a, 0xae, 0xe3, 0x90, 0x58, 0x90, 0x75, 0xfd, 0x4e, 0x20, 0x1a, 0x96, 0x2a, 0x8b, - 0xc7, 0x41, 0x2f, 0x6a, 0xb3, 0x03, 0xbf, 0x13, 0x50, 0xb1, 0x46, 0xae, 0xc2, 0x72, 0x84, 0xf9, - 0x17, 0xd7, 0x72, 0xc2, 0x29, 0x05, 0xe4, 0x92, 0x59, 0xaa, 0x16, 0xac, 0x0a, 0x94, 0xe4, 0xb9, - 0x55, 0xf0, 0x7f, 0xbd, 0x08, 0x6f, 0x3c, 0x62, 0x67, 0xdb, 0xc9, 0xb9, 0x12, 0x87, 0xac, 0x42, - 0xb1, 0x4f, 0x3b, 0xd8, 0x51, 0x57, 0x48, 0x27, 0xa1, 0xb1, 0xa3, 0xa0, 0xe7, 0xf3, 0x24, 0x86, - 0xc2, 0x98, 0xa0, 0x50, 0xb5, 0x40, 0xde, 0x87, 0xdc, 0x23, 0xc6, 0xcf, 0x82, 0xe8, 0xb9, 0x38, - 0x75, 0xa5, 0x59, 0x44, 0x9e, 0x47, 0x8c, 0x23, 0xae, 0xa2, 0xc9, 0x1a, 0x82, 0xb5, 0x30, 0x01, - 0x6b, 0xd9, 0x49, 0x60, 0x2d, 0x59, 0x25, 0x9b, 0x50, 0x6c, 0x07, 0x7e, 0xcc, 0x23, 0xdb, 0x45, - 0xc3, 0x4b, 0x82, 0xf9, 0x4d, 0x64, 0x96, 0x81, 0xdd, 0x1e, 0x2c, 0x52, 0x9d, 0x93, 0x6c, 0x00, - 0xb0, 0x97, 0x3c, 0xb2, 0xf7, 0x83, 0xb8, 0xff, 0xb0, 0x01, 0x94, 0x43, 0xc2, 0x41, 0x8b, 0x6a, - 0xab, 0xd6, 0x5b, 0x70, 0x79, 0xd8, 0x23, 0xca, 0x55, 0xf7, 0xe0, 0xff, 0x28, 0xf3, 0x98, 0x1d, - 0xb3, 0xf9, 0xbd, 0x65, 0x99, 0x50, 0x1b, 0x17, 0x56, 0x8a, 0xff, 0x93, 0x81, 0xe2, 0xee, 0x4b, - 0xd6, 0x3e, 0x62, 0x71, 0x6c, 0x77, 0x05, 0x64, 0x6c, 0x45, 0x41, 0x9b, 0xc5, 0x71, 0x5f, 0xd7, - 0x80, 0x40, 0xbe, 0x0f, 0xd9, 0x03, 0xdf, 0xe5, 0xaa, 0x3f, 0xae, 0xa5, 0x22, 0x76, 0x97, 0x2b, - 0x9d, 0xfb, 0x0b, 0x54, 0x48, 0x91, 0xbb, 0x90, 0xc5, 0xea, 0x32, 0x4b, 0x85, 0x77, 0x34, 0x59, - 0x94, 0x21, 0x5b, 0xe2, 0xcb, 0x9a, 0xfb, 0x25, 0x53, 0x51, 0x5a, 0x4f, 0x6f, 0x4d, 0xee, 0x97, - 0x6c, 0xa0, 0x41, 0x49, 0x92, 0x5d, 0xc8, 0x1d, 0x73, 0x3b, 0xe2, 0xcc, 0x51, 0xd1, 0xbb, 0x9e, - 0x86, 0x60, 0x24, 0xe7, 0x40, 0x4b, 0x22, 0x8b, 0x4e, 0xd8, 0x7d, 0xe9, 0x72, 0x95, 0x0d, 0x69, - 0x4e, 0x40, 0x36, 0xed, 0x20, 0x38, 0x45, 0xe9, 0x9d, 0xc0, 0x67, 0xb5, 0xdc, 0x54, 0x69, 0x64, - 0xd3, 0xa4, 0x71, 0x8a, 0x6e, 0x38, 0x76, 0xbb, 0x08, 0x0c, 0xf3, 0x53, 0xdd, 0x20, 0x19, 0x35, - 0x37, 0x48, 0xc2, 0x56, 0x0e, 0x96, 0x04, 0x0c, 0xb2, 0x7e, 0x6b, 0x40, 0x51, 0x8b, 0xd3, 0x0c, - 0x79, 0xf7, 0x0e, 0x64, 0xf1, 0x55, 0xad, 0xe2, 0x9f, 0x17, 0x59, 0xc7, 0xb8, 0x4d, 0x05, 0x15, - 0x0b, 0xc7, 0x9e, 0x23, 0x8b, 0x62, 0x99, 0xe2, 0x10, 0x29, 0x4f, 0xf8, 0xb9, 0x08, 0x59, 0x9e, - 0xe2, 0x90, 0xdc, 0x80, 0xfc, 0x31, 0x6b, 0xf7, 0x22, 0x97, 0x9f, 0x8b, 0x20, 0x54, 0x9a, 0x55, - 0x51, 0x4e, 0x14, 0x4d, 0x24, 0x67, 0x9f, 0xc3, 0x7a, 0x88, 0x97, 0x73, 0xb0, 0x41, 0x02, 0xd9, - 0x6d, 0x7c, 0x28, 0xe1, 0xce, 0xca, 0x54, 0x8c, 0xf1, 0xad, 0xba, 0x3b, 0xed, 0xad, 0xba, 0x9b, - 0xbc, 0x55, 0x87, 0x83, 0x8a, 0xdd, 0x47, 0x73, 0xb2, 0xf5, 0x00, 0x0a, 0xfd, 0x8b, 0x47, 0x2a, - 0xb0, 0xb8, 0xe7, 0x28, 0x4b, 0x8b, 0x7b, 0x0e, 0x1e, 0x65, 0xf7, 0xf1, 0x9e, 0xb0, 0x92, 0xa7, - 0x38, 0xec, 0x83, 0x84, 0x8c, 0x06, 0x12, 0x36, 0xf1, 0x15, 0xae, 0xdd, 0x3e, 0x64, 0xa2, 0xc1, - 0x59, 0x9c, 0x6c, 0x19, 0xc7, 0xf2, 0x18, 0x5e, 0x2c, 0x74, 0x89, 0x63, 0x78, 0xb1, 0x75, 0x0d, - 0xca, 0x43, 0xf1, 0x42, 0x26, 0xf1, 0xec, 0x53, 0x58, 0x12, 0xc7, 0x1b, 0x0c, 0x56, 0x46, 0xbe, - 0x04, 0x91, 0xf7, 0x61, 0x59, 0x7e, 0x71, 0xa8, 0x2e, 0x98, 0x6f, 0x7f, 0xfd, 0xcd, 0xea, 0x9b, - 0x23, 0x0c, 0x72, 0x11, 0xd9, 0xb6, 0x7a, 0xbe, 0xe3, 0xb1, 0xaa, 0x31, 0x91, 0x4d, 0x2e, 0x9a, - 0xd9, 0x5f, 0xfd, 0xfe, 0xca, 0xc2, 0x86, 0x0d, 0x97, 0xc6, 0xbe, 0x62, 0x90, 0x6b, 0x90, 0x3d, - 0x66, 0x5e, 0x27, 0x31, 0x33, 0xc6, 0x80, 0x8b, 0xe4, 0x2a, 0x64, 0xa8, 0x7d, 0x56, 0x35, 0xcc, - 0xda, 0xd7, 0xdf, 0xac, 0x5e, 0x1e, 0xff, 0x14, 0x62, 0x9f, 0x49, 0x13, 0xcd, 0xbf, 0x00, 0x14, - 0x0e, 0x0f, 0xb7, 0xb6, 0x22, 0xd7, 0xe9, 0x32, 0xf2, 0x4b, 0x03, 0xc8, 0xf8, 0x4b, 0x94, 0xdc, - 0x4e, 0xcf, 0xf1, 0xc9, 0x0f, 0x72, 0xf3, 0xe3, 0x39, 0xa5, 0x14, 0xd2, 0xf8, 0x1c, 0x96, 0x04, - 0x3c, 0x26, 0x1f, 0xcc, 0xf8, 0xac, 0x31, 0xd7, 0xa7, 0x33, 0x2a, 0xdd, 0x6d, 0xc8, 0x27, 0x10, - 0x93, 0x6c, 0xa4, 0x6e, 0x6f, 0x08, 0x41, 0x9b, 0x1f, 0xce, 0xc4, 0xab, 0x8c, 0xfc, 0x14, 0x72, - 0x0a, 0x39, 0x92, 0xeb, 0x53, 0xe4, 0x06, 0x18, 0xd6, 0xdc, 0x98, 0x85, 0x75, 0x70, 0x8c, 0x04, - 0x21, 0xa6, 0x1e, 0x63, 0x04, 0x7f, 0xa6, 0x1e, 0x63, 0x0c, 0x72, 0xb6, 0x07, 0x0f, 0xc1, 0x54, - 0x23, 0x23, 0x78, 0x33, 0xd5, 0xc8, 0x28, 0xec, 0x24, 0x4f, 0x21, 0x8b, 0xb0, 0x93, 0xa4, 0x95, - 0x5f, 0x0d, 0x97, 0x9a, 0x69, 0x77, 0x62, 0x08, 0xaf, 0xfe, 0x04, 0xdb, 0x94, 0x78, 0xf3, 0xa7, - 0x37, 0x28, 0xed, 0x43, 0x9d, 0x79, 0x7d, 0x06, 0xce, 0x81, 0x7a, 0xf5, 0x5e, 0x5e, 0x9f, 0xe1, - 0x6b, 0xd9, 0x74, 0xf5, 0x23, 0xdf, 0xe5, 0x02, 0x28, 0xe9, 0xe8, 0x83, 0xd4, 0x53, 0x44, 0x27, - 0x00, 0x37, 0xb3, 0x31, 0x33, 0xbf, 0x32, 0xf8, 0x15, 0xbe, 0xbd, 0x86, 0x91, 0x09, 0x69, 0xa6, - 0xba, 0x63, 0x22, 0x06, 0x32, 0x6f, 0xcd, 0x25, 0xa3, 0x8c, 0xdb, 0x12, 0xf9, 0x28, 0x74, 0x43, - 0xd2, 0x1b, 0x79, 0x1f, 0x21, 0x99, 0x33, 0xf2, 0xad, 0x1b, 0x37, 0x0d, 0xbc, 0x67, 0x88, 0x78, - 0x53, 0x75, 0x6b, 0x4f, 0x81, 0xd4, 0x7b, 0xa6, 0x43, 0xe7, 0xad, 0xd2, 0xb7, 0xaf, 0xae, 0x18, - 0x7f, 0x7f, 0x75, 0xc5, 0xf8, 0xd7, 0xab, 0x2b, 0xc6, 0xc9, 0xb2, 0xf8, 0xfb, 0xf1, 0xd6, 0x7f, - 0x03, 0x00, 0x00, 0xff, 0xff, 0x5c, 0x01, 0xa5, 0x69, 0xd0, 0x1d, 0x00, 0x00, + 0x03, 0xdf, 0x8d, 0xb9, 0xeb, 0x76, 0xdd, 0x7a, 0x27, 0x16, 0x32, 0xd2, 0x0a, 0x1e, 0x42, 0xb2, + 0x5b, 0x7f, 0xcb, 0xc2, 0x32, 0x65, 0x71, 0xcf, 0xe3, 0x64, 0x1d, 0x4a, 0x11, 0xeb, 0xec, 0xb2, + 0x30, 0x62, 0x6d, 0x9b, 0x33, 0xa7, 0x6a, 0xac, 0x19, 0x1b, 0xf9, 0x83, 0x05, 0x3a, 0x4c, 0x26, + 0x3f, 0x82, 0x72, 0xc4, 0x3a, 0xb1, 0xc6, 0xb8, 0xb8, 0x66, 0x6c, 0x14, 0x1a, 0x1f, 0xd6, 0x2e, + 0x0c, 0x46, 0x8d, 0xb2, 0xce, 0x91, 0x1d, 0x0e, 0x44, 0x0e, 0x16, 0xe8, 0x88, 0x12, 0xd2, 0x80, + 0x4c, 0xc4, 0x3a, 0xd5, 0x8c, 0xd0, 0x75, 0x25, 0x5d, 0xd7, 0xc1, 0x02, 0x45, 0x66, 0xb2, 0x05, + 0x59, 0xd4, 0x52, 0xcd, 0x0a, 0xa1, 0xab, 0x53, 0x37, 0x70, 0xb0, 0x40, 0x85, 0x00, 0x79, 0x08, + 0xb9, 0x53, 0xc6, 0x6d, 0xc7, 0xe6, 0x76, 0x15, 0xd6, 0x32, 0x1b, 0x85, 0x46, 0x3d, 0x55, 0x18, + 0x1d, 0x54, 0x3b, 0x52, 0x12, 0x7b, 0x3e, 0x8f, 0xce, 0x69, 0x5f, 0x01, 0x79, 0x0a, 0x45, 0x9b, + 0x73, 0x86, 0x5e, 0x75, 0x03, 0x3f, 0xae, 0x16, 0x85, 0xc2, 0x5b, 0xd3, 0x15, 0x3e, 0xd0, 0xa4, + 0xa4, 0xd2, 0x21, 0x45, 0xe6, 0x3d, 0x28, 0x0d, 0xd9, 0x24, 0x15, 0xc8, 0x3c, 0x67, 0xe7, 0x32, + 0x30, 0x14, 0x87, 0xe4, 0x32, 0x2c, 0xbd, 0xb0, 0xbd, 0x1e, 0x13, 0x31, 0x28, 0x52, 0x39, 0xb9, + 0xbb, 0x78, 0xc7, 0x30, 0x9f, 0xc1, 0xa5, 0x31, 0xfd, 0x13, 0x14, 0xfc, 0x40, 0x57, 0x50, 0x68, + 0x7c, 0x90, 0xb2, 0x6b, 0x5d, 0x9d, 0x66, 0x69, 0x3b, 0x07, 0xcb, 0x91, 0x38, 0x90, 0xf5, 0x1b, + 0x03, 0x2a, 0xa3, 0xa1, 0x26, 0x4d, 0x15, 0x24, 0x43, 0xb8, 0xe5, 0xe3, 0x39, 0x6e, 0x09, 0x12, + 0x94, 0x63, 0x84, 0x0a, 0x73, 0x0b, 0xf2, 0x7d, 0xd2, 0x34, 0x67, 0xe4, 0xb5, 0x2d, 0x5a, 0x5b, + 0x90, 0xa1, 0xac, 0x43, 0xca, 0xb0, 0xe8, 0xaa, 0x7b, 0x4d, 0x17, 0x5d, 0x87, 0xac, 0x41, 0xc6, + 0x61, 0x1d, 0x75, 0xf4, 0x72, 0x2d, 0x3c, 0xa9, 0xed, 0xb2, 0x8e, 0xeb, 0xbb, 0x78, 0x44, 0x8a, + 0x4b, 0xd6, 0xef, 0x0c, 0xcc, 0x0f, 0xdc, 0x16, 0xf9, 0x64, 0xe8, 0x1c, 0xd3, 0x6f, 0xfb, 0xd8, + 0xee, 0x9f, 0xa6, 0xef, 0xfe, 0xf6, 0x70, 0x24, 0xa6, 0xa4, 0x80, 0x7e, 0xba, 0x1f, 0x43, 0x51, + 0x8f, 0x0d, 0x39, 0x80, 0x82, 0x76, 0x8f, 0xd4, 0x86, 0xd7, 0x67, 0x8b, 0x2c, 0xd5, 0x45, 0xad, + 0x3f, 0x64, 0xa0, 0xa0, 0x2d, 0x92, 0xfb, 0x90, 0x7d, 0xee, 0xfa, 0xd2, 0x85, 0xe5, 0xc6, 0xe6, + 0x6c, 0x2a, 0x1f, 0xba, 0xbe, 0x43, 0x85, 0x1c, 0x69, 0x69, 0x79, 0xb7, 0x28, 0xb6, 0x75, 0x7b, + 0x36, 0x1d, 0x17, 0x26, 0xdf, 0xcd, 0x39, 0xca, 0x86, 0x2c, 0x1a, 0x04, 0xb2, 0xa1, 0xcd, 0x9f, + 0x89, 0xa2, 0x91, 0xa7, 0x62, 0x4c, 0x6e, 0xc2, 0x1b, 0xae, 0xff, 0x24, 0xe0, 0x41, 0x2b, 0x62, + 0x8e, 0x8b, 0x97, 0xef, 0xc9, 0x79, 0xc8, 0xaa, 0x4b, 0x82, 0x65, 0xd2, 0x12, 0x69, 0x41, 0x59, + 0x92, 0x8f, 0x7b, 0x27, 0x3f, 0x63, 0x6d, 0x1e, 0x57, 0x97, 0xc5, 0x79, 0x36, 0x52, 0xb6, 0xd0, + 0xd4, 0x05, 0xe8, 0x88, 0xfc, 0x6b, 0x65, 0xbb, 0xf5, 0x27, 0x03, 0x4a, 0x43, 0xea, 0xc9, 0xa7, + 0x43, 0xa1, 0xba, 0x31, 0xeb, 0xb6, 0xb4, 0x60, 0x7d, 0x06, 0xcb, 0x8e, 0xdb, 0x65, 0x31, 0x17, + 0xa1, 0xca, 0x6f, 0x37, 0xbe, 0xfd, 0xee, 0xdd, 0x85, 0x7f, 0x7c, 0xf7, 0xee, 0xa6, 0xd6, 0x62, + 0x82, 0x90, 0xf9, 0xed, 0xc0, 0xe7, 0xb6, 0xeb, 0xb3, 0x08, 0x3b, 0xe5, 0x47, 0x52, 0xa4, 0xb6, + 0x2b, 0x7e, 0xa8, 0xd2, 0x80, 0x4e, 0xf7, 0xed, 0x53, 0x26, 0xe2, 0x94, 0xa7, 0x62, 0x6c, 0x71, + 0x28, 0x51, 0xc6, 0x7b, 0x91, 0x4f, 0xd9, 0xcf, 0x7b, 0xc8, 0xf4, 0xbd, 0xa4, 0x90, 0x88, 0x4d, + 0x4f, 0x2b, 0xe8, 0xc8, 0x48, 0x95, 0x00, 0xd9, 0x80, 0x25, 0x16, 0x45, 0x41, 0xa4, 0x92, 0x87, + 0xd4, 0x64, 0xcf, 0xae, 0x45, 0x61, 0xbb, 0x76, 0x2c, 0x7a, 0x36, 0x95, 0x0c, 0x56, 0x05, 0xca, + 0x89, 0xd5, 0x38, 0x0c, 0xfc, 0x98, 0x59, 0xab, 0xe8, 0xba, 0xb0, 0xc7, 0x63, 0xb5, 0x0f, 0xeb, + 0xaf, 0x06, 0x94, 0x13, 0x8a, 0xe4, 0x21, 0x5f, 0x40, 0x61, 0x50, 0x1a, 0x92, 0x1a, 0x70, 0x37, + 0xd5, 0xa9, 0xba, 0xbc, 0x56, 0x57, 0x54, 0x49, 0xd0, 0xd5, 0x99, 0x8f, 0xa0, 0x32, 0xca, 0x30, + 0x21, 0xfa, 0xef, 0x0d, 0x17, 0x88, 0xd1, 0x7a, 0xa5, 0xdd, 0x86, 0x7f, 0x19, 0xf0, 0x36, 0x65, + 0x02, 0x84, 0x34, 0x4f, 0xed, 0x2e, 0xdb, 0x09, 0xfc, 0x8e, 0xdb, 0x4d, 0xdc, 0x5c, 0x11, 0xc5, + 0x30, 0xd1, 0x8c, 0x75, 0x71, 0x03, 0x72, 0x2d, 0xcf, 0xe6, 0x9d, 0x20, 0x3a, 0x55, 0xca, 0x8b, + 0xa8, 0x3c, 0xa1, 0xd1, 0xfe, 0x2a, 0x59, 0x83, 0x82, 0x52, 0x7c, 0x14, 0x38, 0x49, 0x38, 0x75, + 0x12, 0xa9, 0xc2, 0xca, 0x61, 0xd0, 0x7d, 0x84, 0xc1, 0x96, 0x19, 0x96, 0x4c, 0x89, 0x05, 0x45, + 0xc5, 0x18, 0xf5, 0xb3, 0x6b, 0x89, 0x0e, 0xd1, 0xc8, 0x3b, 0x90, 0x3f, 0x66, 0x71, 0xec, 0x06, + 0x7e, 0x73, 0xb7, 0xba, 0x2c, 0xe4, 0x07, 0x04, 0xd4, 0x7d, 0xcc, 0x83, 0x88, 0x35, 0x77, 0xab, + 0x2b, 0x52, 0xb7, 0x9a, 0x5a, 0xbf, 0x30, 0xc0, 0x9c, 0x74, 0x62, 0x15, 0xbe, 0xcf, 0x60, 0x59, + 0x5e, 0x48, 0x79, 0xea, 0xff, 0xed, 0x2a, 0xcb, 0x5f, 0xf2, 0x16, 0x2c, 0x4b, 0xed, 0x2a, 0x0b, + 0xd5, 0xcc, 0xfa, 0xf3, 0x12, 0x14, 0x8f, 0x71, 0x03, 0x89, 0x9f, 0x6b, 0x00, 0x83, 0xf0, 0xa8, + 0x2b, 0x3d, 0x1a, 0x34, 0x8d, 0x83, 0x98, 0x90, 0xdb, 0x57, 0xd7, 0x47, 0x75, 0xb0, 0xfe, 0x9c, + 0x7c, 0x0e, 0x85, 0x64, 0xfc, 0x38, 0xe4, 0xd5, 0x8c, 0xb8, 0x7f, 0x77, 0x52, 0xee, 0x9f, 0xbe, + 0x93, 0x9a, 0x26, 0xaa, 0x6e, 0x9f, 0x46, 0x21, 0x37, 0xe0, 0x92, 0xed, 0x79, 0xc1, 0x99, 0x4a, + 0x29, 0x91, 0x1c, 0x22, 0x38, 0x39, 0x3a, 0xbe, 0x80, 0xa5, 0x52, 0x23, 0x3e, 0x88, 0x22, 0xfb, + 0x1c, 0x6f, 0xd3, 0xb2, 0xe0, 0x9f, 0xb4, 0x84, 0x55, 0x6b, 0xdf, 0xf5, 0x6d, 0xaf, 0x0a, 0x82, + 0x47, 0x4e, 0xf0, 0x36, 0xec, 0xbd, 0x0c, 0x83, 0x88, 0xb3, 0xe8, 0x01, 0xe7, 0x51, 0xb5, 0x20, + 0x9c, 0x39, 0x44, 0x23, 0x2d, 0x28, 0xee, 0xd8, 0xed, 0x67, 0xac, 0x79, 0x8a, 0xc4, 0x04, 0x59, + 0xa5, 0xd5, 0x32, 0xc1, 0xfe, 0x38, 0xd4, 0x21, 0x95, 0xae, 0x81, 0xb4, 0xa1, 0x9c, 0x1c, 0x5d, + 0x66, 0x68, 0xb5, 0x24, 0x74, 0xde, 0x9b, 0xd7, 0x95, 0x52, 0x5a, 0x9a, 0x18, 0x51, 0x89, 0x81, + 0xdc, 0xc3, 0x64, 0xb4, 0x39, 0xab, 0x96, 0xc5, 0x99, 0xfb, 0x73, 0xf3, 0x3e, 0x54, 0x46, 0xa3, + 0x31, 0x0f, 0x92, 0x31, 0x7f, 0x08, 0x6f, 0x4c, 0xd8, 0xc2, 0x6b, 0x55, 0x8b, 0x3f, 0x1a, 0x70, + 0x69, 0xcc, 0x6f, 0x58, 0xb1, 0x45, 0x96, 0x4a, 0x95, 0x62, 0x4c, 0x8e, 0x60, 0x09, 0xe3, 0x12, + 0xab, 0xde, 0xbd, 0x35, 0x4f, 0x20, 0x6a, 0x42, 0x52, 0x3a, 0x4c, 0x6a, 0x31, 0xef, 0x00, 0x0c, + 0x88, 0x73, 0xe1, 0xb9, 0x2f, 0xa0, 0xa4, 0xa2, 0xa2, 0x12, 0xbc, 0x22, 0x61, 0x80, 0x12, 0xc6, + 0x36, 0x3f, 0x68, 0x26, 0x99, 0x39, 0x9b, 0x89, 0xf5, 0x15, 0xac, 0x52, 0x66, 0x3b, 0xfb, 0xae, + 0xc7, 0x2e, 0xae, 0x99, 0x98, 0xad, 0xae, 0xc7, 0x5a, 0x08, 0x25, 0x92, 0x6c, 0x55, 0x73, 0x72, + 0x17, 0x96, 0xa8, 0xed, 0x77, 0x99, 0x32, 0xfd, 0x5e, 0x8a, 0x69, 0x61, 0x04, 0x79, 0xa9, 0x14, + 0xb1, 0xee, 0x41, 0xbe, 0x4f, 0xc3, 0x5a, 0xf3, 0xb8, 0xd3, 0x89, 0x99, 0xac, 0x5b, 0x19, 0xaa, + 0x66, 0x48, 0x3f, 0x64, 0x7e, 0x57, 0x99, 0xce, 0x50, 0x35, 0xb3, 0xd6, 0x11, 0x7f, 0x27, 0x3b, + 0x57, 0xae, 0x21, 0x90, 0xdd, 0x45, 0xbc, 0x65, 0x88, 0x04, 0x13, 0x63, 0xcb, 0xc1, 0x26, 0x68, + 0x3b, 0xbb, 0x6e, 0x74, 0xf1, 0x01, 0xab, 0xb0, 0xb2, 0xeb, 0x46, 0xda, 0xf9, 0x92, 0x29, 0x59, + 0xc7, 0xf6, 0xd8, 0xf6, 0x7a, 0x0e, 0x9e, 0x96, 0xb3, 0xc8, 0x57, 0x7d, 0x60, 0x84, 0x6a, 0x7d, + 0x22, 0xfd, 0x28, 0xac, 0xa8, 0xcd, 0xdc, 0x80, 0x15, 0xe6, 0xf3, 0xc8, 0x65, 0x49, 0x0f, 0x25, + 0x35, 0xf9, 0x34, 0xad, 0x89, 0xa7, 0xa9, 0xe8, 0xd5, 0x34, 0x61, 0xb1, 0xb6, 0x60, 0x15, 0x09, + 0xe9, 0x81, 0x20, 0x90, 0xd5, 0x36, 0x29, 0xc6, 0xd6, 0x5d, 0xa8, 0x0c, 0x04, 0x95, 0xe9, 0x75, + 0xc8, 0x22, 0x98, 0x54, 0x85, 0x78, 0x92, 0x5d, 0xb1, 0x6e, 0x5d, 0x83, 0xd5, 0x24, 0x5b, 0x2f, + 0x34, 0x6a, 0x11, 0xa8, 0x0c, 0x98, 0x14, 0x8e, 0x28, 0x41, 0xa1, 0xe5, 0xfa, 0x49, 0x9b, 0xb5, + 0x5e, 0x19, 0x50, 0x6c, 0x05, 0xfe, 0xa0, 0x09, 0xb5, 0x60, 0x35, 0x49, 0xdd, 0x07, 0xad, 0xe6, + 0x8e, 0x1d, 0x26, 0x3e, 0x58, 0x1b, 0xbf, 0x1f, 0xea, 0x71, 0x5f, 0x93, 0x8c, 0xdb, 0x59, 0xec, + 0x57, 0x74, 0x54, 0x9c, 0x7c, 0x0a, 0x2b, 0x87, 0x87, 0xdb, 0x42, 0xd3, 0xe2, 0x5c, 0x9a, 0x12, + 0x31, 0x72, 0x1f, 0x56, 0x9e, 0x8a, 0x6f, 0x0e, 0xb1, 0xea, 0x29, 0x13, 0xee, 0xaa, 0xf4, 0x90, + 0x64, 0xa3, 0xac, 0x1d, 0x44, 0x0e, 0x4d, 0x84, 0xac, 0x7f, 0x1b, 0x50, 0x78, 0x6a, 0x0f, 0x20, + 0xdc, 0x00, 0x33, 0xbe, 0x46, 0xa3, 0x55, 0x98, 0xf1, 0x32, 0x2c, 0x79, 0xec, 0x05, 0xf3, 0xd4, + 0x1d, 0x97, 0x13, 0xa4, 0xc6, 0xcf, 0x82, 0x48, 0xa6, 0x75, 0x91, 0xca, 0x09, 0x26, 0x84, 0xc3, + 0xb8, 0xed, 0x7a, 0xd5, 0xec, 0x5a, 0x06, 0x9b, 0xb2, 0x9c, 0x61, 0xe4, 0x7a, 0x91, 0xa7, 0x80, + 0x3c, 0x0e, 0x89, 0x05, 0x59, 0xd7, 0xef, 0x04, 0xa2, 0x61, 0xa9, 0xb2, 0x78, 0x1c, 0xf4, 0xa2, + 0x36, 0x6b, 0xfa, 0x9d, 0x80, 0x8a, 0x35, 0x72, 0x15, 0x96, 0x23, 0xcc, 0xbf, 0xb8, 0xba, 0x22, + 0x9c, 0x92, 0x47, 0x2e, 0x99, 0xa5, 0x6a, 0xc1, 0x2a, 0x43, 0x51, 0x9e, 0x5b, 0x05, 0xff, 0xd7, + 0x8b, 0xf0, 0xc6, 0x23, 0x76, 0xb6, 0x93, 0x9c, 0x2b, 0x71, 0xc8, 0x1a, 0x14, 0xfa, 0xb4, 0xe6, + 0xae, 0xba, 0x42, 0x3a, 0x09, 0x8d, 0x1d, 0x05, 0x3d, 0x9f, 0x27, 0x31, 0x14, 0xc6, 0x04, 0x85, + 0xaa, 0x05, 0xf2, 0x3e, 0xac, 0x3c, 0x62, 0xfc, 0x2c, 0x88, 0x9e, 0x8b, 0x53, 0x97, 0x1b, 0x05, + 0xe4, 0x79, 0xc4, 0x38, 0x22, 0x2e, 0x9a, 0xac, 0x21, 0x8c, 0x0b, 0x13, 0x18, 0x97, 0x9d, 0x04, + 0xe3, 0x92, 0x55, 0xb2, 0x05, 0x85, 0x76, 0xe0, 0xc7, 0x3c, 0xb2, 0x5d, 0x34, 0xbc, 0x24, 0x98, + 0xdf, 0x44, 0x66, 0x19, 0xd8, 0x9d, 0xc1, 0x22, 0xd5, 0x39, 0xc9, 0x26, 0x00, 0x7b, 0xc9, 0x23, + 0xfb, 0x20, 0x88, 0xfb, 0x4f, 0x1e, 0x40, 0x39, 0x24, 0x34, 0x5b, 0x54, 0x5b, 0xb5, 0xde, 0x82, + 0xcb, 0xc3, 0x1e, 0x51, 0xae, 0xba, 0x07, 0xff, 0x47, 0x99, 0xc7, 0xec, 0x98, 0xcd, 0xef, 0x2d, + 0xcb, 0x84, 0xea, 0xb8, 0xb0, 0x52, 0xfc, 0x9f, 0x0c, 0x14, 0xf6, 0x5e, 0xb2, 0xf6, 0x11, 0x8b, + 0x63, 0xbb, 0x2b, 0xc0, 0x64, 0x2b, 0x0a, 0xda, 0x2c, 0x8e, 0xfb, 0xba, 0x06, 0x04, 0xf2, 0x7d, + 0xc8, 0x36, 0x7d, 0x97, 0xab, 0xfe, 0xb8, 0x9e, 0x8a, 0xe5, 0x5d, 0xae, 0x74, 0x1e, 0x2c, 0x50, + 0x21, 0x45, 0xee, 0x42, 0x16, 0xab, 0xcb, 0x2c, 0x15, 0xde, 0xd1, 0x64, 0x51, 0x86, 0x6c, 0x8b, + 0x6f, 0x6e, 0xee, 0x97, 0x4c, 0x45, 0x69, 0x23, 0xbd, 0x35, 0xb9, 0x5f, 0xb2, 0x81, 0x06, 0x25, + 0x49, 0xf6, 0x10, 0x0a, 0xdb, 0x11, 0x67, 0x8e, 0x8a, 0xde, 0xf5, 0x34, 0x04, 0x23, 0x39, 0x07, + 0x5a, 0x12, 0x59, 0x74, 0xc2, 0xde, 0x4b, 0x97, 0xab, 0x6c, 0x48, 0x73, 0x02, 0xb2, 0x69, 0x07, + 0xc1, 0x29, 0x4a, 0xef, 0x06, 0x3e, 0x13, 0x60, 0x3c, 0x5d, 0x1a, 0xd9, 0x34, 0x69, 0x9c, 0xa2, + 0x1b, 0x8e, 0xdd, 0x2e, 0x02, 0xc3, 0xdc, 0x54, 0x37, 0x48, 0x46, 0xcd, 0x0d, 0x92, 0xb0, 0xbd, + 0x02, 0x4b, 0x02, 0x06, 0x59, 0xbf, 0x35, 0xa0, 0xa0, 0xc5, 0x69, 0x86, 0xbc, 0x7b, 0x07, 0xb2, + 0xf8, 0xde, 0x56, 0xf1, 0xcf, 0x89, 0xac, 0x63, 0xdc, 0xa6, 0x82, 0x8a, 0x85, 0x63, 0xdf, 0x91, + 0x45, 0xb1, 0x44, 0x71, 0x88, 0x94, 0x27, 0xfc, 0x5c, 0x84, 0x2c, 0x47, 0x71, 0x48, 0x6e, 0x40, + 0xee, 0x98, 0xb5, 0x7b, 0x91, 0xcb, 0xcf, 0x45, 0x10, 0xca, 0x8d, 0x8a, 0x28, 0x27, 0x8a, 0x26, + 0x92, 0xb3, 0xcf, 0x61, 0x3d, 0xc4, 0xcb, 0x39, 0xd8, 0x20, 0x81, 0xec, 0x0e, 0x3e, 0xa1, 0x70, + 0x67, 0x25, 0x2a, 0xc6, 0xf8, 0x8a, 0xdd, 0x9b, 0xf6, 0x8a, 0xdd, 0x4b, 0x5e, 0xb1, 0xc3, 0x41, + 0xc5, 0xee, 0xa3, 0x39, 0xd9, 0x7a, 0x00, 0xf9, 0xfe, 0xc5, 0x23, 0x65, 0x58, 0xdc, 0x77, 0x94, + 0xa5, 0xc5, 0x7d, 0x07, 0x8f, 0xb2, 0xf7, 0x78, 0x5f, 0x58, 0xc9, 0x51, 0x1c, 0xf6, 0x41, 0x42, + 0x46, 0x03, 0x09, 0x5b, 0xf8, 0x3e, 0xd7, 0x6e, 0x1f, 0x32, 0xd1, 0xe0, 0x2c, 0x4e, 0xb6, 0x8c, + 0x63, 0x79, 0x0c, 0x2f, 0x16, 0xba, 0xc4, 0x31, 0xbc, 0xd8, 0xba, 0x06, 0xa5, 0xa1, 0x78, 0x21, + 0x93, 0x78, 0x10, 0x2a, 0x2c, 0x89, 0xe3, 0x4d, 0x06, 0xab, 0x23, 0xdf, 0x88, 0xc8, 0xfb, 0xb0, + 0x2c, 0xbf, 0x45, 0x54, 0x16, 0xcc, 0xb7, 0xbf, 0xfe, 0x66, 0xed, 0xcd, 0x11, 0x06, 0xb9, 0x88, + 0x6c, 0xdb, 0x3d, 0xdf, 0xf1, 0x58, 0xc5, 0x98, 0xc8, 0x26, 0x17, 0xcd, 0xec, 0xaf, 0x7e, 0x7f, + 0x65, 0x61, 0xd3, 0x86, 0x4b, 0x63, 0xdf, 0x37, 0xc8, 0x35, 0xc8, 0x1e, 0x33, 0xaf, 0x93, 0x98, + 0x19, 0x63, 0xc0, 0x45, 0x72, 0x15, 0x32, 0xd4, 0x3e, 0xab, 0x18, 0x66, 0xf5, 0xeb, 0x6f, 0xd6, + 0x2e, 0x8f, 0x7f, 0x24, 0xb1, 0xcf, 0xa4, 0x89, 0xc6, 0x5f, 0x00, 0xf2, 0x87, 0x87, 0xdb, 0xdb, + 0x91, 0xeb, 0x74, 0x19, 0xf9, 0xa5, 0x01, 0x64, 0xfc, 0x25, 0x4a, 0x6e, 0xa7, 0xe7, 0xf8, 0xe4, + 0xa7, 0xba, 0xf9, 0xf1, 0x9c, 0x52, 0x0a, 0x69, 0x7c, 0x0e, 0x4b, 0x02, 0x1e, 0x93, 0x0f, 0x66, + 0x7c, 0xd6, 0x98, 0x1b, 0xd3, 0x19, 0x95, 0xee, 0x36, 0xe4, 0x12, 0x88, 0x49, 0x36, 0x53, 0xb7, + 0x37, 0x84, 0xa0, 0xcd, 0x0f, 0x67, 0xe2, 0x55, 0x46, 0x7e, 0x0a, 0x2b, 0x0a, 0x39, 0x92, 0xeb, + 0x53, 0xe4, 0x06, 0x18, 0xd6, 0xdc, 0x9c, 0x85, 0x75, 0x70, 0x8c, 0x04, 0x21, 0xa6, 0x1e, 0x63, + 0x04, 0x7f, 0xa6, 0x1e, 0x63, 0x0c, 0x72, 0xb6, 0x07, 0x0f, 0xc1, 0x54, 0x23, 0x23, 0x78, 0x33, + 0xd5, 0xc8, 0x28, 0xec, 0x24, 0x4f, 0x21, 0x8b, 0xb0, 0x93, 0xa4, 0x95, 0x5f, 0x0d, 0x97, 0x9a, + 0x69, 0x77, 0x62, 0x08, 0xaf, 0xfe, 0x04, 0xdb, 0x94, 0x78, 0xf3, 0xa7, 0x37, 0x28, 0xed, 0x13, + 0x9e, 0x79, 0x7d, 0x06, 0xce, 0x81, 0x7a, 0xf5, 0x5e, 0xde, 0x98, 0xe1, 0x3b, 0xda, 0x74, 0xf5, + 0x23, 0x5f, 0xec, 0x02, 0x28, 0xea, 0xe8, 0x83, 0xd4, 0x52, 0x44, 0x27, 0x00, 0x37, 0xb3, 0x3e, + 0x33, 0xbf, 0x32, 0xf8, 0x15, 0xbe, 0xbd, 0x86, 0x91, 0x09, 0x69, 0xa4, 0xba, 0x63, 0x22, 0x06, + 0x32, 0x6f, 0xcd, 0x25, 0xa3, 0x8c, 0xdb, 0x12, 0xf9, 0x28, 0x74, 0x43, 0xd2, 0x1b, 0x79, 0x1f, + 0x21, 0x99, 0x33, 0xf2, 0x6d, 0x18, 0x37, 0x0d, 0xbc, 0x67, 0x88, 0x78, 0x53, 0x75, 0x6b, 0x4f, + 0x81, 0xd4, 0x7b, 0xa6, 0x43, 0xe7, 0xed, 0xe2, 0xb7, 0xaf, 0xae, 0x18, 0x7f, 0x7f, 0x75, 0xc5, + 0xf8, 0xe7, 0xab, 0x2b, 0xc6, 0xc9, 0xb2, 0xf8, 0x63, 0xf2, 0xd6, 0x7f, 0x03, 0x00, 0x00, 0xff, + 0xff, 0x7d, 0x4e, 0x08, 0x7e, 0xea, 0x1d, 0x00, 0x00, } // Reference imports to suppress errors if they are not otherwise used. @@ -3993,6 +4002,13 @@ func (m *ResolveImageConfigRequest) MarshalToSizedBuffer(dAtA []byte) (int, erro i -= len(m.XXX_unrecognized) copy(dAtA[i:], m.XXX_unrecognized) } + if len(m.StoreID) > 0 { + i -= len(m.StoreID) + copy(dAtA[i:], m.StoreID) + i = encodeVarintGateway(dAtA, i, uint64(len(m.StoreID))) + i-- + dAtA[i] = 0x3a + } if len(m.SessionID) > 0 { i -= len(m.SessionID) copy(dAtA[i:], m.SessionID) @@ -5912,6 +5928,10 @@ func (m *ResolveImageConfigRequest) Size() (n int) { if l > 0 { n += 1 + l + sovGateway(uint64(l)) } + l = len(m.StoreID) + if l > 0 { + n += 1 + l + sovGateway(uint64(l)) + } if m.XXX_unrecognized != nil { n += len(m.XXX_unrecognized) } @@ -8716,6 +8736,38 @@ func (m *ResolveImageConfigRequest) Unmarshal(dAtA []byte) error { } m.SessionID = string(dAtA[iNdEx:postIndex]) iNdEx = postIndex + case 7: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field StoreID", 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.StoreID = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex default: iNdEx = preIndex skippy, err := skipGateway(dAtA[iNdEx:]) diff --git a/frontend/gateway/pb/gateway.proto b/frontend/gateway/pb/gateway.proto index 0a24d31f33c1..6fd3a9ae9635 100644 --- a/frontend/gateway/pb/gateway.proto +++ b/frontend/gateway/pb/gateway.proto @@ -122,6 +122,7 @@ message ResolveImageConfigRequest { string LogName = 4; int32 ResolverType = 5; string SessionID = 6; + string StoreID = 7; } message ResolveImageConfigResponse { diff --git a/solver/llbsolver/provenance.go b/solver/llbsolver/provenance.go index f3fc171aa45d..341e2ab839a5 100644 --- a/solver/llbsolver/provenance.go +++ b/solver/llbsolver/provenance.go @@ -324,7 +324,7 @@ func captureProvenance(ctx context.Context, res solver.CachedResultWithProvenanc return errors.Wrapf(err, "failed to parse OCI digest %s", pin) } c.AddLocalImage(provenance.ImageSource{ - Ref: s.Name, + Ref: s.Reference.String(), Platform: s.Platform, Digest: dgst, }) diff --git a/solver/pb/attr.go b/solver/pb/attr.go index 5b138d76f14b..85e7cce60ee8 100644 --- a/solver/pb/attr.go +++ b/solver/pb/attr.go @@ -29,6 +29,7 @@ const AttrImageRecordType = "image.recordtype" const AttrImageLayerLimit = "image.layerlimit" const AttrOCILayoutSessionID = "oci.session" +const AttrOCILayoutStoreID = "oci.store" const AttrOCILayoutLayerLimit = "oci.layerlimit" const AttrLocalDiffer = "local.differ" diff --git a/source/containerimage/ocilayout.go b/source/containerimage/ocilayout.go index 521a2e7b2dde..2358b5339b7a 100644 --- a/source/containerimage/ocilayout.go +++ b/source/containerimage/ocilayout.go @@ -8,6 +8,7 @@ import ( "github.com/containerd/containerd/content" "github.com/containerd/containerd/reference" "github.com/containerd/containerd/remotes" + "github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/session" sessioncontent "github.com/moby/buildkit/session/content" "github.com/moby/buildkit/util/imageutil" @@ -20,22 +21,20 @@ const ( ) // getOCILayoutResolver gets a resolver to an OCI layout for a specified store from the client using the given session. -func getOCILayoutResolver(storeID string, sm *session.Manager, sessionID string, g session.Group) *ociLayoutResolver { +func getOCILayoutResolver(store llb.ResolveImageConfigOptStore, sm *session.Manager, g session.Group) *ociLayoutResolver { r := &ociLayoutResolver{ - storeID: storeID, - sm: sm, - sessionID: sessionID, - g: g, + store: store, + sm: sm, + g: g, } return r } type ociLayoutResolver struct { remotes.Resolver - storeID string - sm *session.Manager - sessionID string - g session.Group + store llb.ResolveImageConfigOptStore + sm *session.Manager + g session.Group } // Fetcher returns a new fetcher for the provided reference. @@ -47,7 +46,7 @@ func (r *ociLayoutResolver) Fetcher(ctx context.Context, ref string) (remotes.Fe func (r *ociLayoutResolver) Fetch(ctx context.Context, desc ocispecs.Descriptor) (io.ReadCloser, error) { var rc io.ReadCloser err := r.withCaller(ctx, func(ctx context.Context, caller session.Caller) error { - store := sessioncontent.NewCallerStore(caller, "oci:"+r.storeID) + store := sessioncontent.NewCallerStore(caller, "oci:"+r.store.StoreID) readerAt, err := store.ReaderAt(ctx, desc) if err != nil { return err @@ -103,7 +102,7 @@ func (r *ociLayoutResolver) Resolve(ctx context.Context, refString string) (stri func (r *ociLayoutResolver) info(ctx context.Context, ref reference.Spec) (content.Info, error) { var info *content.Info err := r.withCaller(ctx, func(ctx context.Context, caller session.Caller) error { - store := sessioncontent.NewCallerStore(caller, "oci:"+r.storeID) + store := sessioncontent.NewCallerStore(caller, "oci:"+r.store.StoreID) _, dgst := reference.SplitObject(ref.Object) if dgst == "" { @@ -123,11 +122,11 @@ func (r *ociLayoutResolver) info(ctx context.Context, ref reference.Spec) (conte } func (r *ociLayoutResolver) withCaller(ctx context.Context, f func(context.Context, session.Caller) error) error { - if r.sessionID != "" { + if r.store.SessionID != "" { timeoutCtx, cancel := context.WithTimeout(ctx, 5*time.Second) defer cancel() - caller, err := r.sm.Get(timeoutCtx, r.sessionID, false) + caller, err := r.sm.Get(timeoutCtx, r.store.SessionID, false) if err != nil { return err } diff --git a/source/containerimage/pull.go b/source/containerimage/pull.go index 0b03d17c16fb..509d2a994660 100644 --- a/source/containerimage/pull.go +++ b/source/containerimage/pull.go @@ -107,12 +107,7 @@ func (is *Source) ResolveImageConfig(ctx context.Context, ref string, opt llb.Re rslvr = resolver.DefaultPool.GetResolver(is.RegistryHosts, ref, "pull", sm, g).WithImageStore(is.ImageStore, rm) case ResolverTypeOCILayout: rm = source.ResolveModeForcePull - - parsed, err := reference.Parse(ref) - if err != nil { - return "", nil, err - } - rslvr = getOCILayoutResolver(parsed.Hostname(), sm, "", g) + rslvr = getOCILayoutResolver(opt.Store, sm, g) } key += rm.String() res, err := is.g.Do(ctx, key, func(ctx context.Context) (interface{}, error) { @@ -137,8 +132,7 @@ func (is *Source) Resolve(ctx context.Context, id source.Identifier, sm *session mode source.ResolveMode recordType client.UsageRecordType ref reference.Spec - sessionID string - storeID string + store llb.ResolveImageConfigOptStore layerLimit *int ) switch is.ResolverType { @@ -165,9 +159,11 @@ func (is *Source) Resolve(ctx context.Context, id source.Identifier, sm *session platform = *ociIdentifier.Platform } mode = source.ResolveModeForcePull // with OCI layout, we always just "pull" - sessionID = ociIdentifier.SessionID - ref = reference.Spec{Locator: "oci-layout/dummy", Object: "@" + ociIdentifier.Digest.String()} - storeID = ociIdentifier.Name + store = llb.ResolveImageConfigOptStore{ + SessionID: ociIdentifier.SessionID, + StoreID: ociIdentifier.StoreID, + } + ref = ociIdentifier.Reference layerLimit = ociIdentifier.LayerLimit default: return nil, errors.Errorf("unknown resolver type: %v", is.ResolverType) @@ -188,9 +184,8 @@ func (is *Source) Resolve(ctx context.Context, id source.Identifier, sm *session RecordType: recordType, Ref: ref.String(), SessionManager: sm, - SessionID: sessionID, vtx: vtx, - storeID: storeID, + store: store, layerLimit: layerLimit, } return p, nil @@ -205,11 +200,10 @@ type puller struct { RecordType client.UsageRecordType Ref string SessionManager *session.Manager - SessionID string layerLimit *int vtx solver.Vertex ResolverType - storeID string + store llb.ResolveImageConfigOptStore g flightcontrol.Group cacheKeyErr error @@ -250,7 +244,7 @@ func (p *puller) CacheKey(ctx context.Context, g session.Group, index int) (cach p.Puller.Resolver = resolver getResolver = func(g session.Group) remotes.Resolver { return resolver.WithSession(g) } case ResolverTypeOCILayout: - resolver := getOCILayoutResolver(p.storeID, p.SessionManager, p.SessionID, g) + resolver := getOCILayoutResolver(p.store, p.SessionManager, g) p.Puller.Resolver = resolver // OCILayout has no need for session getResolver = func(g session.Group) remotes.Resolver { return resolver } @@ -366,7 +360,7 @@ func (p *puller) Snapshot(ctx context.Context, g session.Group) (ir cache.Immuta p.Puller.Resolver = resolver getResolver = func(g session.Group) remotes.Resolver { return resolver.WithSession(g) } case ResolverTypeOCILayout: - resolver := getOCILayoutResolver(p.storeID, p.SessionManager, p.SessionID, g) + resolver := getOCILayoutResolver(p.store, p.SessionManager, g) p.Puller.Resolver = resolver // OCILayout has no need for session getResolver = func(g session.Group) remotes.Resolver { return resolver } diff --git a/source/identifier.go b/source/identifier.go index be7bd21f8bd1..aad9f226ff6e 100644 --- a/source/identifier.go +++ b/source/identifier.go @@ -207,10 +207,8 @@ func FromLLB(op *pb.Op_Source, platform *pb.Platform) (Identifier, error) { switch k { case pb.AttrOCILayoutSessionID: id.SessionID = v - if p := strings.SplitN(v, ":", 2); len(p) == 2 { - id.Name = p[0] + "-" + id.Name - id.SessionID = p[1] - } + case pb.AttrOCILayoutStoreID: + id.StoreID = v case pb.AttrOCILayoutLayerLimit: l, err := strconv.Atoi(v) if err != nil { @@ -291,23 +289,23 @@ func (*HTTPIdentifier) ID() string { } type OCIIdentifier struct { - Name string - Digest digest.Digest + Reference reference.Spec Platform *ocispecs.Platform SessionID string + StoreID string LayerLimit *int } func NewOCIIdentifier(str string) (*OCIIdentifier, error) { - store, digSrc, found := strings.Cut(str, "@") - if !found { - return nil, errors.Errorf("invalid OCI identifier %s", str) - } - dig, err := digest.Parse(digSrc) + ref, err := reference.Parse(str) if err != nil { - return nil, errors.Wrapf(err, "invalid digest in OCI identifier %s", str) + return nil, errors.WithStack(err) + } + + if ref.Object == "" { + return nil, errors.WithStack(reference.ErrObjectRequired) } - return &OCIIdentifier{Name: store, Digest: dig}, nil + return &OCIIdentifier{Reference: ref}, nil } func (*OCIIdentifier) ID() string { From e2185a7ab31a7ed2dcd8abfeceee0adf0c459a85 Mon Sep 17 00:00:00 2001 From: Justin Chadwell Date: Tue, 6 Dec 2022 18:14:21 +0000 Subject: [PATCH 4/4] dockerfile: use target name as the dummy reference Now that the reference is not significant to image resolution, with only the digest being used to determine what to lookup, the only effect of the dummy reference is to provide reasonable error messages. Since the name of the store is likely not significant, using that as the basis for the reference may be deceiving. We can use the original name of the image as the dummy reference, except with the targeted digest. We can't easily require that clients should expose the name of the store, since that may be a leak of the local path to the store, which may be private. Signed-off-by: Justin Chadwell --- frontend/dockerfile/builder/build.go | 60 +++++++++++++++------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/frontend/dockerfile/builder/build.go b/frontend/dockerfile/builder/build.go index cd0b8fe0419a..8c429efa46e9 100644 --- a/frontend/dockerfile/builder/build.go +++ b/frontend/dockerfile/builder/build.go @@ -873,8 +873,8 @@ func contextByNameFunc(c client.Client, sessionID string) func(context.Context, p = &pp } if p != nil { - name := name + "::" + platforms.Format(platforms.Normalize(*p)) - st, img, err := contextByName(ctx, c, sessionID, name, p, resolveMode) + pname := name + "::" + platforms.Format(platforms.Normalize(*p)) + st, img, err := contextByName(ctx, c, sessionID, name, pname, p, resolveMode) if err != nil { return nil, nil, err } @@ -882,20 +882,20 @@ func contextByNameFunc(c client.Client, sessionID string) func(context.Context, return st, img, nil } } - return contextByName(ctx, c, sessionID, name, p, resolveMode) + return contextByName(ctx, c, sessionID, name, name, p, resolveMode) } } -func contextByName(ctx context.Context, c client.Client, sessionID, name string, platform *ocispecs.Platform, resolveMode string) (*llb.State, *dockerfile2llb.Image, error) { +func contextByName(ctx context.Context, c client.Client, sessionID, name string, pname string, platform *ocispecs.Platform, resolveMode string) (*llb.State, *dockerfile2llb.Image, error) { opts := c.BuildOpts().Opts - v, ok := opts[contextPrefix+name] + v, ok := opts[contextPrefix+pname] if !ok { return nil, nil, nil } vv := strings.SplitN(v, ":", 2) if len(vv) != 2 { - return nil, nil, errors.Errorf("invalid context specifier %s for %s", v, name) + return nil, nil, errors.Errorf("invalid context specifier %s for %s", v, pname) } // allow git@ without protocol for SSH URLs for backwards compatibility if strings.HasPrefix(vv[0], "git@") { @@ -910,7 +910,7 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string, } imgOpt := []llb.ImageOption{ - llb.WithCustomName("[context " + name + "] " + ref), + llb.WithCustomName("[context " + pname + "] " + ref), } if platform != nil { imgOpt = append(imgOpt, llb.Platform(*platform)) @@ -926,7 +926,7 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string, _, data, err := c.ResolveImageConfig(ctx, named.String(), llb.ResolveImageConfigOpt{ Platform: platform, ResolveMode: resolveMode, - LogName: fmt.Sprintf("[context %s] load metadata for %s", name, ref), + LogName: fmt.Sprintf("[context %s] load metadata for %s", pname, ref), ResolverType: llb.ResolverTypeRegistry, }) if err != nil { @@ -954,7 +954,7 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string, case "http", "https": st, ok := detectGitContext(v, true) if !ok { - httpst := llb.HTTP(v, llb.WithCustomName("[context "+name+"] "+v)) + httpst := llb.HTTP(v, llb.WithCustomName("[context "+pname+"] "+v)) st = &httpst } return st, nil, nil @@ -968,22 +968,26 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string, if !ok { return nil, nil, errors.Errorf("oci-layout reference %q has no name", ref.String()) } - if reference.Domain(named) != "" { - return nil, nil, errors.Errorf("oci-layout reference %q has domain", ref.String()) + dgstd, ok := named.(reference.Digested) + if !ok { + return nil, nil, errors.Errorf("oci-layout reference %q has no digest", named.String()) } - if strings.Contains(reference.Path(named), "/") { - return nil, nil, errors.Errorf("oci-layout reference %q name is multi-part", ref.String()) + + // for the dummy ref primarily used in log messages, we can use the + // original name, since the store key may not be significant + dummyRef, err := reference.ParseNormalizedNamed(name) + if err != nil { + return nil, nil, errors.Wrapf(err, "could not parse oci-layout reference %q", name) } - digested, ok := ref.(reference.Digested) - if !ok { - return nil, nil, errors.Errorf("oci-layout reference %q does not have digest", ref.String()) + dummyRef, err = reference.WithDigest(dummyRef, dgstd.Digest()) + if err != nil { + return nil, nil, errors.Wrapf(err, "could not wrap %q with digest", name) } - id := fmt.Sprintf("foo/bar@%s", digested.Digest()) - _, data, err := c.ResolveImageConfig(ctx, id, llb.ResolveImageConfigOpt{ + _, data, err := c.ResolveImageConfig(ctx, dummyRef.String(), llb.ResolveImageConfigOpt{ Platform: platform, ResolveMode: resolveMode, - LogName: fmt.Sprintf("[context %s] load metadata for %s", name, ref), + LogName: fmt.Sprintf("[context %s] load metadata for %s", pname, dummyRef.String()), ResolverType: llb.ResolverTypeOCILayout, Store: llb.ResolveImageConfigOptStore{ SessionID: sessionID, @@ -1000,14 +1004,14 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string, } ociOpt := []llb.OCILayoutOption{ - llb.WithCustomName("[context " + name + "] OCI load from client"), + llb.WithCustomName("[context " + pname + "] OCI load from client"), llb.OCIStore(c.BuildOpts().SessionID, named.Name()), } if platform != nil { ociOpt = append(ociOpt, llb.Platform(*platform)) } st := llb.OCILayout( - id, + dummyRef.String(), ociOpt..., ) st, err = st.WithImageConfig(data) @@ -1019,8 +1023,8 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string, st := llb.Local(vv[1], llb.SessionID(c.BuildOpts().SessionID), llb.FollowPaths([]string{dockerignoreFilename}), - llb.SharedKeyHint("context:"+name+"-"+dockerignoreFilename), - llb.WithCustomName("[context "+name+"] load "+dockerignoreFilename), + llb.SharedKeyHint("context:"+pname+"-"+dockerignoreFilename), + llb.WithCustomName("[context "+pname+"] load "+dockerignoreFilename), llb.Differ(llb.DiffNone, false), ) def, err := st.Marshal(ctx) @@ -1049,9 +1053,9 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string, } } st = llb.Local(vv[1], - llb.WithCustomName("[context "+name+"] load from client"), + llb.WithCustomName("[context "+pname+"] load from client"), llb.SessionID(c.BuildOpts().SessionID), - llb.SharedKeyHint("context:"+name), + llb.SharedKeyHint("context:"+pname), llb.ExcludePatterns(excludes), ) return &st, nil, nil @@ -1062,7 +1066,7 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string, } st, ok := inputs[vv[1]] if !ok { - return nil, nil, errors.Errorf("invalid input %s for %s", vv[1], name) + return nil, nil, errors.Errorf("invalid input %s for %s", vv[1], pname) } md, ok := opts[inputMetadataPrefix+vv[1]] if ok { @@ -1077,14 +1081,14 @@ func contextByName(ctx context.Context, c client.Client, sessionID, name string, return nil, nil, err } if err := json.Unmarshal(dtic, &img); err != nil { - return nil, nil, errors.Wrapf(err, "failed to parse image config for %s", name) + return nil, nil, errors.Wrapf(err, "failed to parse image config for %s", pname) } } return &st, img, nil } return &st, nil, nil default: - return nil, nil, errors.Errorf("unsupported context source %s for %s", vv[0], name) + return nil, nil, errors.Errorf("unsupported context source %s for %s", vv[0], pname) } }