feat(cache): remove temporary cache after filesystem scanning (#1868)

This commit is contained in:
afdesk
2022-03-27 14:31:54 +06:00
committed by GitHub
parent f36d9b6f90
commit 9154b819ac
10 changed files with 496 additions and 97 deletions

View File

@@ -504,6 +504,53 @@ func (x *MissingBlobsResponse) GetMissingBlobIds() []string {
return nil
}
type DeleteBlobsRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
BlobIds []string `protobuf:"bytes,1,rep,name=blob_ids,json=blobIds,proto3" json:"blob_ids,omitempty"`
}
func (x *DeleteBlobsRequest) Reset() {
*x = DeleteBlobsRequest{}
if protoimpl.UnsafeEnabled {
mi := &file_rpc_cache_service_proto_msgTypes[7]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *DeleteBlobsRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*DeleteBlobsRequest) ProtoMessage() {}
func (x *DeleteBlobsRequest) ProtoReflect() protoreflect.Message {
mi := &file_rpc_cache_service_proto_msgTypes[7]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use DeleteBlobsRequest.ProtoReflect.Descriptor instead.
func (*DeleteBlobsRequest) Descriptor() ([]byte, []int) {
return file_rpc_cache_service_proto_rawDescGZIP(), []int{7}
}
func (x *DeleteBlobsRequest) GetBlobIds() []string {
if x != nil {
return x.BlobIds
}
return nil
}
var File_rpc_cache_service_proto protoreflect.FileDescriptor
var file_rpc_cache_service_proto_rawDesc = []byte{
@@ -592,25 +639,33 @@ var file_rpc_cache_service_proto_rawDesc = []byte{
0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x28, 0x0a, 0x10, 0x6d, 0x69, 0x73, 0x73,
0x69, 0x6e, 0x67, 0x5f, 0x62, 0x6c, 0x6f, 0x62, 0x5f, 0x69, 0x64, 0x73, 0x18, 0x02, 0x20, 0x03,
0x28, 0x09, 0x52, 0x0e, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x62, 0x49,
0x64, 0x73, 0x32, 0xf0, 0x01, 0x0a, 0x05, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x49, 0x0a, 0x0b,
0x50, 0x75, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x22, 0x2e, 0x74, 0x72,
0x69, 0x76, 0x79, 0x2e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x74,
0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75,
0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x41, 0x0a, 0x07, 0x50, 0x75, 0x74, 0x42, 0x6c,
0x6f, 0x62, 0x12, 0x1e, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x61, 0x63, 0x68, 0x65,
0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x59, 0x0a, 0x0c, 0x4d, 0x69,
0x73, 0x73, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x12, 0x23, 0x2e, 0x74, 0x72, 0x69,
0x76, 0x79, 0x2e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x69, 0x73, 0x73,
0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
0x24, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x76, 0x31,
0x2e, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x73,
0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e,
0x63, 0x6f, 0x6d, 0x2f, 0x61, 0x71, 0x75, 0x61, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79,
0x2f, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x61, 0x63, 0x68, 0x65,
0x3b, 0x63, 0x61, 0x63, 0x68, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x64, 0x73, 0x22, 0x2f, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x6c, 0x6f, 0x62,
0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x62, 0x6c, 0x6f, 0x62,
0x5f, 0x69, 0x64, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x62, 0x6c, 0x6f, 0x62,
0x49, 0x64, 0x73, 0x32, 0xbb, 0x02, 0x0a, 0x05, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x49, 0x0a,
0x0b, 0x50, 0x75, 0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x12, 0x22, 0x2e, 0x74,
0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75,
0x74, 0x41, 0x72, 0x74, 0x69, 0x66, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x41, 0x0a, 0x07, 0x50, 0x75, 0x74, 0x42,
0x6c, 0x6f, 0x62, 0x12, 0x1e, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x61, 0x63, 0x68,
0x65, 0x2e, 0x76, 0x31, 0x2e, 0x50, 0x75, 0x74, 0x42, 0x6c, 0x6f, 0x62, 0x52, 0x65, 0x71, 0x75,
0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f,
0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x59, 0x0a, 0x0c, 0x4d,
0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x12, 0x23, 0x2e, 0x74, 0x72,
0x69, 0x76, 0x79, 0x2e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x4d, 0x69, 0x73,
0x73, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74,
0x1a, 0x24, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x61, 0x63, 0x68, 0x65, 0x2e, 0x76,
0x31, 0x2e, 0x4d, 0x69, 0x73, 0x73, 0x69, 0x6e, 0x67, 0x42, 0x6c, 0x6f, 0x62, 0x73, 0x52, 0x65,
0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x49, 0x0a, 0x0b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65,
0x42, 0x6c, 0x6f, 0x62, 0x73, 0x12, 0x22, 0x2e, 0x74, 0x72, 0x69, 0x76, 0x79, 0x2e, 0x63, 0x61,
0x63, 0x68, 0x65, 0x2e, 0x76, 0x31, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x42, 0x6c, 0x6f,
0x62, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67,
0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74,
0x79, 0x42, 0x2f, 0x5a, 0x2d, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
0x61, 0x71, 0x75, 0x61, 0x73, 0x65, 0x63, 0x75, 0x72, 0x69, 0x74, 0x79, 0x2f, 0x74, 0x72, 0x69,
0x76, 0x79, 0x2f, 0x72, 0x70, 0x63, 0x2f, 0x63, 0x61, 0x63, 0x68, 0x65, 0x3b, 0x63, 0x61, 0x63,
0x68, 0x65, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
@@ -625,7 +680,7 @@ func file_rpc_cache_service_proto_rawDescGZIP() []byte {
return file_rpc_cache_service_proto_rawDescData
}
var file_rpc_cache_service_proto_msgTypes = make([]protoimpl.MessageInfo, 7)
var file_rpc_cache_service_proto_msgTypes = make([]protoimpl.MessageInfo, 8)
var file_rpc_cache_service_proto_goTypes = []interface{}{
(*ArtifactInfo)(nil), // 0: trivy.cache.v1.ArtifactInfo
(*PutArtifactRequest)(nil), // 1: trivy.cache.v1.PutArtifactRequest
@@ -634,34 +689,37 @@ var file_rpc_cache_service_proto_goTypes = []interface{}{
(*PutResponse)(nil), // 4: trivy.cache.v1.PutResponse
(*MissingBlobsRequest)(nil), // 5: trivy.cache.v1.MissingBlobsRequest
(*MissingBlobsResponse)(nil), // 6: trivy.cache.v1.MissingBlobsResponse
(*timestamppb.Timestamp)(nil), // 7: google.protobuf.Timestamp
(*common.Package)(nil), // 8: trivy.common.Package
(*common.OS)(nil), // 9: trivy.common.OS
(*common.PackageInfo)(nil), // 10: trivy.common.PackageInfo
(*common.Application)(nil), // 11: trivy.common.Application
(*common.Misconfiguration)(nil), // 12: trivy.common.Misconfiguration
(*common.CustomResource)(nil), // 13: trivy.common.CustomResource
(*emptypb.Empty)(nil), // 14: google.protobuf.Empty
(*DeleteBlobsRequest)(nil), // 7: trivy.cache.v1.DeleteBlobsRequest
(*timestamppb.Timestamp)(nil), // 8: google.protobuf.Timestamp
(*common.Package)(nil), // 9: trivy.common.Package
(*common.OS)(nil), // 10: trivy.common.OS
(*common.PackageInfo)(nil), // 11: trivy.common.PackageInfo
(*common.Application)(nil), // 12: trivy.common.Application
(*common.Misconfiguration)(nil), // 13: trivy.common.Misconfiguration
(*common.CustomResource)(nil), // 14: trivy.common.CustomResource
(*emptypb.Empty)(nil), // 15: google.protobuf.Empty
}
var file_rpc_cache_service_proto_depIdxs = []int32{
7, // 0: trivy.cache.v1.ArtifactInfo.created:type_name -> google.protobuf.Timestamp
8, // 1: trivy.cache.v1.ArtifactInfo.history_packages:type_name -> trivy.common.Package
8, // 0: trivy.cache.v1.ArtifactInfo.created:type_name -> google.protobuf.Timestamp
9, // 1: trivy.cache.v1.ArtifactInfo.history_packages:type_name -> trivy.common.Package
0, // 2: trivy.cache.v1.PutArtifactRequest.artifact_info:type_name -> trivy.cache.v1.ArtifactInfo
9, // 3: trivy.cache.v1.BlobInfo.os:type_name -> trivy.common.OS
10, // 4: trivy.cache.v1.BlobInfo.package_infos:type_name -> trivy.common.PackageInfo
11, // 5: trivy.cache.v1.BlobInfo.applications:type_name -> trivy.common.Application
12, // 6: trivy.cache.v1.BlobInfo.misconfigurations:type_name -> trivy.common.Misconfiguration
13, // 7: trivy.cache.v1.BlobInfo.custom_resources:type_name -> trivy.common.CustomResource
10, // 3: trivy.cache.v1.BlobInfo.os:type_name -> trivy.common.OS
11, // 4: trivy.cache.v1.BlobInfo.package_infos:type_name -> trivy.common.PackageInfo
12, // 5: trivy.cache.v1.BlobInfo.applications:type_name -> trivy.common.Application
13, // 6: trivy.cache.v1.BlobInfo.misconfigurations:type_name -> trivy.common.Misconfiguration
14, // 7: trivy.cache.v1.BlobInfo.custom_resources:type_name -> trivy.common.CustomResource
2, // 8: trivy.cache.v1.PutBlobRequest.blob_info:type_name -> trivy.cache.v1.BlobInfo
9, // 9: trivy.cache.v1.PutResponse.os:type_name -> trivy.common.OS
10, // 9: trivy.cache.v1.PutResponse.os:type_name -> trivy.common.OS
1, // 10: trivy.cache.v1.Cache.PutArtifact:input_type -> trivy.cache.v1.PutArtifactRequest
3, // 11: trivy.cache.v1.Cache.PutBlob:input_type -> trivy.cache.v1.PutBlobRequest
5, // 12: trivy.cache.v1.Cache.MissingBlobs:input_type -> trivy.cache.v1.MissingBlobsRequest
14, // 13: trivy.cache.v1.Cache.PutArtifact:output_type -> google.protobuf.Empty
14, // 14: trivy.cache.v1.Cache.PutBlob:output_type -> google.protobuf.Empty
6, // 15: trivy.cache.v1.Cache.MissingBlobs:output_type -> trivy.cache.v1.MissingBlobsResponse
13, // [13:16] is the sub-list for method output_type
10, // [10:13] is the sub-list for method input_type
7, // 13: trivy.cache.v1.Cache.DeleteBlobs:input_type -> trivy.cache.v1.DeleteBlobsRequest
15, // 14: trivy.cache.v1.Cache.PutArtifact:output_type -> google.protobuf.Empty
15, // 15: trivy.cache.v1.Cache.PutBlob:output_type -> google.protobuf.Empty
6, // 16: trivy.cache.v1.Cache.MissingBlobs:output_type -> trivy.cache.v1.MissingBlobsResponse
15, // 17: trivy.cache.v1.Cache.DeleteBlobs:output_type -> google.protobuf.Empty
14, // [14:18] is the sub-list for method output_type
10, // [10:14] is the sub-list for method input_type
10, // [10:10] is the sub-list for extension type_name
10, // [10:10] is the sub-list for extension extendee
0, // [0:10] is the sub-list for field type_name
@@ -757,6 +815,18 @@ func file_rpc_cache_service_proto_init() {
return nil
}
}
file_rpc_cache_service_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*DeleteBlobsRequest); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
@@ -764,7 +834,7 @@ func file_rpc_cache_service_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_rpc_cache_service_proto_rawDesc,
NumEnums: 0,
NumMessages: 7,
NumMessages: 8,
NumExtensions: 0,
NumServices: 1,
},

View File

@@ -11,6 +11,7 @@ service Cache {
rpc PutArtifact(PutArtifactRequest) returns (google.protobuf.Empty);
rpc PutBlob(PutBlobRequest) returns (google.protobuf.Empty);
rpc MissingBlobs(MissingBlobsRequest) returns (MissingBlobsResponse);
rpc DeleteBlobs(DeleteBlobsRequest) returns (google.protobuf.Empty);
}
message ArtifactInfo {
@@ -59,3 +60,7 @@ message MissingBlobsResponse {
bool missing_artifact = 1;
repeated string missing_blob_ids = 2;
}
message DeleteBlobsRequest {
repeated string blob_ids = 1;
}

View File

@@ -40,6 +40,8 @@ type Cache interface {
PutBlob(context.Context, *PutBlobRequest) (*google_protobuf2.Empty, error)
MissingBlobs(context.Context, *MissingBlobsRequest) (*MissingBlobsResponse, error)
DeleteBlobs(context.Context, *DeleteBlobsRequest) (*google_protobuf2.Empty, error)
}
// =====================
@@ -48,7 +50,7 @@ type Cache interface {
type cacheProtobufClient struct {
client HTTPClient
urls [3]string
urls [4]string
interceptor twirp.Interceptor
opts twirp.ClientOptions
}
@@ -76,10 +78,11 @@ func NewCacheProtobufClient(baseURL string, client HTTPClient, opts ...twirp.Cli
// Build method URLs: <baseURL>[<prefix>]/<package>.<Service>/<Method>
serviceURL := sanitizeBaseURL(baseURL)
serviceURL += baseServicePath(pathPrefix, "trivy.cache.v1", "Cache")
urls := [3]string{
urls := [4]string{
serviceURL + "PutArtifact",
serviceURL + "PutBlob",
serviceURL + "MissingBlobs",
serviceURL + "DeleteBlobs",
}
return &cacheProtobufClient{
@@ -228,13 +231,59 @@ func (c *cacheProtobufClient) callMissingBlobs(ctx context.Context, in *MissingB
return out, nil
}
func (c *cacheProtobufClient) DeleteBlobs(ctx context.Context, in *DeleteBlobsRequest) (*google_protobuf2.Empty, error) {
ctx = ctxsetters.WithPackageName(ctx, "trivy.cache.v1")
ctx = ctxsetters.WithServiceName(ctx, "Cache")
ctx = ctxsetters.WithMethodName(ctx, "DeleteBlobs")
caller := c.callDeleteBlobs
if c.interceptor != nil {
caller = func(ctx context.Context, req *DeleteBlobsRequest) (*google_protobuf2.Empty, error) {
resp, err := c.interceptor(
func(ctx context.Context, req interface{}) (interface{}, error) {
typedReq, ok := req.(*DeleteBlobsRequest)
if !ok {
return nil, twirp.InternalError("failed type assertion req.(*DeleteBlobsRequest) when calling interceptor")
}
return c.callDeleteBlobs(ctx, typedReq)
},
)(ctx, req)
if resp != nil {
typedResp, ok := resp.(*google_protobuf2.Empty)
if !ok {
return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf2.Empty) when calling interceptor")
}
return typedResp, err
}
return nil, err
}
}
return caller(ctx, in)
}
func (c *cacheProtobufClient) callDeleteBlobs(ctx context.Context, in *DeleteBlobsRequest) (*google_protobuf2.Empty, error) {
out := new(google_protobuf2.Empty)
ctx, err := doProtobufRequest(ctx, c.client, c.opts.Hooks, c.urls[3], in, out)
if err != nil {
twerr, ok := err.(twirp.Error)
if !ok {
twerr = twirp.InternalErrorWith(err)
}
callClientError(ctx, c.opts.Hooks, twerr)
return nil, err
}
callClientResponseReceived(ctx, c.opts.Hooks)
return out, nil
}
// =================
// Cache JSON Client
// =================
type cacheJSONClient struct {
client HTTPClient
urls [3]string
urls [4]string
interceptor twirp.Interceptor
opts twirp.ClientOptions
}
@@ -262,10 +311,11 @@ func NewCacheJSONClient(baseURL string, client HTTPClient, opts ...twirp.ClientO
// Build method URLs: <baseURL>[<prefix>]/<package>.<Service>/<Method>
serviceURL := sanitizeBaseURL(baseURL)
serviceURL += baseServicePath(pathPrefix, "trivy.cache.v1", "Cache")
urls := [3]string{
urls := [4]string{
serviceURL + "PutArtifact",
serviceURL + "PutBlob",
serviceURL + "MissingBlobs",
serviceURL + "DeleteBlobs",
}
return &cacheJSONClient{
@@ -414,6 +464,52 @@ func (c *cacheJSONClient) callMissingBlobs(ctx context.Context, in *MissingBlobs
return out, nil
}
func (c *cacheJSONClient) DeleteBlobs(ctx context.Context, in *DeleteBlobsRequest) (*google_protobuf2.Empty, error) {
ctx = ctxsetters.WithPackageName(ctx, "trivy.cache.v1")
ctx = ctxsetters.WithServiceName(ctx, "Cache")
ctx = ctxsetters.WithMethodName(ctx, "DeleteBlobs")
caller := c.callDeleteBlobs
if c.interceptor != nil {
caller = func(ctx context.Context, req *DeleteBlobsRequest) (*google_protobuf2.Empty, error) {
resp, err := c.interceptor(
func(ctx context.Context, req interface{}) (interface{}, error) {
typedReq, ok := req.(*DeleteBlobsRequest)
if !ok {
return nil, twirp.InternalError("failed type assertion req.(*DeleteBlobsRequest) when calling interceptor")
}
return c.callDeleteBlobs(ctx, typedReq)
},
)(ctx, req)
if resp != nil {
typedResp, ok := resp.(*google_protobuf2.Empty)
if !ok {
return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf2.Empty) when calling interceptor")
}
return typedResp, err
}
return nil, err
}
}
return caller(ctx, in)
}
func (c *cacheJSONClient) callDeleteBlobs(ctx context.Context, in *DeleteBlobsRequest) (*google_protobuf2.Empty, error) {
out := new(google_protobuf2.Empty)
ctx, err := doJSONRequest(ctx, c.client, c.opts.Hooks, c.urls[3], in, out)
if err != nil {
twerr, ok := err.(twirp.Error)
if !ok {
twerr = twirp.InternalErrorWith(err)
}
callClientError(ctx, c.opts.Hooks, twerr)
return nil, err
}
callClientResponseReceived(ctx, c.opts.Hooks)
return out, nil
}
// ====================
// Cache Server Handler
// ====================
@@ -520,6 +616,9 @@ func (s *cacheServer) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
case "MissingBlobs":
s.serveMissingBlobs(ctx, resp, req)
return
case "DeleteBlobs":
s.serveDeleteBlobs(ctx, resp, req)
return
default:
msg := fmt.Sprintf("no handler for path %q", req.URL.Path)
s.writeError(ctx, resp, badRouteError(msg, req.Method, req.URL.Path))
@@ -1067,6 +1166,186 @@ func (s *cacheServer) serveMissingBlobsProtobuf(ctx context.Context, resp http.R
callResponseSent(ctx, s.hooks)
}
func (s *cacheServer) serveDeleteBlobs(ctx context.Context, resp http.ResponseWriter, req *http.Request) {
header := req.Header.Get("Content-Type")
i := strings.Index(header, ";")
if i == -1 {
i = len(header)
}
switch strings.TrimSpace(strings.ToLower(header[:i])) {
case "application/json":
s.serveDeleteBlobsJSON(ctx, resp, req)
case "application/protobuf":
s.serveDeleteBlobsProtobuf(ctx, resp, req)
default:
msg := fmt.Sprintf("unexpected Content-Type: %q", req.Header.Get("Content-Type"))
twerr := badRouteError(msg, req.Method, req.URL.Path)
s.writeError(ctx, resp, twerr)
}
}
func (s *cacheServer) serveDeleteBlobsJSON(ctx context.Context, resp http.ResponseWriter, req *http.Request) {
var err error
ctx = ctxsetters.WithMethodName(ctx, "DeleteBlobs")
ctx, err = callRequestRouted(ctx, s.hooks)
if err != nil {
s.writeError(ctx, resp, err)
return
}
d := json.NewDecoder(req.Body)
rawReqBody := json.RawMessage{}
if err := d.Decode(&rawReqBody); err != nil {
s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err)
return
}
reqContent := new(DeleteBlobsRequest)
unmarshaler := protojson.UnmarshalOptions{DiscardUnknown: true}
if err = unmarshaler.Unmarshal(rawReqBody, reqContent); err != nil {
s.handleRequestBodyError(ctx, resp, "the json request could not be decoded", err)
return
}
handler := s.Cache.DeleteBlobs
if s.interceptor != nil {
handler = func(ctx context.Context, req *DeleteBlobsRequest) (*google_protobuf2.Empty, error) {
resp, err := s.interceptor(
func(ctx context.Context, req interface{}) (interface{}, error) {
typedReq, ok := req.(*DeleteBlobsRequest)
if !ok {
return nil, twirp.InternalError("failed type assertion req.(*DeleteBlobsRequest) when calling interceptor")
}
return s.Cache.DeleteBlobs(ctx, typedReq)
},
)(ctx, req)
if resp != nil {
typedResp, ok := resp.(*google_protobuf2.Empty)
if !ok {
return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf2.Empty) when calling interceptor")
}
return typedResp, err
}
return nil, err
}
}
// Call service method
var respContent *google_protobuf2.Empty
func() {
defer ensurePanicResponses(ctx, resp, s.hooks)
respContent, err = handler(ctx, reqContent)
}()
if err != nil {
s.writeError(ctx, resp, err)
return
}
if respContent == nil {
s.writeError(ctx, resp, twirp.InternalError("received a nil *google_protobuf2.Empty and nil error while calling DeleteBlobs. nil responses are not supported"))
return
}
ctx = callResponsePrepared(ctx, s.hooks)
marshaler := &protojson.MarshalOptions{UseProtoNames: !s.jsonCamelCase, EmitUnpopulated: !s.jsonSkipDefaults}
respBytes, err := marshaler.Marshal(respContent)
if err != nil {
s.writeError(ctx, resp, wrapInternal(err, "failed to marshal json response"))
return
}
ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK)
resp.Header().Set("Content-Type", "application/json")
resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes)))
resp.WriteHeader(http.StatusOK)
if n, err := resp.Write(respBytes); err != nil {
msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error())
twerr := twirp.NewError(twirp.Unknown, msg)
ctx = callError(ctx, s.hooks, twerr)
}
callResponseSent(ctx, s.hooks)
}
func (s *cacheServer) serveDeleteBlobsProtobuf(ctx context.Context, resp http.ResponseWriter, req *http.Request) {
var err error
ctx = ctxsetters.WithMethodName(ctx, "DeleteBlobs")
ctx, err = callRequestRouted(ctx, s.hooks)
if err != nil {
s.writeError(ctx, resp, err)
return
}
buf, err := ioutil.ReadAll(req.Body)
if err != nil {
s.handleRequestBodyError(ctx, resp, "failed to read request body", err)
return
}
reqContent := new(DeleteBlobsRequest)
if err = proto.Unmarshal(buf, reqContent); err != nil {
s.writeError(ctx, resp, malformedRequestError("the protobuf request could not be decoded"))
return
}
handler := s.Cache.DeleteBlobs
if s.interceptor != nil {
handler = func(ctx context.Context, req *DeleteBlobsRequest) (*google_protobuf2.Empty, error) {
resp, err := s.interceptor(
func(ctx context.Context, req interface{}) (interface{}, error) {
typedReq, ok := req.(*DeleteBlobsRequest)
if !ok {
return nil, twirp.InternalError("failed type assertion req.(*DeleteBlobsRequest) when calling interceptor")
}
return s.Cache.DeleteBlobs(ctx, typedReq)
},
)(ctx, req)
if resp != nil {
typedResp, ok := resp.(*google_protobuf2.Empty)
if !ok {
return nil, twirp.InternalError("failed type assertion resp.(*google_protobuf2.Empty) when calling interceptor")
}
return typedResp, err
}
return nil, err
}
}
// Call service method
var respContent *google_protobuf2.Empty
func() {
defer ensurePanicResponses(ctx, resp, s.hooks)
respContent, err = handler(ctx, reqContent)
}()
if err != nil {
s.writeError(ctx, resp, err)
return
}
if respContent == nil {
s.writeError(ctx, resp, twirp.InternalError("received a nil *google_protobuf2.Empty and nil error while calling DeleteBlobs. nil responses are not supported"))
return
}
ctx = callResponsePrepared(ctx, s.hooks)
respBytes, err := proto.Marshal(respContent)
if err != nil {
s.writeError(ctx, resp, wrapInternal(err, "failed to marshal proto response"))
return
}
ctx = ctxsetters.WithStatusCode(ctx, http.StatusOK)
resp.Header().Set("Content-Type", "application/protobuf")
resp.Header().Set("Content-Length", strconv.Itoa(len(respBytes)))
resp.WriteHeader(http.StatusOK)
if n, err := resp.Write(respBytes); err != nil {
msg := fmt.Sprintf("failed to write response, %d of %d bytes written: %s", n, len(respBytes), err.Error())
twerr := twirp.NewError(twirp.Unknown, msg)
ctx = callError(ctx, s.hooks, twerr)
}
callResponseSent(ctx, s.hooks)
}
func (s *cacheServer) ServiceDescriptor() ([]byte, int) {
return twirpFileDescriptor0, 0
}
@@ -1651,52 +1930,54 @@ func callClientError(ctx context.Context, h *twirp.ClientHooks, err twirp.Error)
}
var twirpFileDescriptor0 = []byte{
// 743 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x55, 0xdd, 0x6e, 0xd3, 0x30,
0x18, 0x55, 0xdb, 0x6d, 0x6d, 0xbf, 0xfe, 0xac, 0x18, 0xd8, 0xb2, 0x32, 0x6d, 0x55, 0x00, 0xa9,
0x5c, 0x90, 0x88, 0x02, 0x57, 0x08, 0x44, 0x37, 0x7e, 0x54, 0x89, 0x89, 0x12, 0x10, 0x12, 0xdc,
0x94, 0xd4, 0x71, 0x5a, 0x6b, 0x4d, 0x9c, 0xd9, 0x4e, 0xa1, 0x6f, 0xc0, 0x73, 0xf2, 0x04, 0x3c,
0x02, 0xb2, 0x93, 0xac, 0x4d, 0x57, 0x26, 0xb8, 0x99, 0xea, 0xf3, 0x7d, 0x3e, 0x3e, 0x3e, 0xe7,
0x73, 0x06, 0xfb, 0x3c, 0xc2, 0x36, 0x76, 0xf1, 0x94, 0xd8, 0x82, 0xf0, 0x39, 0xc5, 0xc4, 0x8a,
0x38, 0x93, 0x0c, 0x35, 0x25, 0xa7, 0xf3, 0x85, 0xa5, 0x4b, 0xd6, 0xfc, 0x51, 0xfb, 0x78, 0xc2,
0xd8, 0x64, 0x46, 0x6c, 0x5d, 0x1d, 0xc7, 0xbe, 0x2d, 0x69, 0x40, 0x84, 0x74, 0x83, 0x28, 0xd9,
0xd0, 0x36, 0x34, 0x13, 0x0b, 0x02, 0x16, 0xe6, 0xa9, 0xda, 0x77, 0xd6, 0xb7, 0x92, 0x20, 0x92,
0x8b, 0xa4, 0x68, 0xfe, 0x2c, 0x42, 0xbd, 0xcf, 0x25, 0xf5, 0x5d, 0x2c, 0x07, 0xa1, 0xcf, 0xd0,
0x7d, 0x68, 0x0a, 0x3c, 0x25, 0x81, 0x3b, 0x9a, 0x13, 0x2e, 0x28, 0x0b, 0x8d, 0x42, 0xa7, 0xd0,
0xdd, 0x76, 0x1a, 0x09, 0xfa, 0x39, 0x01, 0x91, 0x09, 0x75, 0x97, 0xe3, 0x29, 0x95, 0x04, 0xcb,
0x98, 0x13, 0xa3, 0xd8, 0x29, 0x74, 0xab, 0x4e, 0x0e, 0x43, 0x4f, 0xa0, 0x8c, 0x39, 0x71, 0x25,
0xf1, 0x8c, 0x52, 0xa7, 0xd0, 0xad, 0xf5, 0xda, 0x56, 0x22, 0xc5, 0xca, 0xa4, 0x58, 0x9f, 0xb2,
0x5b, 0x38, 0x59, 0xab, 0x12, 0xe0, 0x31, 0x7c, 0x4e, 0xf8, 0xa5, 0x80, 0x2d, 0xcd, 0xdd, 0x48,
0xd0, 0x4c, 0x40, 0x13, 0x8a, 0x4c, 0x18, 0xdb, 0xba, 0x54, 0x64, 0x02, 0xbd, 0x84, 0xd6, 0x94,
0x0a, 0xc9, 0xf8, 0x62, 0x14, 0xb9, 0xf8, 0xdc, 0x9d, 0x10, 0x61, 0xec, 0x74, 0x4a, 0xdd, 0x5a,
0xef, 0xb6, 0x95, 0x7a, 0xa9, 0xcd, 0xb1, 0x86, 0x49, 0xd5, 0xd9, 0x4d, 0xdb, 0xd3, 0xb5, 0x30,
0x7f, 0x00, 0x1a, 0xc6, 0x32, 0x33, 0xc3, 0x21, 0x17, 0x31, 0x11, 0x12, 0x1d, 0x43, 0xcd, 0x4d,
0xa1, 0x11, 0xf5, 0xb4, 0x19, 0x55, 0x07, 0x32, 0x68, 0xe0, 0xa1, 0x3e, 0x34, 0x96, 0x0d, 0xa1,
0xcf, 0xb4, 0x15, 0xb5, 0xde, 0xa1, 0x95, 0x4f, 0xd0, 0x5a, 0x75, 0x59, 0x19, 0xb5, 0x5c, 0x99,
0xbf, 0x4a, 0x50, 0x39, 0x99, 0xb1, 0xf1, 0xff, 0x04, 0xd0, 0xd1, 0xf7, 0x4f, 0xce, 0x6a, 0xe5,
0x6f, 0xf8, 0xfe, 0xa3, 0x76, 0xe4, 0x05, 0x34, 0x52, 0x27, 0xb4, 0x2e, 0x61, 0x94, 0xb4, 0x1d,
0x07, 0x1b, 0xed, 0x48, 0x54, 0x45, 0xcb, 0x85, 0x40, 0xcf, 0xa1, 0xee, 0x46, 0xd1, 0x8c, 0x62,
0x57, 0x52, 0x16, 0x0a, 0x63, 0x6b, 0xd3, 0xf6, 0xfe, 0xb2, 0xc3, 0xc9, 0xb5, 0xa3, 0x77, 0x70,
0x23, 0xa0, 0x02, 0xb3, 0xd0, 0xa7, 0x93, 0x98, 0xa7, 0x1c, 0x55, 0xcd, 0x71, 0x94, 0xe7, 0x38,
0x5b, 0x6b, 0x73, 0xae, 0x6e, 0x54, 0x31, 0xb0, 0xc8, 0xbd, 0x88, 0xc9, 0xc8, 0xa3, 0x5c, 0xe5,
0x5e, 0x52, 0x31, 0x24, 0xd0, 0x2b, 0xca, 0x85, 0xb2, 0xed, 0xbb, 0x1a, 0x3d, 0x16, 0xcb, 0x91,
0x4f, 0x67, 0x69, 0xfa, 0x55, 0xa7, 0x91, 0xa1, 0x6f, 0x14, 0x88, 0xf6, 0x60, 0xc7, 0xa3, 0x13,
0x22, 0xa4, 0x51, 0xd6, 0x49, 0xa6, 0x2b, 0xb4, 0x0f, 0x65, 0x8f, 0xfa, 0xbe, 0x8a, 0xb8, 0x92,
0x15, 0x7c, 0x7f, 0xe0, 0xa1, 0xb7, 0xd0, 0xc2, 0xb1, 0x90, 0x2c, 0x18, 0x71, 0x22, 0x58, 0xcc,
0x31, 0x11, 0x06, 0xe8, 0x5b, 0x1c, 0xe6, 0x6f, 0x71, 0xaa, 0xbb, 0x9c, 0xb4, 0xc9, 0xd9, 0xc5,
0xb9, 0xb5, 0x30, 0xbf, 0x41, 0x73, 0x18, 0x4b, 0x15, 0x73, 0x36, 0x5a, 0x2b, 0x67, 0x16, 0x72,
0x67, 0x3e, 0x85, 0xea, 0x78, 0xc6, 0xc6, 0xc9, 0x38, 0x25, 0x4f, 0xc7, 0x58, 0x1f, 0xa7, 0x6c,
0x5e, 0x9c, 0xca, 0x38, 0xfd, 0x65, 0x9e, 0x42, 0x6d, 0x18, 0x4b, 0x87, 0x88, 0x88, 0x85, 0x82,
0xa4, 0x13, 0x52, 0xb8, 0x66, 0x42, 0x10, 0x6c, 0x11, 0x26, 0x66, 0x7a, 0x8a, 0x2a, 0x8e, 0xfe,
0x6d, 0x7e, 0x80, 0x9b, 0x67, 0x54, 0x08, 0x1a, 0x4e, 0xd4, 0x09, 0xe2, 0x9f, 0x9f, 0xc1, 0x01,
0x54, 0x12, 0xcd, 0x9e, 0x9a, 0x4a, 0xe5, 0x7c, 0x59, 0x0b, 0xf3, 0x84, 0x79, 0x0e, 0xb7, 0xf2,
0x94, 0xa9, 0xc0, 0x07, 0xd0, 0x0a, 0x12, 0x7c, 0x94, 0x11, 0x69, 0xe2, 0x8a, 0xb3, 0x9b, 0xe2,
0xd9, 0x9b, 0x41, 0xdd, 0x65, 0xeb, 0xda, 0x29, 0xcd, 0x60, 0x49, 0x3d, 0xf0, 0x44, 0xef, 0x77,
0x01, 0xb6, 0x4f, 0x95, 0x49, 0x68, 0xa0, 0xed, 0xb8, 0xa4, 0x30, 0xd7, 0x1d, 0xbc, 0xfa, 0xd8,
0xdb, 0x7b, 0x57, 0x3e, 0x50, 0xaf, 0xd5, 0xb7, 0x12, 0xf5, 0xa1, 0x9c, 0x66, 0x87, 0x8e, 0x36,
0xd0, 0xac, 0x84, 0xfa, 0x57, 0x8a, 0x2f, 0x50, 0x5f, 0x35, 0x01, 0xdd, 0x5d, 0xe7, 0xd9, 0xe0,
0x7a, 0xfb, 0xde, 0xf5, 0x4d, 0x89, 0x8f, 0x27, 0xf6, 0xd7, 0x87, 0x13, 0x2a, 0xa7, 0xf1, 0x58,
0xc5, 0x6b, 0xbb, 0x17, 0xb1, 0x2b, 0x08, 0x8e, 0x39, 0x95, 0x0b, 0x5b, 0x6f, 0xb7, 0x2f, 0xff,
0xc9, 0x3c, 0xd3, 0x7f, 0xc7, 0x3b, 0x5a, 0xdb, 0xe3, 0x3f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x67,
0x38, 0x22, 0xa3, 0x7e, 0x06, 0x00, 0x00,
// 772 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x55, 0xdd, 0x6e, 0xd3, 0x48,
0x14, 0x56, 0x92, 0xb6, 0x49, 0x4e, 0x7e, 0x9a, 0x9d, 0xdd, 0x6d, 0xdd, 0x6c, 0xd5, 0x46, 0xde,
0x5d, 0x29, 0x5c, 0x60, 0x8b, 0x00, 0x57, 0x08, 0x44, 0xda, 0x02, 0x8a, 0x44, 0x45, 0x30, 0x08,
0x09, 0x6e, 0x82, 0x33, 0x1e, 0x27, 0xa3, 0xc6, 0x1e, 0x77, 0x66, 0x1c, 0xc8, 0x1b, 0xf0, 0x4e,
0xbc, 0x0d, 0x4f, 0x82, 0x66, 0x6c, 0x37, 0x71, 0x92, 0x56, 0x70, 0x13, 0x79, 0xce, 0x39, 0xf3,
0x9d, 0xef, 0x7c, 0xe7, 0xb3, 0x03, 0x87, 0x3c, 0xc2, 0x36, 0x76, 0xf1, 0x94, 0xd8, 0x82, 0xf0,
0x39, 0xc5, 0xc4, 0x8a, 0x38, 0x93, 0x0c, 0x35, 0x25, 0xa7, 0xf3, 0x85, 0xa5, 0x53, 0xd6, 0xfc,
0x41, 0xfb, 0x74, 0xc2, 0xd8, 0x64, 0x46, 0x6c, 0x9d, 0x1d, 0xc7, 0xbe, 0x2d, 0x69, 0x40, 0x84,
0x74, 0x83, 0x28, 0xb9, 0xd0, 0x36, 0x34, 0x12, 0x0b, 0x02, 0x16, 0xe6, 0xa1, 0xda, 0xff, 0xac,
0x5f, 0x25, 0x41, 0x24, 0x17, 0x49, 0xd2, 0xfc, 0x56, 0x84, 0x7a, 0x9f, 0x4b, 0xea, 0xbb, 0x58,
0x0e, 0x42, 0x9f, 0xa1, 0xff, 0xa1, 0x29, 0xf0, 0x94, 0x04, 0xee, 0x68, 0x4e, 0xb8, 0xa0, 0x2c,
0x34, 0x0a, 0x9d, 0x42, 0x77, 0xd7, 0x69, 0x24, 0xd1, 0x0f, 0x49, 0x10, 0x99, 0x50, 0x77, 0x39,
0x9e, 0x52, 0x49, 0xb0, 0x8c, 0x39, 0x31, 0x8a, 0x9d, 0x42, 0xb7, 0xea, 0xe4, 0x62, 0xe8, 0x11,
0x94, 0x31, 0x27, 0xae, 0x24, 0x9e, 0x51, 0xea, 0x14, 0xba, 0xb5, 0x5e, 0xdb, 0x4a, 0xa8, 0x58,
0x19, 0x15, 0xeb, 0x7d, 0x36, 0x85, 0x93, 0x95, 0x2a, 0x02, 0x1e, 0xc3, 0x57, 0x84, 0xdf, 0x10,
0xd8, 0xd1, 0xd8, 0x8d, 0x24, 0x9a, 0x11, 0x68, 0x42, 0x91, 0x09, 0x63, 0x57, 0xa7, 0x8a, 0x4c,
0xa0, 0xe7, 0xd0, 0x9a, 0x52, 0x21, 0x19, 0x5f, 0x8c, 0x22, 0x17, 0x5f, 0xb9, 0x13, 0x22, 0x8c,
0xbd, 0x4e, 0xa9, 0x5b, 0xeb, 0xfd, 0x6d, 0xa5, 0x5a, 0x6a, 0x71, 0xac, 0x61, 0x92, 0x75, 0xf6,
0xd3, 0xf2, 0xf4, 0x2c, 0xcc, 0xaf, 0x80, 0x86, 0xb1, 0xcc, 0xc4, 0x70, 0xc8, 0x75, 0x4c, 0x84,
0x44, 0xa7, 0x50, 0x73, 0xd3, 0xd0, 0x88, 0x7a, 0x5a, 0x8c, 0xaa, 0x03, 0x59, 0x68, 0xe0, 0xa1,
0x3e, 0x34, 0x96, 0x05, 0xa1, 0xcf, 0xb4, 0x14, 0xb5, 0xde, 0xb1, 0x95, 0xdf, 0xa0, 0xb5, 0xaa,
0xb2, 0x12, 0x6a, 0x79, 0x32, 0x7f, 0x94, 0xa0, 0x72, 0x36, 0x63, 0xe3, 0xdf, 0x59, 0x40, 0x47,
0xcf, 0x9f, 0xf4, 0x6a, 0xe5, 0x27, 0x7c, 0xf3, 0x4e, 0x2b, 0xf2, 0x0c, 0x1a, 0xa9, 0x12, 0x9a,
0x97, 0x30, 0x4a, 0x5a, 0x8e, 0xa3, 0xad, 0x72, 0x24, 0xac, 0xa2, 0xe5, 0x41, 0xa0, 0xa7, 0x50,
0x77, 0xa3, 0x68, 0x46, 0xb1, 0x2b, 0x29, 0x0b, 0x85, 0xb1, 0xb3, 0xed, 0x7a, 0x7f, 0x59, 0xe1,
0xe4, 0xca, 0xd1, 0x6b, 0xf8, 0x23, 0xa0, 0x02, 0xb3, 0xd0, 0xa7, 0x93, 0x98, 0xa7, 0x18, 0x55,
0x8d, 0x71, 0x92, 0xc7, 0xb8, 0x5c, 0x2b, 0x73, 0x36, 0x2f, 0xaa, 0x35, 0xb0, 0xc8, 0xbd, 0x8e,
0xc9, 0xc8, 0xa3, 0x5c, 0xed, 0xbd, 0xa4, 0xd6, 0x90, 0x84, 0x2e, 0x28, 0x17, 0x4a, 0xb6, 0x2f,
0xca, 0x7a, 0x2c, 0x96, 0x23, 0x9f, 0xce, 0xd2, 0xed, 0x57, 0x9d, 0x46, 0x16, 0x7d, 0xa9, 0x82,
0xe8, 0x00, 0xf6, 0x3c, 0x3a, 0x21, 0x42, 0x1a, 0x65, 0xbd, 0xc9, 0xf4, 0x84, 0x0e, 0xa1, 0xec,
0x51, 0xdf, 0x57, 0x2b, 0xae, 0x64, 0x09, 0xdf, 0x1f, 0x78, 0xe8, 0x15, 0xb4, 0x70, 0x2c, 0x24,
0x0b, 0x46, 0x9c, 0x08, 0x16, 0x73, 0x4c, 0x84, 0x01, 0x7a, 0x8a, 0xe3, 0xfc, 0x14, 0xe7, 0xba,
0xca, 0x49, 0x8b, 0x9c, 0x7d, 0x9c, 0x3b, 0x0b, 0xf3, 0x33, 0x34, 0x87, 0xb1, 0x54, 0x6b, 0xce,
0xac, 0xb5, 0xd2, 0xb3, 0x90, 0xeb, 0xf9, 0x18, 0xaa, 0xe3, 0x19, 0x1b, 0x27, 0x76, 0x4a, 0x5e,
0x1d, 0x63, 0xdd, 0x4e, 0x99, 0x5f, 0x9c, 0xca, 0x38, 0x7d, 0x32, 0xcf, 0xa1, 0x36, 0x8c, 0xa5,
0x43, 0x44, 0xc4, 0x42, 0x41, 0x52, 0x87, 0x14, 0xee, 0x70, 0x08, 0x82, 0x1d, 0xc2, 0xc4, 0x4c,
0xbb, 0xa8, 0xe2, 0xe8, 0x67, 0xf3, 0x2d, 0xfc, 0x79, 0x49, 0x85, 0xa0, 0xe1, 0x44, 0x75, 0x10,
0xbf, 0xfc, 0x1a, 0x1c, 0x41, 0x25, 0xe1, 0xec, 0x29, 0x57, 0x2a, 0xe5, 0xcb, 0x9a, 0x98, 0x27,
0xcc, 0x2b, 0xf8, 0x2b, 0x0f, 0x99, 0x12, 0xbc, 0x07, 0xad, 0x20, 0x89, 0x8f, 0x32, 0x20, 0x0d,
0x5c, 0x71, 0xf6, 0xd3, 0x78, 0xf6, 0xce, 0xa0, 0xee, 0xb2, 0x74, 0xad, 0x4b, 0x33, 0x58, 0x42,
0xab, 0x66, 0x36, 0xa0, 0x0b, 0x32, 0x23, 0x92, 0xe4, 0xe8, 0xaf, 0xb2, 0x2b, 0xe4, 0xd8, 0xf5,
0xbe, 0x17, 0x61, 0xf7, 0x5c, 0xa9, 0x8a, 0x06, 0x5a, 0xbf, 0x9b, 0x9e, 0xe6, 0xba, 0xe4, 0x9b,
0x5f, 0x87, 0xf6, 0xc1, 0xc6, 0x17, 0xed, 0x85, 0xfa, 0xb8, 0xa2, 0x3e, 0x94, 0xd3, 0x65, 0xa3,
0x93, 0x2d, 0x30, 0x2b, 0x2e, 0xb8, 0x15, 0xe2, 0x23, 0xd4, 0x57, 0x55, 0x43, 0xff, 0xae, 0xe3,
0x6c, 0x59, 0x53, 0xfb, 0xbf, 0xbb, 0x8b, 0x52, 0xe1, 0x07, 0x50, 0x5b, 0xd1, 0x68, 0x73, 0xd0,
0x4d, 0x01, 0x6f, 0x63, 0x79, 0x66, 0x7f, 0xba, 0x3f, 0xa1, 0x72, 0x1a, 0x8f, 0x95, 0xb5, 0x6c,
0xf7, 0x3a, 0x76, 0x05, 0xc1, 0x31, 0xa7, 0x72, 0x61, 0x6b, 0x50, 0xfb, 0xe6, 0x0f, 0xee, 0x89,
0xfe, 0x1d, 0xef, 0x69, 0x80, 0x87, 0x3f, 0x03, 0x00, 0x00, 0xff, 0xff, 0xec, 0x7d, 0x3a, 0x0b,
0xfa, 0x06, 0x00, 0x00,
}