commit
ae43689c40
|
@ -1,5 +1,6 @@
|
||||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
// Code generated by protoc-gen-gogo.
|
||||||
// source: control.proto
|
// source: control.proto
|
||||||
|
// DO NOT EDIT!
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Package moby_buildkit_v1 is a generated protocol buffer package.
|
Package moby_buildkit_v1 is a generated protocol buffer package.
|
||||||
|
@ -8,6 +9,7 @@
|
||||||
control.proto
|
control.proto
|
||||||
|
|
||||||
It has these top-level messages:
|
It has these top-level messages:
|
||||||
|
PruneRequest
|
||||||
DiskUsageRequest
|
DiskUsageRequest
|
||||||
DiskUsageResponse
|
DiskUsageResponse
|
||||||
UsageRecord
|
UsageRecord
|
||||||
|
@ -57,6 +59,14 @@ var _ = time.Kitchen
|
||||||
// proto package needs to be updated.
|
// proto package needs to be updated.
|
||||||
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
|
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
|
||||||
|
|
||||||
|
type PruneRequest struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *PruneRequest) Reset() { *m = PruneRequest{} }
|
||||||
|
func (m *PruneRequest) String() string { return proto.CompactTextString(m) }
|
||||||
|
func (*PruneRequest) ProtoMessage() {}
|
||||||
|
func (*PruneRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{0} }
|
||||||
|
|
||||||
type DiskUsageRequest struct {
|
type DiskUsageRequest struct {
|
||||||
Filter string `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"`
|
Filter string `protobuf:"bytes,1,opt,name=filter,proto3" json:"filter,omitempty"`
|
||||||
}
|
}
|
||||||
|
@ -64,7 +74,7 @@ type DiskUsageRequest struct {
|
||||||
func (m *DiskUsageRequest) Reset() { *m = DiskUsageRequest{} }
|
func (m *DiskUsageRequest) Reset() { *m = DiskUsageRequest{} }
|
||||||
func (m *DiskUsageRequest) String() string { return proto.CompactTextString(m) }
|
func (m *DiskUsageRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*DiskUsageRequest) ProtoMessage() {}
|
func (*DiskUsageRequest) ProtoMessage() {}
|
||||||
func (*DiskUsageRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{0} }
|
func (*DiskUsageRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{1} }
|
||||||
|
|
||||||
func (m *DiskUsageRequest) GetFilter() string {
|
func (m *DiskUsageRequest) GetFilter() string {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -80,7 +90,7 @@ type DiskUsageResponse struct {
|
||||||
func (m *DiskUsageResponse) Reset() { *m = DiskUsageResponse{} }
|
func (m *DiskUsageResponse) Reset() { *m = DiskUsageResponse{} }
|
||||||
func (m *DiskUsageResponse) String() string { return proto.CompactTextString(m) }
|
func (m *DiskUsageResponse) String() string { return proto.CompactTextString(m) }
|
||||||
func (*DiskUsageResponse) ProtoMessage() {}
|
func (*DiskUsageResponse) ProtoMessage() {}
|
||||||
func (*DiskUsageResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{1} }
|
func (*DiskUsageResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{2} }
|
||||||
|
|
||||||
func (m *DiskUsageResponse) GetRecord() []*UsageRecord {
|
func (m *DiskUsageResponse) GetRecord() []*UsageRecord {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -104,7 +114,7 @@ type UsageRecord struct {
|
||||||
func (m *UsageRecord) Reset() { *m = UsageRecord{} }
|
func (m *UsageRecord) Reset() { *m = UsageRecord{} }
|
||||||
func (m *UsageRecord) String() string { return proto.CompactTextString(m) }
|
func (m *UsageRecord) String() string { return proto.CompactTextString(m) }
|
||||||
func (*UsageRecord) ProtoMessage() {}
|
func (*UsageRecord) ProtoMessage() {}
|
||||||
func (*UsageRecord) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{2} }
|
func (*UsageRecord) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{3} }
|
||||||
|
|
||||||
func (m *UsageRecord) GetID() string {
|
func (m *UsageRecord) GetID() string {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -183,7 +193,7 @@ type SolveRequest struct {
|
||||||
func (m *SolveRequest) Reset() { *m = SolveRequest{} }
|
func (m *SolveRequest) Reset() { *m = SolveRequest{} }
|
||||||
func (m *SolveRequest) String() string { return proto.CompactTextString(m) }
|
func (m *SolveRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*SolveRequest) ProtoMessage() {}
|
func (*SolveRequest) ProtoMessage() {}
|
||||||
func (*SolveRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{3} }
|
func (*SolveRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{4} }
|
||||||
|
|
||||||
func (m *SolveRequest) GetRef() string {
|
func (m *SolveRequest) GetRef() string {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -249,7 +259,7 @@ type CacheOptions struct {
|
||||||
func (m *CacheOptions) Reset() { *m = CacheOptions{} }
|
func (m *CacheOptions) Reset() { *m = CacheOptions{} }
|
||||||
func (m *CacheOptions) String() string { return proto.CompactTextString(m) }
|
func (m *CacheOptions) String() string { return proto.CompactTextString(m) }
|
||||||
func (*CacheOptions) ProtoMessage() {}
|
func (*CacheOptions) ProtoMessage() {}
|
||||||
func (*CacheOptions) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{4} }
|
func (*CacheOptions) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{5} }
|
||||||
|
|
||||||
func (m *CacheOptions) GetExportRef() string {
|
func (m *CacheOptions) GetExportRef() string {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -272,7 +282,7 @@ type SolveResponse struct {
|
||||||
func (m *SolveResponse) Reset() { *m = SolveResponse{} }
|
func (m *SolveResponse) Reset() { *m = SolveResponse{} }
|
||||||
func (m *SolveResponse) String() string { return proto.CompactTextString(m) }
|
func (m *SolveResponse) String() string { return proto.CompactTextString(m) }
|
||||||
func (*SolveResponse) ProtoMessage() {}
|
func (*SolveResponse) ProtoMessage() {}
|
||||||
func (*SolveResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{5} }
|
func (*SolveResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{6} }
|
||||||
|
|
||||||
func (m *SolveResponse) GetVtx() []*Vertex {
|
func (m *SolveResponse) GetVtx() []*Vertex {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -288,7 +298,7 @@ type StatusRequest struct {
|
||||||
func (m *StatusRequest) Reset() { *m = StatusRequest{} }
|
func (m *StatusRequest) Reset() { *m = StatusRequest{} }
|
||||||
func (m *StatusRequest) String() string { return proto.CompactTextString(m) }
|
func (m *StatusRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*StatusRequest) ProtoMessage() {}
|
func (*StatusRequest) ProtoMessage() {}
|
||||||
func (*StatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{6} }
|
func (*StatusRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{7} }
|
||||||
|
|
||||||
func (m *StatusRequest) GetRef() string {
|
func (m *StatusRequest) GetRef() string {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -306,7 +316,7 @@ type StatusResponse struct {
|
||||||
func (m *StatusResponse) Reset() { *m = StatusResponse{} }
|
func (m *StatusResponse) Reset() { *m = StatusResponse{} }
|
||||||
func (m *StatusResponse) String() string { return proto.CompactTextString(m) }
|
func (m *StatusResponse) String() string { return proto.CompactTextString(m) }
|
||||||
func (*StatusResponse) ProtoMessage() {}
|
func (*StatusResponse) ProtoMessage() {}
|
||||||
func (*StatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{7} }
|
func (*StatusResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{8} }
|
||||||
|
|
||||||
func (m *StatusResponse) GetVertexes() []*Vertex {
|
func (m *StatusResponse) GetVertexes() []*Vertex {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -342,7 +352,7 @@ type Vertex struct {
|
||||||
func (m *Vertex) Reset() { *m = Vertex{} }
|
func (m *Vertex) Reset() { *m = Vertex{} }
|
||||||
func (m *Vertex) String() string { return proto.CompactTextString(m) }
|
func (m *Vertex) String() string { return proto.CompactTextString(m) }
|
||||||
func (*Vertex) ProtoMessage() {}
|
func (*Vertex) ProtoMessage() {}
|
||||||
func (*Vertex) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{8} }
|
func (*Vertex) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{9} }
|
||||||
|
|
||||||
func (m *Vertex) GetName() string {
|
func (m *Vertex) GetName() string {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -394,7 +404,7 @@ type VertexStatus struct {
|
||||||
func (m *VertexStatus) Reset() { *m = VertexStatus{} }
|
func (m *VertexStatus) Reset() { *m = VertexStatus{} }
|
||||||
func (m *VertexStatus) String() string { return proto.CompactTextString(m) }
|
func (m *VertexStatus) String() string { return proto.CompactTextString(m) }
|
||||||
func (*VertexStatus) ProtoMessage() {}
|
func (*VertexStatus) ProtoMessage() {}
|
||||||
func (*VertexStatus) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{9} }
|
func (*VertexStatus) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{10} }
|
||||||
|
|
||||||
func (m *VertexStatus) GetID() string {
|
func (m *VertexStatus) GetID() string {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -455,7 +465,7 @@ type VertexLog struct {
|
||||||
func (m *VertexLog) Reset() { *m = VertexLog{} }
|
func (m *VertexLog) Reset() { *m = VertexLog{} }
|
||||||
func (m *VertexLog) String() string { return proto.CompactTextString(m) }
|
func (m *VertexLog) String() string { return proto.CompactTextString(m) }
|
||||||
func (*VertexLog) ProtoMessage() {}
|
func (*VertexLog) ProtoMessage() {}
|
||||||
func (*VertexLog) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{10} }
|
func (*VertexLog) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{11} }
|
||||||
|
|
||||||
func (m *VertexLog) GetTimestamp() time.Time {
|
func (m *VertexLog) GetTimestamp() time.Time {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -485,7 +495,7 @@ type BytesMessage struct {
|
||||||
func (m *BytesMessage) Reset() { *m = BytesMessage{} }
|
func (m *BytesMessage) Reset() { *m = BytesMessage{} }
|
||||||
func (m *BytesMessage) String() string { return proto.CompactTextString(m) }
|
func (m *BytesMessage) String() string { return proto.CompactTextString(m) }
|
||||||
func (*BytesMessage) ProtoMessage() {}
|
func (*BytesMessage) ProtoMessage() {}
|
||||||
func (*BytesMessage) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{11} }
|
func (*BytesMessage) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{12} }
|
||||||
|
|
||||||
func (m *BytesMessage) GetData() []byte {
|
func (m *BytesMessage) GetData() []byte {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -501,7 +511,7 @@ type ListWorkersRequest struct {
|
||||||
func (m *ListWorkersRequest) Reset() { *m = ListWorkersRequest{} }
|
func (m *ListWorkersRequest) Reset() { *m = ListWorkersRequest{} }
|
||||||
func (m *ListWorkersRequest) String() string { return proto.CompactTextString(m) }
|
func (m *ListWorkersRequest) String() string { return proto.CompactTextString(m) }
|
||||||
func (*ListWorkersRequest) ProtoMessage() {}
|
func (*ListWorkersRequest) ProtoMessage() {}
|
||||||
func (*ListWorkersRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{12} }
|
func (*ListWorkersRequest) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{13} }
|
||||||
|
|
||||||
func (m *ListWorkersRequest) GetFilter() []string {
|
func (m *ListWorkersRequest) GetFilter() []string {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -517,7 +527,7 @@ type ListWorkersResponse struct {
|
||||||
func (m *ListWorkersResponse) Reset() { *m = ListWorkersResponse{} }
|
func (m *ListWorkersResponse) Reset() { *m = ListWorkersResponse{} }
|
||||||
func (m *ListWorkersResponse) String() string { return proto.CompactTextString(m) }
|
func (m *ListWorkersResponse) String() string { return proto.CompactTextString(m) }
|
||||||
func (*ListWorkersResponse) ProtoMessage() {}
|
func (*ListWorkersResponse) ProtoMessage() {}
|
||||||
func (*ListWorkersResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{13} }
|
func (*ListWorkersResponse) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{14} }
|
||||||
|
|
||||||
func (m *ListWorkersResponse) GetRecord() []*WorkerRecord {
|
func (m *ListWorkersResponse) GetRecord() []*WorkerRecord {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -534,7 +544,7 @@ type WorkerRecord struct {
|
||||||
func (m *WorkerRecord) Reset() { *m = WorkerRecord{} }
|
func (m *WorkerRecord) Reset() { *m = WorkerRecord{} }
|
||||||
func (m *WorkerRecord) String() string { return proto.CompactTextString(m) }
|
func (m *WorkerRecord) String() string { return proto.CompactTextString(m) }
|
||||||
func (*WorkerRecord) ProtoMessage() {}
|
func (*WorkerRecord) ProtoMessage() {}
|
||||||
func (*WorkerRecord) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{14} }
|
func (*WorkerRecord) Descriptor() ([]byte, []int) { return fileDescriptorControl, []int{15} }
|
||||||
|
|
||||||
func (m *WorkerRecord) GetID() string {
|
func (m *WorkerRecord) GetID() string {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
|
@ -551,6 +561,7 @@ func (m *WorkerRecord) GetLabels() map[string]string {
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
proto.RegisterType((*PruneRequest)(nil), "moby.buildkit.v1.PruneRequest")
|
||||||
proto.RegisterType((*DiskUsageRequest)(nil), "moby.buildkit.v1.DiskUsageRequest")
|
proto.RegisterType((*DiskUsageRequest)(nil), "moby.buildkit.v1.DiskUsageRequest")
|
||||||
proto.RegisterType((*DiskUsageResponse)(nil), "moby.buildkit.v1.DiskUsageResponse")
|
proto.RegisterType((*DiskUsageResponse)(nil), "moby.buildkit.v1.DiskUsageResponse")
|
||||||
proto.RegisterType((*UsageRecord)(nil), "moby.buildkit.v1.UsageRecord")
|
proto.RegisterType((*UsageRecord)(nil), "moby.buildkit.v1.UsageRecord")
|
||||||
|
@ -580,6 +591,7 @@ const _ = grpc.SupportPackageIsVersion4
|
||||||
|
|
||||||
type ControlClient interface {
|
type ControlClient interface {
|
||||||
DiskUsage(ctx context.Context, in *DiskUsageRequest, opts ...grpc.CallOption) (*DiskUsageResponse, error)
|
DiskUsage(ctx context.Context, in *DiskUsageRequest, opts ...grpc.CallOption) (*DiskUsageResponse, error)
|
||||||
|
Prune(ctx context.Context, in *PruneRequest, opts ...grpc.CallOption) (Control_PruneClient, error)
|
||||||
Solve(ctx context.Context, in *SolveRequest, opts ...grpc.CallOption) (*SolveResponse, error)
|
Solve(ctx context.Context, in *SolveRequest, opts ...grpc.CallOption) (*SolveResponse, error)
|
||||||
Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (Control_StatusClient, error)
|
Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (Control_StatusClient, error)
|
||||||
Session(ctx context.Context, opts ...grpc.CallOption) (Control_SessionClient, error)
|
Session(ctx context.Context, opts ...grpc.CallOption) (Control_SessionClient, error)
|
||||||
|
@ -603,6 +615,38 @@ func (c *controlClient) DiskUsage(ctx context.Context, in *DiskUsageRequest, opt
|
||||||
return out, nil
|
return out, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *controlClient) Prune(ctx context.Context, in *PruneRequest, opts ...grpc.CallOption) (Control_PruneClient, error) {
|
||||||
|
stream, err := grpc.NewClientStream(ctx, &_Control_serviceDesc.Streams[0], c.cc, "/moby.buildkit.v1.Control/Prune", opts...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
x := &controlPruneClient{stream}
|
||||||
|
if err := x.ClientStream.SendMsg(in); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if err := x.ClientStream.CloseSend(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return x, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type Control_PruneClient interface {
|
||||||
|
Recv() (*UsageRecord, error)
|
||||||
|
grpc.ClientStream
|
||||||
|
}
|
||||||
|
|
||||||
|
type controlPruneClient struct {
|
||||||
|
grpc.ClientStream
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *controlPruneClient) Recv() (*UsageRecord, error) {
|
||||||
|
m := new(UsageRecord)
|
||||||
|
if err := x.ClientStream.RecvMsg(m); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return m, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (c *controlClient) Solve(ctx context.Context, in *SolveRequest, opts ...grpc.CallOption) (*SolveResponse, error) {
|
func (c *controlClient) Solve(ctx context.Context, in *SolveRequest, opts ...grpc.CallOption) (*SolveResponse, error) {
|
||||||
out := new(SolveResponse)
|
out := new(SolveResponse)
|
||||||
err := grpc.Invoke(ctx, "/moby.buildkit.v1.Control/Solve", in, out, c.cc, opts...)
|
err := grpc.Invoke(ctx, "/moby.buildkit.v1.Control/Solve", in, out, c.cc, opts...)
|
||||||
|
@ -613,7 +657,7 @@ func (c *controlClient) Solve(ctx context.Context, in *SolveRequest, opts ...grp
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controlClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (Control_StatusClient, error) {
|
func (c *controlClient) Status(ctx context.Context, in *StatusRequest, opts ...grpc.CallOption) (Control_StatusClient, error) {
|
||||||
stream, err := grpc.NewClientStream(ctx, &_Control_serviceDesc.Streams[0], c.cc, "/moby.buildkit.v1.Control/Status", opts...)
|
stream, err := grpc.NewClientStream(ctx, &_Control_serviceDesc.Streams[1], c.cc, "/moby.buildkit.v1.Control/Status", opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -645,7 +689,7 @@ func (x *controlStatusClient) Recv() (*StatusResponse, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *controlClient) Session(ctx context.Context, opts ...grpc.CallOption) (Control_SessionClient, error) {
|
func (c *controlClient) Session(ctx context.Context, opts ...grpc.CallOption) (Control_SessionClient, error) {
|
||||||
stream, err := grpc.NewClientStream(ctx, &_Control_serviceDesc.Streams[1], c.cc, "/moby.buildkit.v1.Control/Session", opts...)
|
stream, err := grpc.NewClientStream(ctx, &_Control_serviceDesc.Streams[2], c.cc, "/moby.buildkit.v1.Control/Session", opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -688,6 +732,7 @@ func (c *controlClient) ListWorkers(ctx context.Context, in *ListWorkersRequest,
|
||||||
|
|
||||||
type ControlServer interface {
|
type ControlServer interface {
|
||||||
DiskUsage(context.Context, *DiskUsageRequest) (*DiskUsageResponse, error)
|
DiskUsage(context.Context, *DiskUsageRequest) (*DiskUsageResponse, error)
|
||||||
|
Prune(*PruneRequest, Control_PruneServer) error
|
||||||
Solve(context.Context, *SolveRequest) (*SolveResponse, error)
|
Solve(context.Context, *SolveRequest) (*SolveResponse, error)
|
||||||
Status(*StatusRequest, Control_StatusServer) error
|
Status(*StatusRequest, Control_StatusServer) error
|
||||||
Session(Control_SessionServer) error
|
Session(Control_SessionServer) error
|
||||||
|
@ -716,6 +761,27 @@ func _Control_DiskUsage_Handler(srv interface{}, ctx context.Context, dec func(i
|
||||||
return interceptor(ctx, in, info, handler)
|
return interceptor(ctx, in, info, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func _Control_Prune_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||||
|
m := new(PruneRequest)
|
||||||
|
if err := stream.RecvMsg(m); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return srv.(ControlServer).Prune(m, &controlPruneServer{stream})
|
||||||
|
}
|
||||||
|
|
||||||
|
type Control_PruneServer interface {
|
||||||
|
Send(*UsageRecord) error
|
||||||
|
grpc.ServerStream
|
||||||
|
}
|
||||||
|
|
||||||
|
type controlPruneServer struct {
|
||||||
|
grpc.ServerStream
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *controlPruneServer) Send(m *UsageRecord) error {
|
||||||
|
return x.ServerStream.SendMsg(m)
|
||||||
|
}
|
||||||
|
|
||||||
func _Control_Solve_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
func _Control_Solve_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
|
||||||
in := new(SolveRequest)
|
in := new(SolveRequest)
|
||||||
if err := dec(in); err != nil {
|
if err := dec(in); err != nil {
|
||||||
|
@ -817,6 +883,11 @@ var _Control_serviceDesc = grpc.ServiceDesc{
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Streams: []grpc.StreamDesc{
|
Streams: []grpc.StreamDesc{
|
||||||
|
{
|
||||||
|
StreamName: "Prune",
|
||||||
|
Handler: _Control_Prune_Handler,
|
||||||
|
ServerStreams: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
StreamName: "Status",
|
StreamName: "Status",
|
||||||
Handler: _Control_Status_Handler,
|
Handler: _Control_Status_Handler,
|
||||||
|
@ -832,6 +903,24 @@ var _Control_serviceDesc = grpc.ServiceDesc{
|
||||||
Metadata: "control.proto",
|
Metadata: "control.proto",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m *PruneRequest) Marshal() (dAtA []byte, err error) {
|
||||||
|
size := m.Size()
|
||||||
|
dAtA = make([]byte, size)
|
||||||
|
n, err := m.MarshalTo(dAtA)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return dAtA[:n], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *PruneRequest) MarshalTo(dAtA []byte) (int, error) {
|
||||||
|
var i int
|
||||||
|
_ = i
|
||||||
|
var l int
|
||||||
|
_ = l
|
||||||
|
return i, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (m *DiskUsageRequest) Marshal() (dAtA []byte, err error) {
|
func (m *DiskUsageRequest) Marshal() (dAtA []byte, err error) {
|
||||||
size := m.Size()
|
size := m.Size()
|
||||||
dAtA = make([]byte, size)
|
dAtA = make([]byte, size)
|
||||||
|
@ -1555,6 +1644,12 @@ func encodeVarintControl(dAtA []byte, offset int, v uint64) int {
|
||||||
dAtA[offset] = uint8(v)
|
dAtA[offset] = uint8(v)
|
||||||
return offset + 1
|
return offset + 1
|
||||||
}
|
}
|
||||||
|
func (m *PruneRequest) Size() (n int) {
|
||||||
|
var l int
|
||||||
|
_ = l
|
||||||
|
return n
|
||||||
|
}
|
||||||
|
|
||||||
func (m *DiskUsageRequest) Size() (n int) {
|
func (m *DiskUsageRequest) Size() (n int) {
|
||||||
var l int
|
var l int
|
||||||
_ = l
|
_ = l
|
||||||
|
@ -1870,6 +1965,56 @@ func sovControl(x uint64) (n int) {
|
||||||
func sozControl(x uint64) (n int) {
|
func sozControl(x uint64) (n int) {
|
||||||
return sovControl(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
return sovControl(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||||
}
|
}
|
||||||
|
func (m *PruneRequest) Unmarshal(dAtA []byte) error {
|
||||||
|
l := len(dAtA)
|
||||||
|
iNdEx := 0
|
||||||
|
for iNdEx < l {
|
||||||
|
preIndex := iNdEx
|
||||||
|
var wire uint64
|
||||||
|
for shift := uint(0); ; shift += 7 {
|
||||||
|
if shift >= 64 {
|
||||||
|
return ErrIntOverflowControl
|
||||||
|
}
|
||||||
|
if iNdEx >= l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
b := dAtA[iNdEx]
|
||||||
|
iNdEx++
|
||||||
|
wire |= (uint64(b) & 0x7F) << shift
|
||||||
|
if b < 0x80 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fieldNum := int32(wire >> 3)
|
||||||
|
wireType := int(wire & 0x7)
|
||||||
|
if wireType == 4 {
|
||||||
|
return fmt.Errorf("proto: PruneRequest: wiretype end group for non-group")
|
||||||
|
}
|
||||||
|
if fieldNum <= 0 {
|
||||||
|
return fmt.Errorf("proto: PruneRequest: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||||
|
}
|
||||||
|
switch fieldNum {
|
||||||
|
default:
|
||||||
|
iNdEx = preIndex
|
||||||
|
skippy, err := skipControl(dAtA[iNdEx:])
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if skippy < 0 {
|
||||||
|
return ErrInvalidLengthControl
|
||||||
|
}
|
||||||
|
if (iNdEx + skippy) > l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
iNdEx += skippy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if iNdEx > l {
|
||||||
|
return io.ErrUnexpectedEOF
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
func (m *DiskUsageRequest) Unmarshal(dAtA []byte) error {
|
func (m *DiskUsageRequest) Unmarshal(dAtA []byte) error {
|
||||||
l := len(dAtA)
|
l := len(dAtA)
|
||||||
iNdEx := 0
|
iNdEx := 0
|
||||||
|
@ -4406,75 +4551,77 @@ var (
|
||||||
func init() { proto.RegisterFile("control.proto", fileDescriptorControl) }
|
func init() { proto.RegisterFile("control.proto", fileDescriptorControl) }
|
||||||
|
|
||||||
var fileDescriptorControl = []byte{
|
var fileDescriptorControl = []byte{
|
||||||
// 1120 bytes of a gzipped FileDescriptorProto
|
// 1144 bytes of a gzipped FileDescriptorProto
|
||||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xa4, 0x56, 0xcd, 0x6e, 0x23, 0x45,
|
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x56, 0xcd, 0x6e, 0x23, 0xc5,
|
||||||
0x10, 0x66, 0x3c, 0xce, 0xd8, 0x2e, 0x3b, 0xab, 0xd0, 0xa0, 0xd5, 0x68, 0x00, 0xc7, 0x0c, 0x20,
|
0x13, 0xff, 0x8f, 0xed, 0x8c, 0xed, 0xb2, 0x13, 0xe5, 0xdf, 0xa0, 0xd5, 0x68, 0x00, 0xc7, 0x0c,
|
||||||
0x59, 0xd1, 0xee, 0x78, 0x37, 0xfc, 0x08, 0x82, 0x84, 0x76, 0x1d, 0x2f, 0x22, 0x51, 0x22, 0x50,
|
0x20, 0x59, 0xd1, 0xee, 0x38, 0x1b, 0x3e, 0x04, 0x41, 0x42, 0xbb, 0x8e, 0x17, 0x91, 0x28, 0x11,
|
||||||
0x67, 0xc3, 0x4a, 0xdc, 0xc6, 0x76, 0x67, 0x76, 0x94, 0xf1, 0xf4, 0xd0, 0xdd, 0x8e, 0x12, 0x9e,
|
0xab, 0xc9, 0x86, 0x95, 0xb8, 0x8d, 0xed, 0xce, 0xec, 0x28, 0xe3, 0xe9, 0xa1, 0xbb, 0x27, 0x4a,
|
||||||
0x82, 0x03, 0x57, 0x4e, 0x3c, 0x02, 0x4f, 0xc0, 0x01, 0x69, 0x8f, 0x9c, 0x39, 0x04, 0x94, 0x07,
|
0x78, 0x0a, 0x0e, 0x5c, 0x79, 0x0a, 0x9e, 0x80, 0x03, 0xd2, 0x1e, 0x39, 0x73, 0x08, 0x28, 0x77,
|
||||||
0xe0, 0x19, 0x50, 0xff, 0x8c, 0x3d, 0xce, 0xe4, 0x7f, 0x4f, 0xd3, 0x55, 0x5d, 0xf5, 0x75, 0x75,
|
0x78, 0x06, 0xd4, 0x1f, 0x63, 0xb7, 0x63, 0xe7, 0x73, 0x4f, 0xd3, 0xd5, 0x5d, 0xf5, 0xeb, 0xea,
|
||||||
0x7d, 0x35, 0x55, 0x0d, 0xcb, 0x23, 0x9a, 0x0a, 0x46, 0x93, 0x20, 0x63, 0x54, 0x50, 0xb4, 0x32,
|
0xfa, 0xd5, 0x54, 0x15, 0x2c, 0x0f, 0x49, 0xca, 0x29, 0x49, 0xfc, 0x8c, 0x12, 0x4e, 0xd0, 0xea,
|
||||||
0xa1, 0xc3, 0x93, 0x60, 0x38, 0x8d, 0x93, 0xf1, 0x61, 0x2c, 0x82, 0xa3, 0xc7, 0xde, 0xc3, 0x28,
|
0x98, 0x0c, 0xce, 0xfc, 0x41, 0x1e, 0x27, 0xa3, 0xe3, 0x98, 0xfb, 0x27, 0x8f, 0xdd, 0x47, 0x51,
|
||||||
0x16, 0x2f, 0xa7, 0xc3, 0x60, 0x44, 0x27, 0xbd, 0x88, 0x46, 0xb4, 0xa7, 0x0c, 0x87, 0xd3, 0x03,
|
0xcc, 0x5f, 0xe5, 0x03, 0x7f, 0x48, 0xc6, 0xdd, 0x88, 0x44, 0xa4, 0x2b, 0x15, 0x07, 0xf9, 0x91,
|
||||||
0x25, 0x29, 0x41, 0xad, 0x34, 0x80, 0xb7, 0x1a, 0x51, 0x1a, 0x25, 0x64, 0x6e, 0x25, 0xe2, 0x09,
|
0x94, 0xa4, 0x20, 0x57, 0x0a, 0xc0, 0x5d, 0x8b, 0x08, 0x89, 0x12, 0x3c, 0xd5, 0xe2, 0xf1, 0x18,
|
||||||
0xe1, 0x22, 0x9c, 0x64, 0xc6, 0xe0, 0x41, 0x01, 0x4f, 0x1e, 0xd6, 0xcb, 0x0f, 0xeb, 0x71, 0x9a,
|
0x33, 0x1e, 0x8e, 0x33, 0xad, 0xf0, 0xd0, 0xc0, 0x13, 0x97, 0x75, 0x8b, 0xcb, 0xba, 0x8c, 0x24,
|
||||||
0x1c, 0x11, 0xd6, 0xcb, 0x86, 0x3d, 0x9a, 0x71, 0x6d, 0xed, 0xaf, 0xc1, 0xca, 0x20, 0xe6, 0x87,
|
0x27, 0x98, 0x76, 0xb3, 0x41, 0x97, 0x64, 0x4c, 0x69, 0x7b, 0x2b, 0xd0, 0x7c, 0x4e, 0xf3, 0x14,
|
||||||
0xfb, 0x3c, 0x8c, 0x08, 0x26, 0x3f, 0x4e, 0x09, 0x17, 0xe8, 0x3e, 0x38, 0x07, 0x71, 0x22, 0x08,
|
0x07, 0xf8, 0x87, 0x1c, 0x33, 0xee, 0xad, 0xc3, 0x6a, 0x3f, 0x66, 0xc7, 0x87, 0x2c, 0x8c, 0x8a,
|
||||||
0x73, 0xad, 0x8e, 0xd5, 0x6d, 0x60, 0x23, 0xf9, 0xdb, 0xf0, 0x66, 0xc1, 0x96, 0x67, 0x34, 0xe5,
|
0x3d, 0xf4, 0x00, 0xec, 0xa3, 0x38, 0xe1, 0x98, 0x3a, 0x56, 0xdb, 0xea, 0xd4, 0x03, 0x2d, 0x79,
|
||||||
0x04, 0x7d, 0x0a, 0x0e, 0x23, 0x23, 0xca, 0xc6, 0xae, 0xd5, 0xb1, 0xbb, 0xcd, 0xf5, 0xf7, 0x82,
|
0xbb, 0xf0, 0x7f, 0x43, 0x97, 0x65, 0x24, 0x65, 0x18, 0x7d, 0x0a, 0x36, 0xc5, 0x43, 0x42, 0x47,
|
||||||
0xf3, 0x37, 0x0c, 0x8c, 0x83, 0x34, 0xc2, 0xc6, 0xd8, 0xff, 0xa3, 0x02, 0xcd, 0x82, 0x1e, 0xdd,
|
0x8e, 0xd5, 0x2e, 0x77, 0x1a, 0x9b, 0xef, 0xf9, 0x97, 0x5f, 0xec, 0x6b, 0x03, 0xa1, 0x14, 0x68,
|
||||||
0x83, 0xca, 0xd6, 0xc0, 0x9c, 0x57, 0xd9, 0x1a, 0x20, 0x17, 0x6a, 0xbb, 0x53, 0x11, 0x0e, 0x13,
|
0x65, 0xef, 0xb7, 0x12, 0x34, 0x8c, 0x7d, 0xb4, 0x02, 0xa5, 0x9d, 0xbe, 0xbe, 0xaf, 0xb4, 0xd3,
|
||||||
0xe2, 0x56, 0x3a, 0x56, 0xb7, 0x8e, 0x73, 0x11, 0xbd, 0x0d, 0x4b, 0x5b, 0xe9, 0x3e, 0x27, 0xae,
|
0x47, 0x0e, 0x54, 0xf7, 0x73, 0x1e, 0x0e, 0x12, 0xec, 0x94, 0xda, 0x56, 0xa7, 0x16, 0x14, 0x22,
|
||||||
0xad, 0xf4, 0x5a, 0x40, 0x08, 0xaa, 0x7b, 0xf1, 0x4f, 0xc4, 0xad, 0x76, 0xac, 0xae, 0x8d, 0xd5,
|
0x7a, 0x1b, 0x96, 0x76, 0xd2, 0x43, 0x86, 0x9d, 0xb2, 0xdc, 0x57, 0x02, 0x42, 0x50, 0x39, 0x88,
|
||||||
0x5a, 0xde, 0xe3, 0xbb, 0x90, 0x91, 0x54, 0xb8, 0x4b, 0xfa, 0x1e, 0x5a, 0x42, 0x7d, 0x68, 0x6c,
|
0x7f, 0xc4, 0x4e, 0xa5, 0x6d, 0x75, 0xca, 0x81, 0x5c, 0x8b, 0x77, 0x3c, 0x0f, 0x29, 0x4e, 0xb9,
|
||||||
0x32, 0x12, 0x0a, 0x32, 0x7e, 0x2a, 0x5c, 0xa7, 0x63, 0x75, 0x9b, 0xeb, 0x5e, 0xa0, 0xd3, 0x1a,
|
0xb3, 0xa4, 0xde, 0xa1, 0x24, 0xd4, 0x83, 0xfa, 0x36, 0xc5, 0x21, 0xc7, 0xa3, 0xa7, 0xdc, 0xb1,
|
||||||
0xe4, 0x69, 0x0d, 0x9e, 0xe7, 0x69, 0xed, 0xd7, 0x5f, 0x9d, 0xae, 0xbe, 0xf1, 0xf3, 0x3f, 0xab,
|
0xdb, 0x56, 0xa7, 0xb1, 0xe9, 0xfa, 0x2a, 0xcc, 0x7e, 0x11, 0x66, 0xff, 0x45, 0x11, 0xe6, 0x5e,
|
||||||
0x16, 0x9e, 0xbb, 0xa1, 0x27, 0x00, 0x3b, 0x21, 0x17, 0xfb, 0x5c, 0x81, 0xd4, 0xae, 0x05, 0xa9,
|
0xed, 0xf5, 0xf9, 0xda, 0xff, 0x7e, 0xfa, 0x6b, 0xcd, 0x0a, 0xa6, 0x66, 0xe8, 0x09, 0xc0, 0x5e,
|
||||||
0x2a, 0x80, 0x82, 0x0f, 0x6a, 0x03, 0xa8, 0x04, 0x6c, 0xd2, 0x69, 0x2a, 0xdc, 0xba, 0x8a, 0xbb,
|
0xc8, 0xf8, 0x21, 0x93, 0x20, 0xd5, 0x1b, 0x41, 0x2a, 0x12, 0xc0, 0xb0, 0x41, 0x2d, 0x00, 0x19,
|
||||||
0xa0, 0x41, 0x1d, 0x68, 0x0e, 0x08, 0x1f, 0xb1, 0x38, 0x13, 0x31, 0x4d, 0xdd, 0x86, 0xba, 0x42,
|
0x80, 0x6d, 0x92, 0xa7, 0xdc, 0xa9, 0x49, 0xbf, 0x8d, 0x1d, 0xd4, 0x86, 0x46, 0x1f, 0xb3, 0x21,
|
||||||
0x51, 0xe5, 0xff, 0x52, 0x85, 0xd6, 0x9e, 0xe4, 0x34, 0x27, 0x6e, 0x05, 0x6c, 0x4c, 0x0e, 0x4c,
|
0x8d, 0x33, 0x1e, 0x93, 0xd4, 0xa9, 0xcb, 0x27, 0x98, 0x5b, 0xde, 0xcf, 0x15, 0x68, 0x1e, 0x08,
|
||||||
0x16, 0xe5, 0x12, 0x05, 0x00, 0x03, 0x72, 0x10, 0xa7, 0xb1, 0xc2, 0xa8, 0xa8, 0x30, 0xef, 0x05,
|
0x8e, 0x0b, 0xe2, 0x56, 0xa1, 0x1c, 0xe0, 0x23, 0x1d, 0x45, 0xb1, 0x44, 0x3e, 0x40, 0x1f, 0x1f,
|
||||||
0xd9, 0x30, 0x98, 0x6b, 0x71, 0xc1, 0x02, 0x79, 0x50, 0x7f, 0x76, 0x9c, 0x51, 0x26, 0xc9, 0xb7,
|
0xc5, 0x69, 0x2c, 0x31, 0x4a, 0xd2, 0xcd, 0x15, 0x3f, 0x1b, 0xf8, 0xd3, 0xdd, 0xc0, 0xd0, 0x40,
|
||||||
0x15, 0xcc, 0x4c, 0x46, 0x2f, 0x60, 0x39, 0x5f, 0x3f, 0x15, 0x82, 0x71, 0xb7, 0xaa, 0x08, 0x7f,
|
0x2e, 0xd4, 0x9e, 0x9d, 0x66, 0x84, 0x0a, 0xf2, 0xcb, 0x12, 0x66, 0x22, 0xa3, 0x97, 0xb0, 0x5c,
|
||||||
0x5c, 0x26, 0xbc, 0x18, 0x54, 0xb0, 0xe0, 0xf3, 0x2c, 0x15, 0xec, 0x04, 0x2f, 0xe2, 0x48, 0xae,
|
0xac, 0x9f, 0x72, 0x4e, 0x99, 0x53, 0x91, 0x84, 0x3f, 0x9e, 0x27, 0xdc, 0x74, 0xca, 0x9f, 0xb1,
|
||||||
0xf7, 0x08, 0xe7, 0x32, 0x42, 0x4d, 0x54, 0x2e, 0xca, 0x70, 0xbe, 0x66, 0x34, 0x15, 0x24, 0x1d,
|
0x79, 0x96, 0x72, 0x7a, 0x16, 0xcc, 0xe2, 0x08, 0xae, 0x0f, 0x30, 0x63, 0xc2, 0x43, 0x45, 0x54,
|
||||||
0x2b, 0xa2, 0x1a, 0x78, 0x26, 0xcb, 0x70, 0xf2, 0xb5, 0x0e, 0xa7, 0x76, 0xa3, 0x70, 0x16, 0x7c,
|
0x21, 0x0a, 0x77, 0xbe, 0xa6, 0x24, 0xe5, 0x38, 0x1d, 0x49, 0xa2, 0xea, 0xc1, 0x44, 0x16, 0xee,
|
||||||
0x4c, 0x38, 0x0b, 0x3a, 0xb4, 0x01, 0x4b, 0x9b, 0xe1, 0xe8, 0x25, 0x51, 0x9c, 0x34, 0xd7, 0xdb,
|
0x14, 0x6b, 0xe5, 0x4e, 0xf5, 0x56, 0xee, 0xcc, 0xd8, 0x68, 0x77, 0x66, 0xf6, 0xd0, 0x16, 0x2c,
|
||||||
0x65, 0x40, 0xb5, 0xfd, 0xad, 0x22, 0x81, 0xf7, 0xab, 0xb2, 0x3c, 0xb0, 0x76, 0xf1, 0x9e, 0x00,
|
0x6d, 0x87, 0xc3, 0x57, 0x58, 0x72, 0xd2, 0xd8, 0x6c, 0xcd, 0x03, 0xca, 0xe3, 0x6f, 0x25, 0x09,
|
||||||
0x2a, 0xdf, 0x57, 0xf2, 0x72, 0x48, 0x4e, 0x72, 0x5e, 0x0e, 0xc9, 0x89, 0x2c, 0xe2, 0xa3, 0x30,
|
0xac, 0x57, 0x11, 0xe9, 0x11, 0x28, 0x13, 0xf7, 0x09, 0xa0, 0xf9, 0xf7, 0x0a, 0x5e, 0x8e, 0xf1,
|
||||||
0x99, 0xea, 0xe2, 0x6e, 0x60, 0x2d, 0x6c, 0x54, 0x3e, 0xb7, 0x24, 0x42, 0x39, 0xc4, 0xdb, 0x20,
|
0x59, 0xc1, 0xcb, 0x31, 0x3e, 0x13, 0x49, 0x7c, 0x12, 0x26, 0xb9, 0x4a, 0xee, 0x7a, 0xa0, 0x84,
|
||||||
0xf8, 0xdb, 0xd0, 0x2a, 0x06, 0x88, 0xde, 0x85, 0x86, 0x8e, 0x69, 0x5e, 0x1b, 0x73, 0x85, 0xdc,
|
0xad, 0xd2, 0xe7, 0x96, 0x40, 0x98, 0x77, 0xf1, 0x2e, 0x08, 0xde, 0x2e, 0x34, 0x4d, 0x07, 0xd1,
|
||||||
0xdd, 0x9a, 0xe4, 0xbb, 0x1a, 0x6b, 0xae, 0xf0, 0xbf, 0x84, 0x65, 0x93, 0x3d, 0xf3, 0xbb, 0xaf,
|
0xbb, 0x50, 0x57, 0x3e, 0x4d, 0x73, 0x63, 0xba, 0x21, 0x4e, 0x77, 0xc6, 0xc5, 0xa9, 0xc2, 0x9a,
|
||||||
0x81, 0x7d, 0x24, 0x8e, 0xcd, 0xbf, 0xee, 0x96, 0x53, 0xf3, 0x3d, 0x61, 0x82, 0x1c, 0x63, 0x69,
|
0x6e, 0x78, 0x5f, 0xc2, 0xb2, 0x8e, 0x9e, 0xfe, 0xdd, 0xd7, 0xa1, 0x7c, 0xc2, 0x4f, 0xf5, 0xbf,
|
||||||
0xe4, 0xbf, 0x0f, 0xcb, 0x7b, 0x22, 0x14, 0x53, 0x7e, 0x69, 0x7d, 0xfa, 0xbf, 0x5b, 0x70, 0x2f,
|
0xee, 0xcc, 0x87, 0xe6, 0x3b, 0x4c, 0x39, 0x3e, 0x0d, 0x84, 0x92, 0xf7, 0x3e, 0x2c, 0x1f, 0xf0,
|
||||||
0xb7, 0x31, 0x27, 0x7c, 0x02, 0xf5, 0x23, 0x05, 0x42, 0xf8, 0xb5, 0xc7, 0xcc, 0x2c, 0xd1, 0x06,
|
0x90, 0xe7, 0xec, 0xca, 0xfc, 0xf4, 0x7e, 0xb5, 0x60, 0xa5, 0xd0, 0xd1, 0x37, 0x7c, 0x02, 0xb5,
|
||||||
0xd4, 0xb9, 0xc2, 0x21, 0xdc, 0xad, 0x28, 0xaf, 0xf6, 0x65, 0x5e, 0xe6, 0xbc, 0x99, 0x3d, 0xea,
|
0x13, 0x09, 0x82, 0xd9, 0x8d, 0xd7, 0x4c, 0x34, 0xd1, 0x16, 0xd4, 0x98, 0xc4, 0xc1, 0xcc, 0x29,
|
||||||
0x41, 0x35, 0xa1, 0x11, 0x77, 0x6d, 0xe5, 0xf7, 0xce, 0x65, 0x7e, 0x3b, 0x34, 0xc2, 0xca, 0xd0,
|
0x49, 0xab, 0xd6, 0x55, 0x56, 0xfa, 0xbe, 0x89, 0x3e, 0xea, 0x42, 0x25, 0x21, 0x11, 0x73, 0xca,
|
||||||
0x3f, 0xad, 0x80, 0xa3, 0x75, 0x68, 0x1b, 0x9c, 0x71, 0x1c, 0x11, 0x2e, 0xf4, 0xad, 0xfa, 0xeb,
|
0xd2, 0xee, 0x9d, 0xab, 0xec, 0xf6, 0x48, 0x14, 0x48, 0x45, 0xef, 0xbc, 0x04, 0xb6, 0xda, 0x43,
|
||||||
0xb2, 0x1a, 0xfe, 0x3e, 0x5d, 0x5d, 0x2b, 0x74, 0x61, 0x9a, 0x91, 0x54, 0x4e, 0x81, 0x30, 0x4e,
|
0xbb, 0x60, 0x8f, 0xe2, 0x08, 0x33, 0xae, 0x5e, 0xd5, 0xdb, 0x14, 0xd9, 0xf0, 0xe7, 0xf9, 0xda,
|
||||||
0x09, 0xe3, 0xbd, 0x88, 0x3e, 0xd4, 0x2e, 0xc1, 0x40, 0x7d, 0xb0, 0x41, 0x90, 0x58, 0x71, 0x9a,
|
0xba, 0x51, 0x95, 0x49, 0x86, 0x53, 0xd1, 0x15, 0xc2, 0x38, 0xc5, 0x94, 0x75, 0x23, 0xf2, 0x48,
|
||||||
0x4d, 0x85, 0xbe, 0xc1, 0x1d, 0xb1, 0x34, 0x82, 0xec, 0x87, 0x69, 0x38, 0x21, 0xe6, 0x27, 0x56,
|
0x99, 0xf8, 0x7d, 0xf9, 0x09, 0x34, 0x82, 0xc0, 0x8a, 0xd3, 0x2c, 0xe7, 0xea, 0x05, 0xf7, 0xc4,
|
||||||
0x6b, 0xd9, 0x0f, 0x47, 0xb2, 0x30, 0xc6, 0xaa, 0x4b, 0xd6, 0xb1, 0x91, 0xd0, 0x06, 0xd4, 0xb8,
|
0x52, 0x08, 0xa2, 0x1e, 0xa6, 0xe1, 0x18, 0xeb, 0x9f, 0x58, 0xae, 0x45, 0x3d, 0x1c, 0x8a, 0xc4,
|
||||||
0x08, 0x99, 0x20, 0x63, 0xf5, 0xff, 0xdd, 0xa4, 0x91, 0xe5, 0x0e, 0xe8, 0x2b, 0x68, 0x8c, 0xe8,
|
0x18, 0xc9, 0x2a, 0x59, 0x0b, 0xb4, 0x84, 0xb6, 0xa0, 0xca, 0x78, 0x48, 0x39, 0x1e, 0xc9, 0xff,
|
||||||
0x24, 0x4b, 0x88, 0xf4, 0x76, 0x6e, 0xe8, 0x3d, 0x77, 0x91, 0x65, 0x4c, 0x18, 0xa3, 0x4c, 0xb5,
|
0xef, 0x36, 0x85, 0xac, 0x30, 0x40, 0x5f, 0x41, 0x7d, 0x48, 0xc6, 0x59, 0x82, 0x85, 0xb5, 0x7d,
|
||||||
0xd0, 0x06, 0xd6, 0x82, 0xff, 0x5f, 0x05, 0x5a, 0x45, 0xb2, 0x4a, 0xe3, 0x61, 0x1b, 0x1c, 0x4d,
|
0x4b, 0xeb, 0xa9, 0x89, 0x48, 0x63, 0x4c, 0x29, 0xa1, 0xb2, 0x84, 0xd6, 0x03, 0x25, 0x78, 0xff,
|
||||||
0xbd, 0x2e, 0xd9, 0xbb, 0xa5, 0x4a, 0x23, 0x5c, 0x98, 0x2a, 0x17, 0x6a, 0xa3, 0x29, 0x53, 0xb3,
|
0x96, 0xa0, 0x69, 0x92, 0x35, 0xd7, 0x1e, 0x76, 0xc1, 0x56, 0xd4, 0xab, 0x94, 0xbd, 0x5f, 0xa8,
|
||||||
0x43, 0x4f, 0x94, 0x5c, 0x94, 0x01, 0x0b, 0x2a, 0xc2, 0x44, 0xa5, 0xca, 0xc6, 0x5a, 0x90, 0x23,
|
0x14, 0xc2, 0xc2, 0x50, 0x39, 0x50, 0x1d, 0xe6, 0x54, 0xf6, 0x0e, 0xd5, 0x51, 0x0a, 0x51, 0x38,
|
||||||
0x65, 0x36, 0x87, 0x6f, 0x37, 0x52, 0x66, 0x6e, 0x45, 0x1a, 0x6a, 0xaf, 0x45, 0x43, 0xfd, 0xd6,
|
0xcc, 0x09, 0x0f, 0x13, 0x19, 0xaa, 0x72, 0xa0, 0x04, 0xd1, 0x52, 0x26, 0x7d, 0xf9, 0x6e, 0x2d,
|
||||||
0x34, 0xf8, 0x7f, 0x5a, 0xd0, 0x98, 0x55, 0x79, 0x21, 0xbb, 0xd6, 0x6b, 0x67, 0x77, 0x21, 0x33,
|
0x65, 0x62, 0x66, 0xd2, 0x50, 0x7d, 0x23, 0x1a, 0x6a, 0x77, 0xa6, 0xc1, 0xfb, 0xdd, 0x82, 0xfa,
|
||||||
0x95, 0xbb, 0x65, 0xe6, 0x3e, 0x38, 0x5c, 0x30, 0x12, 0x4e, 0x14, 0x47, 0x36, 0x36, 0x92, 0xec,
|
0x24, 0xcb, 0x8d, 0xe8, 0x5a, 0x6f, 0x1c, 0xdd, 0x99, 0xc8, 0x94, 0xee, 0x17, 0x99, 0x07, 0x60,
|
||||||
0x27, 0x13, 0x1e, 0x29, 0x86, 0x5a, 0x58, 0x2e, 0x7d, 0x1f, 0x5a, 0xfd, 0x13, 0x41, 0xf8, 0x2e,
|
0x33, 0x4e, 0x71, 0x38, 0x96, 0x1c, 0x95, 0x03, 0x2d, 0x89, 0x7a, 0x32, 0x66, 0x91, 0x64, 0xa8,
|
||||||
0xe1, 0x72, 0x92, 0x4a, 0x6e, 0xc7, 0xa1, 0x08, 0xd5, 0x3d, 0x5a, 0x58, 0xad, 0xfd, 0x07, 0x80,
|
0x19, 0x88, 0xa5, 0xe7, 0x41, 0xb3, 0x77, 0xc6, 0x31, 0xdb, 0xc7, 0x4c, 0x74, 0x52, 0xc1, 0xed,
|
||||||
0x76, 0x62, 0x2e, 0x5e, 0x50, 0x76, 0x48, 0x18, 0xbf, 0xe8, 0xd1, 0x63, 0x17, 0x1e, 0x3d, 0xbb,
|
0x28, 0xe4, 0xa1, 0x7c, 0x47, 0x33, 0x90, 0x6b, 0xef, 0x21, 0xa0, 0xbd, 0x98, 0xf1, 0x97, 0x84,
|
||||||
0xf0, 0xd6, 0x82, 0xb5, 0xe9, 0x52, 0x9f, 0x9d, 0x7b, 0xf6, 0x5c, 0xd0, 0x6d, 0xb4, 0xcb, 0xb9,
|
0x1e, 0x63, 0xca, 0x16, 0x0d, 0x3d, 0x65, 0x63, 0xe8, 0xd9, 0x87, 0xb7, 0x66, 0xb4, 0x75, 0x95,
|
||||||
0x77, 0xcf, 0xaf, 0x16, 0xb4, 0x8a, 0x1b, 0xa5, 0xca, 0xee, 0x83, 0xb3, 0x13, 0x0e, 0x49, 0x92,
|
0xfa, 0xec, 0xd2, 0xd8, 0xb3, 0xa0, 0xda, 0x28, 0x93, 0x4b, 0x73, 0xcf, 0x2f, 0x16, 0x34, 0xcd,
|
||||||
0xb7, 0xb1, 0xb5, 0xab, 0x81, 0x03, 0x6d, 0xac, 0x07, 0x99, 0xf1, 0xf4, 0xbe, 0x80, 0x66, 0x41,
|
0x83, 0xb9, 0xcc, 0xee, 0x81, 0xbd, 0x17, 0x0e, 0x70, 0x52, 0x94, 0xb1, 0xf5, 0xeb, 0x81, 0x7d,
|
||||||
0x7d, 0x9b, 0xe1, 0xb1, 0xfe, 0x9b, 0x0d, 0xb5, 0x4d, 0xfd, 0x62, 0x45, 0xcf, 0xa1, 0x31, 0x7b,
|
0xa5, 0xac, 0x1a, 0x99, 0xb6, 0x74, 0xbf, 0x80, 0x86, 0xb1, 0x7d, 0x97, 0xe6, 0xb1, 0xf9, 0x4f,
|
||||||
0xef, 0x21, 0xbf, 0x1c, 0xc7, 0xf9, 0x87, 0xa3, 0xf7, 0xc1, 0x95, 0x36, 0x26, 0x73, 0xdf, 0xc0,
|
0x19, 0xaa, 0xdb, 0x6a, 0x82, 0x45, 0x2f, 0xa0, 0x3e, 0x99, 0xf7, 0x90, 0x37, 0xef, 0xc7, 0xe5,
|
||||||
0x92, 0x1a, 0x29, 0xa8, 0x7d, 0xf5, 0xa4, 0xf6, 0x56, 0x2f, 0xdd, 0x37, 0x48, 0xbb, 0xe0, 0x98,
|
0xc1, 0xd1, 0xfd, 0xe0, 0x5a, 0x1d, 0x1d, 0xb9, 0x6f, 0x60, 0x49, 0x4e, 0xa0, 0x68, 0x41, 0xc8,
|
||||||
0xf6, 0x70, 0x91, 0x69, 0x71, 0xf2, 0x78, 0x9d, 0xcb, 0x0d, 0x34, 0xd8, 0x23, 0x0b, 0xed, 0xce,
|
0xcc, 0xd1, 0xd4, 0xbd, 0x7e, 0x92, 0xdc, 0xb0, 0x04, 0x92, 0x6c, 0x4e, 0x8b, 0x90, 0xcc, 0x9e,
|
||||||
0x9e, 0x21, 0x17, 0x85, 0x56, 0x2c, 0x2b, 0xef, 0x9a, 0xfd, 0xae, 0xf5, 0xc8, 0x42, 0x3f, 0x40,
|
0xef, 0xae, 0x5d, 0x79, 0xae, 0x7d, 0xda, 0x07, 0x5b, 0x17, 0x9a, 0x45, 0xaa, 0x66, 0x0f, 0x73,
|
||||||
0xb3, 0x50, 0x38, 0xe8, 0xc3, 0xb2, 0x4b, 0xb9, 0x0a, 0xbd, 0x8f, 0xae, 0xb1, 0xd2, 0xc1, 0xf6,
|
0xdb, 0x57, 0x2b, 0x28, 0xb0, 0x0d, 0x0b, 0xed, 0x4f, 0x06, 0x9a, 0x45, 0xae, 0x99, 0x09, 0xea,
|
||||||
0x5b, 0xaf, 0xce, 0xda, 0xd6, 0x5f, 0x67, 0x6d, 0xeb, 0xdf, 0xb3, 0xb6, 0x35, 0x74, 0xd4, 0x7f,
|
0xde, 0x70, 0xde, 0xb1, 0x36, 0x2c, 0xf4, 0x3d, 0x34, 0x8c, 0x14, 0x44, 0x1f, 0xce, 0x9b, 0xcc,
|
||||||
0xf4, 0xf1, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0x54, 0x2e, 0xae, 0xbd, 0x6b, 0x0c, 0x00, 0x00,
|
0xe7, 0xb3, 0xfb, 0xd1, 0x0d, 0x5a, 0xca, 0xd9, 0x5e, 0xf3, 0xf5, 0x45, 0xcb, 0xfa, 0xe3, 0xa2,
|
||||||
|
0x65, 0xfd, 0x7d, 0xd1, 0xb2, 0x06, 0xb6, 0xfc, 0x23, 0x3f, 0xfe, 0x2f, 0x00, 0x00, 0xff, 0xff,
|
||||||
|
0x67, 0x51, 0xef, 0xa3, 0xc5, 0x0c, 0x00, 0x00,
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,12 +12,17 @@ option (gogoproto.unmarshaler_all) = true;
|
||||||
|
|
||||||
service Control {
|
service Control {
|
||||||
rpc DiskUsage(DiskUsageRequest) returns (DiskUsageResponse);
|
rpc DiskUsage(DiskUsageRequest) returns (DiskUsageResponse);
|
||||||
|
rpc Prune(PruneRequest) returns (stream UsageRecord);
|
||||||
rpc Solve(SolveRequest) returns (SolveResponse);
|
rpc Solve(SolveRequest) returns (SolveResponse);
|
||||||
rpc Status(StatusRequest) returns (stream StatusResponse);
|
rpc Status(StatusRequest) returns (stream StatusResponse);
|
||||||
rpc Session(stream BytesMessage) returns (stream BytesMessage);
|
rpc Session(stream BytesMessage) returns (stream BytesMessage);
|
||||||
rpc ListWorkers(ListWorkersRequest) returns (ListWorkersResponse);
|
rpc ListWorkers(ListWorkersRequest) returns (ListWorkersResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message PruneRequest {
|
||||||
|
// TODO: filter
|
||||||
|
}
|
||||||
|
|
||||||
message DiskUsageRequest {
|
message DiskUsageRequest {
|
||||||
string filter = 1; // FIXME: this should be containerd-compatible repeated string?
|
string filter = 1; // FIXME: this should be containerd-compatible repeated string?
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package blobs
|
package blobs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
gocontext "context"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
|
@ -26,19 +25,10 @@ type DiffPair struct {
|
||||||
Blobsum digest.Digest
|
Blobsum digest.Digest
|
||||||
}
|
}
|
||||||
|
|
||||||
type blobmapper interface {
|
|
||||||
GetBlob(ctx gocontext.Context, key string) (digest.Digest, digest.Digest, error)
|
|
||||||
SetBlob(ctx gocontext.Context, key string, diffID, blob digest.Digest) error
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetDiffPairs(ctx context.Context, contentStore content.Store, snapshotter snapshot.Snapshotter, differ diff.Differ, ref cache.ImmutableRef) ([]DiffPair, error) {
|
func GetDiffPairs(ctx context.Context, contentStore content.Store, snapshotter snapshot.Snapshotter, differ diff.Differ, ref cache.ImmutableRef) ([]DiffPair, error) {
|
||||||
if ref == nil {
|
if ref == nil {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
blobmap, ok := snapshotter.(blobmapper)
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.Errorf("image exporter requires snapshotter with blobs mapping support")
|
|
||||||
}
|
|
||||||
|
|
||||||
eg, ctx := errgroup.WithContext(ctx)
|
eg, ctx := errgroup.WithContext(ctx)
|
||||||
var diffPairs []DiffPair
|
var diffPairs []DiffPair
|
||||||
|
@ -57,7 +47,7 @@ func GetDiffPairs(ctx context.Context, contentStore content.Store, snapshotter s
|
||||||
}
|
}
|
||||||
eg.Go(func() error {
|
eg.Go(func() error {
|
||||||
dp, err := g.Do(ctx, ref.ID(), func(ctx context.Context) (interface{}, error) {
|
dp, err := g.Do(ctx, ref.ID(), func(ctx context.Context) (interface{}, error) {
|
||||||
diffID, blob, err := blobmap.GetBlob(ctx, ref.ID())
|
diffID, blob, err := snapshotter.GetBlob(ctx, ref.ID())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -100,7 +90,7 @@ func GetDiffPairs(ctx context.Context, contentStore content.Store, snapshotter s
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if err := blobmap.SetBlob(ctx, ref.ID(), diffIDDigest, descr.Digest); err != nil {
|
if err := snapshotter.SetBlob(ctx, ref.ID(), diffIDDigest, descr.Digest); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return DiffPair{DiffID: diffIDDigest, Blobsum: descr.Digest}, nil
|
return DiffPair{DiffID: diffIDDigest, Blobsum: descr.Digest}, nil
|
||||||
|
|
|
@ -2,7 +2,6 @@ package cacheimport
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
gocontext "context"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -25,11 +24,6 @@ import (
|
||||||
|
|
||||||
const mediaTypeConfig = "application/vnd.buildkit.cacheconfig.v0"
|
const mediaTypeConfig = "application/vnd.buildkit.cacheconfig.v0"
|
||||||
|
|
||||||
type blobmapper interface {
|
|
||||||
GetBlob(ctx gocontext.Context, key string) (digest.Digest, digest.Digest, error)
|
|
||||||
SetBlob(ctx gocontext.Context, key string, diffID, blob digest.Digest) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type CacheRecord struct {
|
type CacheRecord struct {
|
||||||
CacheKey digest.Digest
|
CacheKey digest.Digest
|
||||||
Reference cache.ImmutableRef
|
Reference cache.ImmutableRef
|
||||||
|
|
|
@ -269,7 +269,6 @@ func (ii *importInfo) unpack(ctx context.Context, dpairs []blobs.DiffPair) (stri
|
||||||
var chain []digest.Digest
|
var chain []digest.Digest
|
||||||
for _, layer := range layers {
|
for _, layer := range layers {
|
||||||
labels := map[string]string{
|
labels := map[string]string{
|
||||||
"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339Nano),
|
|
||||||
"containerd.io/uncompressed": layer.Diff.Digest.String(),
|
"containerd.io/uncompressed": layer.Diff.Digest.String(),
|
||||||
}
|
}
|
||||||
if _, err := rootfs.ApplyLayer(ctx, layer, chain, ii.opt.Snapshotter, ii.opt.Applier, cdsnapshot.WithLabels(labels)); err != nil {
|
if _, err := rootfs.ApplyLayer(ctx, layer, chain, ii.opt.Snapshotter, ii.opt.Applier, cdsnapshot.WithLabels(labels)); err != nil {
|
||||||
|
@ -291,7 +290,7 @@ func (ii *importInfo) fillBlobMapping(ctx context.Context, layers []rootfs.Layer
|
||||||
for _, l := range layers {
|
for _, l := range layers {
|
||||||
chain = append(chain, l.Diff.Digest)
|
chain = append(chain, l.Diff.Digest)
|
||||||
chainID := identity.ChainID(chain)
|
chainID := identity.ChainID(chain)
|
||||||
if err := ii.opt.Snapshotter.(blobmapper).SetBlob(ctx, string(chainID), l.Diff.Digest, l.Blob.Digest); err != nil {
|
if err := ii.opt.Snapshotter.SetBlob(ctx, string(chainID), l.Diff.Digest, l.Blob.Digest); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/snapshots"
|
||||||
"github.com/containerd/containerd/snapshots/naive"
|
"github.com/containerd/containerd/snapshots/naive"
|
||||||
"github.com/moby/buildkit/cache"
|
"github.com/moby/buildkit/cache"
|
||||||
"github.com/moby/buildkit/cache/metadata"
|
"github.com/moby/buildkit/cache/metadata"
|
||||||
|
@ -383,7 +384,7 @@ func createRef(t *testing.T, cm cache.Manager, files []string) cache.ImmutableRe
|
||||||
return ref
|
return ref
|
||||||
}
|
}
|
||||||
|
|
||||||
func setupCacheManager(t *testing.T, tmpdir string, snapshotter snapshot.Snapshotter) cache.Manager {
|
func setupCacheManager(t *testing.T, tmpdir string, snapshotter snapshots.Snapshotter) cache.Manager {
|
||||||
md, err := metadata.NewStore(filepath.Join(tmpdir, "metadata.db"))
|
md, err := metadata.NewStore(filepath.Join(tmpdir, "metadata.db"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
|
|
@ -22,10 +22,6 @@ type GCPolicy struct {
|
||||||
// return CachePolicy{Priority: 10, LastUsed: time.Now()}
|
// return CachePolicy{Priority: 10, LastUsed: time.Now()}
|
||||||
// }
|
// }
|
||||||
|
|
||||||
func (cm *cacheManager) Prune(ctx context.Context) (map[string]int64, error) {
|
|
||||||
return nil, errors.New("Prune not implemented")
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cm *cacheManager) GC(ctx context.Context) error {
|
func (cm *cacheManager) GC(ctx context.Context) error {
|
||||||
return errors.New("GC not implemented")
|
return errors.New("GC not implemented")
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,11 +6,10 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
cdsnapshot "github.com/containerd/containerd/snapshots"
|
"github.com/containerd/containerd/snapshots"
|
||||||
"github.com/moby/buildkit/cache/metadata"
|
"github.com/moby/buildkit/cache/metadata"
|
||||||
"github.com/moby/buildkit/client"
|
"github.com/moby/buildkit/client"
|
||||||
"github.com/moby/buildkit/identity"
|
"github.com/moby/buildkit/identity"
|
||||||
"github.com/moby/buildkit/snapshot"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"golang.org/x/sync/errgroup"
|
"golang.org/x/sync/errgroup"
|
||||||
|
@ -23,7 +22,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
type ManagerOpt struct {
|
type ManagerOpt struct {
|
||||||
Snapshotter snapshot.Snapshotter
|
Snapshotter snapshots.Snapshotter
|
||||||
GCPolicy GCPolicy
|
GCPolicy GCPolicy
|
||||||
MetadataStore *metadata.Store
|
MetadataStore *metadata.Store
|
||||||
}
|
}
|
||||||
|
@ -36,7 +35,7 @@ type Accessor interface {
|
||||||
|
|
||||||
type Controller interface {
|
type Controller interface {
|
||||||
DiskUsage(ctx context.Context, info client.DiskUsageInfo) ([]*client.UsageInfo, error)
|
DiskUsage(ctx context.Context, info client.DiskUsageInfo) ([]*client.UsageInfo, error)
|
||||||
Prune(ctx context.Context) (map[string]int64, error)
|
Prune(ctx context.Context, ch chan client.UsageInfo) error
|
||||||
GC(ctx context.Context) error
|
GC(ctx context.Context) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,6 +50,8 @@ type cacheManager struct {
|
||||||
mu sync.Mutex
|
mu sync.Mutex
|
||||||
ManagerOpt
|
ManagerOpt
|
||||||
md *metadata.Store
|
md *metadata.Store
|
||||||
|
|
||||||
|
muPrune sync.Mutex // make sure parallel prune is not allowed so there will not be inconsistent results
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewManager(opt ManagerOpt) (Manager, error) {
|
func NewManager(opt ManagerOpt) (Manager, error) {
|
||||||
|
@ -69,6 +70,8 @@ func NewManager(opt ManagerOpt) (Manager, error) {
|
||||||
return cm, nil
|
return cm, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// init loads all snapshots from metadata state and tries to load the records
|
||||||
|
// from the snapshotter. If snaphot can't be found, metadata is deleted as well.
|
||||||
func (cm *cacheManager) init(ctx context.Context) error {
|
func (cm *cacheManager) init(ctx context.Context) error {
|
||||||
items, err := cm.md.All()
|
items, err := cm.md.All()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -76,27 +79,32 @@ func (cm *cacheManager) init(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, si := range items {
|
for _, si := range items {
|
||||||
if _, err := cm.load(ctx, si.ID()); err != nil {
|
if _, err := cm.getRecord(ctx, si.ID()); err != nil {
|
||||||
logrus.Debugf("could not load snapshot %s, %v", si.ID(), err)
|
logrus.Debugf("could not load snapshot %s: %v", si.ID(), err)
|
||||||
cm.md.Clear(si.ID())
|
cm.md.Clear(si.ID())
|
||||||
|
// TODO: make sure content is deleted as well
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Close closes the manager and releases the metadata database lock. No other
|
||||||
|
// method should be called after Close.
|
||||||
func (cm *cacheManager) Close() error {
|
func (cm *cacheManager) Close() error {
|
||||||
// TODO: allocate internal context and cancel it here
|
// TODO: allocate internal context and cancel it here
|
||||||
return cm.md.Close()
|
return cm.md.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get returns an immutable snapshot reference for ID
|
||||||
func (cm *cacheManager) Get(ctx context.Context, id string, opts ...RefOption) (ImmutableRef, error) {
|
func (cm *cacheManager) Get(ctx context.Context, id string, opts ...RefOption) (ImmutableRef, error) {
|
||||||
cm.mu.Lock()
|
cm.mu.Lock()
|
||||||
defer cm.mu.Unlock()
|
defer cm.mu.Unlock()
|
||||||
return cm.get(ctx, id, opts...)
|
return cm.get(ctx, id, opts...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// get requires manager lock to be taken
|
||||||
func (cm *cacheManager) get(ctx context.Context, id string, opts ...RefOption) (ImmutableRef, error) {
|
func (cm *cacheManager) get(ctx context.Context, id string, opts ...RefOption) (ImmutableRef, error) {
|
||||||
rec, err := cm.load(ctx, id, opts...)
|
rec, err := cm.getRecord(ctx, id, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -104,7 +112,7 @@ func (cm *cacheManager) get(ctx context.Context, id string, opts ...RefOption) (
|
||||||
defer rec.mu.Unlock()
|
defer rec.mu.Unlock()
|
||||||
|
|
||||||
if rec.mutable {
|
if rec.mutable {
|
||||||
if rec.dead || len(rec.refs) != 0 {
|
if len(rec.refs) != 0 {
|
||||||
return nil, errors.Wrapf(errLocked, "%s is locked", id)
|
return nil, errors.Wrapf(errLocked, "%s is locked", id)
|
||||||
}
|
}
|
||||||
if rec.equalImmutable != nil {
|
if rec.equalImmutable != nil {
|
||||||
|
@ -116,21 +124,30 @@ func (cm *cacheManager) get(ctx context.Context, id string, opts ...RefOption) (
|
||||||
return rec.ref(), nil
|
return rec.ref(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cm *cacheManager) load(ctx context.Context, id string, opts ...RefOption) (*cacheRecord, error) {
|
// getRecord returns record for id. Requires manager lock.
|
||||||
if rec, ok := cm.records[id]; ok && !rec.dead {
|
func (cm *cacheManager) getRecord(ctx context.Context, id string, opts ...RefOption) (cr *cacheRecord, retErr error) {
|
||||||
|
if rec, ok := cm.records[id]; ok {
|
||||||
|
if rec.isDead() {
|
||||||
|
return nil, errNotFound
|
||||||
|
}
|
||||||
return rec, nil
|
return rec, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
md, _ := cm.md.Get(id)
|
md, _ := cm.md.Get(id)
|
||||||
if mutableID := getEqualMutable(md); mutableID != "" {
|
if mutableID := getEqualMutable(md); mutableID != "" {
|
||||||
mutable, err := cm.load(ctx, mutableID)
|
mutable, err := cm.getRecord(ctx, mutableID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// check loading mutable deleted record from disk
|
||||||
|
if errors.Cause(err) == errNotFound {
|
||||||
|
cm.md.Clear(id)
|
||||||
|
}
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
rec := &cacheRecord{
|
rec := &cacheRecord{
|
||||||
|
mu: &sync.Mutex{},
|
||||||
cm: cm,
|
cm: cm,
|
||||||
refs: make(map[Mountable]struct{}),
|
refs: make(map[Mountable]struct{}),
|
||||||
parent: mutable.parent,
|
parent: mutable.Parent(),
|
||||||
md: md,
|
md: md,
|
||||||
equalMutable: &mutableRef{cacheRecord: mutable},
|
equalMutable: &mutableRef{cacheRecord: mutable},
|
||||||
}
|
}
|
||||||
|
@ -150,16 +167,30 @@ func (cm *cacheManager) load(ctx context.Context, id string, opts ...RefOption)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
if retErr != nil {
|
||||||
|
parent.Release(context.TODO())
|
||||||
|
}
|
||||||
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
rec := &cacheRecord{
|
rec := &cacheRecord{
|
||||||
mutable: info.Kind != cdsnapshot.KindCommitted,
|
mu: &sync.Mutex{},
|
||||||
|
mutable: info.Kind != snapshots.KindCommitted,
|
||||||
cm: cm,
|
cm: cm,
|
||||||
refs: make(map[Mountable]struct{}),
|
refs: make(map[Mountable]struct{}),
|
||||||
parent: parent,
|
parent: parent,
|
||||||
md: md,
|
md: md,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// the record was deleted but we crashed before data on disk was removed
|
||||||
|
if getDeleted(md) {
|
||||||
|
if err := rec.remove(ctx, true); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return nil, errNotFound
|
||||||
|
}
|
||||||
|
|
||||||
if err := initializeMetadata(rec, opts...); err != nil {
|
if err := initializeMetadata(rec, opts...); err != nil {
|
||||||
if parent != nil {
|
if parent != nil {
|
||||||
parent.Release(context.TODO())
|
parent.Release(context.TODO())
|
||||||
|
@ -188,10 +219,7 @@ func (cm *cacheManager) New(ctx context.Context, s ImmutableRef, opts ...RefOpti
|
||||||
parentID = parent.ID()
|
parentID = parent.ID()
|
||||||
}
|
}
|
||||||
|
|
||||||
labels := map[string]string{
|
if _, err := cm.Snapshotter.Prepare(ctx, id, parentID); err != nil {
|
||||||
"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339Nano),
|
|
||||||
}
|
|
||||||
if _, err := cm.Snapshotter.Prepare(ctx, id, parentID, cdsnapshot.WithLabels(labels)); err != nil {
|
|
||||||
if parent != nil {
|
if parent != nil {
|
||||||
parent.Release(context.TODO())
|
parent.Release(context.TODO())
|
||||||
}
|
}
|
||||||
|
@ -201,6 +229,7 @@ func (cm *cacheManager) New(ctx context.Context, s ImmutableRef, opts ...RefOpti
|
||||||
md, _ := cm.md.Get(id)
|
md, _ := cm.md.Get(id)
|
||||||
|
|
||||||
rec := &cacheRecord{
|
rec := &cacheRecord{
|
||||||
|
mu: &sync.Mutex{},
|
||||||
mutable: true,
|
mutable: true,
|
||||||
cm: cm,
|
cm: cm,
|
||||||
refs: make(map[Mountable]struct{}),
|
refs: make(map[Mountable]struct{}),
|
||||||
|
@ -226,7 +255,7 @@ func (cm *cacheManager) GetMutable(ctx context.Context, id string) (MutableRef,
|
||||||
cm.mu.Lock()
|
cm.mu.Lock()
|
||||||
defer cm.mu.Unlock()
|
defer cm.mu.Unlock()
|
||||||
|
|
||||||
rec, err := cm.load(ctx, id)
|
rec, err := cm.getRecord(ctx, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -255,6 +284,107 @@ func (cm *cacheManager) GetMutable(ctx context.Context, id string) (MutableRef,
|
||||||
return rec.mref(), nil
|
return rec.mref(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (cm *cacheManager) Prune(ctx context.Context, ch chan client.UsageInfo) error {
|
||||||
|
cm.muPrune.Lock()
|
||||||
|
defer cm.muPrune.Unlock()
|
||||||
|
return cm.prune(ctx, ch)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cm *cacheManager) prune(ctx context.Context, ch chan client.UsageInfo) error {
|
||||||
|
var toDelete []*cacheRecord
|
||||||
|
cm.mu.Lock()
|
||||||
|
|
||||||
|
for _, cr := range cm.records {
|
||||||
|
cr.mu.Lock()
|
||||||
|
|
||||||
|
// ignore duplicates that share data
|
||||||
|
if cr.equalImmutable != nil && len(cr.equalImmutable.refs) > 0 || cr.equalMutable != nil && len(cr.refs) == 0 {
|
||||||
|
cr.mu.Unlock()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if cr.isDead() {
|
||||||
|
cr.mu.Unlock()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(cr.refs) == 0 {
|
||||||
|
cr.dead = true
|
||||||
|
toDelete = append(toDelete, cr)
|
||||||
|
}
|
||||||
|
|
||||||
|
// mark metadata as deleted in case we crash before cleanup finished
|
||||||
|
if err := setDeleted(cr.md); err != nil {
|
||||||
|
cr.mu.Unlock()
|
||||||
|
cm.mu.Unlock()
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
cr.mu.Unlock()
|
||||||
|
}
|
||||||
|
|
||||||
|
cm.mu.Unlock()
|
||||||
|
|
||||||
|
if len(toDelete) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
for _, cr := range toDelete {
|
||||||
|
cr.mu.Lock()
|
||||||
|
|
||||||
|
usageCount, lastUsedAt := getLastUsed(cr.md)
|
||||||
|
|
||||||
|
c := client.UsageInfo{
|
||||||
|
ID: cr.ID(),
|
||||||
|
Mutable: cr.mutable,
|
||||||
|
InUse: len(cr.refs) > 0,
|
||||||
|
Size: getSize(cr.md),
|
||||||
|
CreatedAt: getCreatedAt(cr.md),
|
||||||
|
Description: GetDescription(cr.md),
|
||||||
|
LastUsedAt: lastUsedAt,
|
||||||
|
UsageCount: usageCount,
|
||||||
|
}
|
||||||
|
|
||||||
|
if cr.parent != nil {
|
||||||
|
c.Parent = cr.parent.ID()
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.Size == sizeUnknown {
|
||||||
|
cr.mu.Unlock() // all the non-prune modifications already protected by cr.dead
|
||||||
|
s, err := cr.Size(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
c.Size = s
|
||||||
|
cr.mu.Lock()
|
||||||
|
}
|
||||||
|
|
||||||
|
if cr.equalImmutable != nil {
|
||||||
|
if err1 := cr.equalImmutable.remove(ctx, false); err == nil {
|
||||||
|
err = err1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err1 := cr.remove(ctx, true); err == nil {
|
||||||
|
err = err1
|
||||||
|
}
|
||||||
|
|
||||||
|
if err == nil && ch != nil {
|
||||||
|
ch <- c
|
||||||
|
}
|
||||||
|
cr.mu.Unlock()
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return ctx.Err()
|
||||||
|
default:
|
||||||
|
return cm.prune(ctx, ch)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (cm *cacheManager) DiskUsage(ctx context.Context, opt client.DiskUsageInfo) ([]*client.UsageInfo, error) {
|
func (cm *cacheManager) DiskUsage(ctx context.Context, opt client.DiskUsageInfo) ([]*client.UsageInfo, error) {
|
||||||
cm.mu.Lock()
|
cm.mu.Lock()
|
||||||
|
|
||||||
|
@ -267,6 +397,7 @@ func (cm *cacheManager) DiskUsage(ctx context.Context, opt client.DiskUsageInfo)
|
||||||
usageCount int
|
usageCount int
|
||||||
lastUsedAt *time.Time
|
lastUsedAt *time.Time
|
||||||
description string
|
description string
|
||||||
|
doubleRef bool
|
||||||
}
|
}
|
||||||
|
|
||||||
m := make(map[string]*cacheUsageInfo, len(cm.records))
|
m := make(map[string]*cacheUsageInfo, len(cm.records))
|
||||||
|
@ -289,6 +420,7 @@ func (cm *cacheManager) DiskUsage(ctx context.Context, opt client.DiskUsageInfo)
|
||||||
usageCount: usageCount,
|
usageCount: usageCount,
|
||||||
lastUsedAt: lastUsedAt,
|
lastUsedAt: lastUsedAt,
|
||||||
description: GetDescription(cr.md),
|
description: GetDescription(cr.md),
|
||||||
|
doubleRef: cr.equalImmutable != nil,
|
||||||
}
|
}
|
||||||
if cr.parent != nil {
|
if cr.parent != nil {
|
||||||
c.parent = cr.parent.ID()
|
c.parent = cr.parent.ID()
|
||||||
|
@ -310,6 +442,9 @@ func (cm *cacheManager) DiskUsage(ctx context.Context, opt client.DiskUsageInfo)
|
||||||
v := m[id]
|
v := m[id]
|
||||||
if v.refs == 0 && v.parent != "" {
|
if v.refs == 0 && v.parent != "" {
|
||||||
m[v.parent].refs--
|
m[v.parent].refs--
|
||||||
|
if v.doubleRef {
|
||||||
|
m[v.parent].refs--
|
||||||
|
}
|
||||||
rescan[v.parent] = struct{}{}
|
rescan[v.parent] = struct{}{}
|
||||||
}
|
}
|
||||||
delete(rescan, id)
|
delete(rescan, id)
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
|
"github.com/containerd/containerd/snapshots"
|
||||||
"github.com/containerd/containerd/snapshots/naive"
|
"github.com/containerd/containerd/snapshots/naive"
|
||||||
"github.com/moby/buildkit/cache/metadata"
|
"github.com/moby/buildkit/cache/metadata"
|
||||||
"github.com/moby/buildkit/client"
|
"github.com/moby/buildkit/client"
|
||||||
|
@ -124,8 +125,119 @@ func TestManager(t *testing.T) {
|
||||||
|
|
||||||
checkDiskUsage(ctx, t, cm, 0, 2)
|
checkDiskUsage(ctx, t, cm, 0, 2)
|
||||||
|
|
||||||
|
buf := pruneResultBuffer()
|
||||||
|
err = cm.Prune(ctx, buf.C)
|
||||||
|
buf.close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
checkDiskUsage(ctx, t, cm, 0, 0)
|
||||||
|
|
||||||
|
require.Equal(t, len(buf.all), 2)
|
||||||
|
|
||||||
err = cm.Close()
|
err = cm.Close()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
dirs, err := ioutil.ReadDir(filepath.Join(tmpdir, "snapshots/snapshots"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 0, len(dirs))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPrune(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
ctx := namespaces.WithNamespace(context.Background(), "buildkit-test")
|
||||||
|
|
||||||
|
tmpdir, err := ioutil.TempDir("", "cachemanager")
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer os.RemoveAll(tmpdir)
|
||||||
|
|
||||||
|
snapshotter, err := naive.NewSnapshotter(filepath.Join(tmpdir, "snapshots"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
cm := getCacheManager(t, tmpdir, snapshotter)
|
||||||
|
|
||||||
|
active, err := cm.New(ctx, nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
snap, err := active.Commit(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
active, err = cm.New(ctx, snap, CachePolicyRetain)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
snap2, err := active.Commit(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
checkDiskUsage(ctx, t, cm, 2, 0)
|
||||||
|
|
||||||
|
// prune with keeping refs does nothing
|
||||||
|
buf := pruneResultBuffer()
|
||||||
|
err = cm.Prune(ctx, buf.C)
|
||||||
|
buf.close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
checkDiskUsage(ctx, t, cm, 2, 0)
|
||||||
|
require.Equal(t, len(buf.all), 0)
|
||||||
|
|
||||||
|
dirs, err := ioutil.ReadDir(filepath.Join(tmpdir, "snapshots/snapshots"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 2, len(dirs))
|
||||||
|
|
||||||
|
err = snap2.Release(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
checkDiskUsage(ctx, t, cm, 1, 1)
|
||||||
|
|
||||||
|
// prune with keeping single refs deletes one
|
||||||
|
buf = pruneResultBuffer()
|
||||||
|
err = cm.Prune(ctx, buf.C)
|
||||||
|
buf.close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
checkDiskUsage(ctx, t, cm, 1, 0)
|
||||||
|
require.Equal(t, len(buf.all), 1)
|
||||||
|
|
||||||
|
dirs, err = ioutil.ReadDir(filepath.Join(tmpdir, "snapshots/snapshots"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 1, len(dirs))
|
||||||
|
|
||||||
|
err = snap.Release(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
active, err = cm.New(ctx, snap, CachePolicyRetain)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
snap2, err = active.Commit(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
err = snap.Release(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
checkDiskUsage(ctx, t, cm, 2, 0)
|
||||||
|
|
||||||
|
// prune with parent released does nothing
|
||||||
|
buf = pruneResultBuffer()
|
||||||
|
err = cm.Prune(ctx, buf.C)
|
||||||
|
buf.close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
checkDiskUsage(ctx, t, cm, 2, 0)
|
||||||
|
require.Equal(t, len(buf.all), 0)
|
||||||
|
|
||||||
|
// releasing last reference
|
||||||
|
err = snap2.Release(ctx)
|
||||||
|
require.NoError(t, err)
|
||||||
|
checkDiskUsage(ctx, t, cm, 0, 2)
|
||||||
|
|
||||||
|
buf = pruneResultBuffer()
|
||||||
|
err = cm.Prune(ctx, buf.C)
|
||||||
|
buf.close()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
checkDiskUsage(ctx, t, cm, 0, 0)
|
||||||
|
require.Equal(t, len(buf.all), 2)
|
||||||
|
|
||||||
|
dirs, err = ioutil.ReadDir(filepath.Join(tmpdir, "snapshots/snapshots"))
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 0, len(dirs))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestLazyCommit(t *testing.T) {
|
func TestLazyCommit(t *testing.T) {
|
||||||
|
@ -257,7 +369,7 @@ func TestLazyCommit(t *testing.T) {
|
||||||
require.Equal(t, errNotFound, errors.Cause(err))
|
require.Equal(t, errNotFound, errors.Cause(err))
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCacheManager(t *testing.T, tmpdir string, snapshotter snapshot.Snapshotter) Manager {
|
func getCacheManager(t *testing.T, tmpdir string, snapshotter snapshots.Snapshotter) Manager {
|
||||||
md, err := metadata.NewStore(filepath.Join(tmpdir, "metadata.db"))
|
md, err := metadata.NewStore(filepath.Join(tmpdir, "metadata.db"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -283,3 +395,25 @@ func checkDiskUsage(ctx context.Context, t *testing.T, cm Manager, inuse, unused
|
||||||
require.Equal(t, inuse, inuseActual)
|
require.Equal(t, inuse, inuseActual)
|
||||||
require.Equal(t, unused, unusedActual)
|
require.Equal(t, unused, unusedActual)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pruneResultBuffer() *buf {
|
||||||
|
b := &buf{C: make(chan client.UsageInfo), closed: make(chan struct{})}
|
||||||
|
go func() {
|
||||||
|
for c := range b.C {
|
||||||
|
b.all = append(b.all, c)
|
||||||
|
}
|
||||||
|
close(b.closed)
|
||||||
|
}()
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
|
type buf struct {
|
||||||
|
C chan client.UsageInfo
|
||||||
|
closed chan struct{}
|
||||||
|
all []client.UsageInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *buf) close() {
|
||||||
|
close(b.C)
|
||||||
|
<-b.closed
|
||||||
|
}
|
||||||
|
|
|
@ -8,13 +8,6 @@ import (
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Fields to be added:
|
|
||||||
// Size int64
|
|
||||||
// AccessTime int64
|
|
||||||
// Tags
|
|
||||||
// Descr
|
|
||||||
// CachePolicy
|
|
||||||
|
|
||||||
const sizeUnknown int64 = -1
|
const sizeUnknown int64 = -1
|
||||||
const keySize = "snapshot.size"
|
const keySize = "snapshot.size"
|
||||||
const keyEqualMutable = "cache.equalMutable"
|
const keyEqualMutable = "cache.equalMutable"
|
||||||
|
@ -24,6 +17,31 @@ const keyCreatedAt = "cache.createdAt"
|
||||||
const keyLastUsedAt = "cache.lastUsedAt"
|
const keyLastUsedAt = "cache.lastUsedAt"
|
||||||
const keyUsageCount = "cache.usageCount"
|
const keyUsageCount = "cache.usageCount"
|
||||||
|
|
||||||
|
const keyDeleted = "cache.deleted"
|
||||||
|
|
||||||
|
func setDeleted(si *metadata.StorageItem) error {
|
||||||
|
v, err := metadata.NewValue(true)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to create size value")
|
||||||
|
}
|
||||||
|
si.Update(func(b *bolt.Bucket) error {
|
||||||
|
return si.SetValue(b, keyDeleted, v)
|
||||||
|
})
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDeleted(si *metadata.StorageItem) bool {
|
||||||
|
v := si.Get(keyDeleted)
|
||||||
|
if v == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
var deleted bool
|
||||||
|
if err := v.Unmarshal(&deleted); err != nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return deleted
|
||||||
|
}
|
||||||
|
|
||||||
func setSize(si *metadata.StorageItem, s int64) error {
|
func setSize(si *metadata.StorageItem, s int64) error {
|
||||||
v, err := metadata.NewValue(s)
|
v, err := metadata.NewValue(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -2,10 +2,8 @@ package cache
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/containerd/containerd/mount"
|
"github.com/containerd/containerd/mount"
|
||||||
cdsnapshot "github.com/containerd/containerd/snapshots"
|
|
||||||
"github.com/moby/buildkit/cache/metadata"
|
"github.com/moby/buildkit/cache/metadata"
|
||||||
"github.com/moby/buildkit/identity"
|
"github.com/moby/buildkit/identity"
|
||||||
"github.com/moby/buildkit/util/flightcontrol"
|
"github.com/moby/buildkit/util/flightcontrol"
|
||||||
|
@ -27,7 +25,6 @@ type ImmutableRef interface {
|
||||||
Ref
|
Ref
|
||||||
Parent() ImmutableRef
|
Parent() ImmutableRef
|
||||||
Finalize(ctx context.Context) error // Make sure reference is flushed to driver
|
Finalize(ctx context.Context) error // Make sure reference is flushed to driver
|
||||||
// Prepare() / ChainID() / Meta()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type MutableRef interface {
|
type MutableRef interface {
|
||||||
|
@ -40,38 +37,46 @@ type Mountable interface {
|
||||||
}
|
}
|
||||||
|
|
||||||
type cacheRecord struct {
|
type cacheRecord struct {
|
||||||
mu sync.Mutex
|
cm *cacheManager
|
||||||
|
mu *sync.Mutex // the mutex is shared by records sharing data
|
||||||
|
|
||||||
mutable bool
|
mutable bool
|
||||||
refs map[Mountable]struct{}
|
refs map[Mountable]struct{}
|
||||||
cm *cacheManager
|
|
||||||
parent ImmutableRef
|
parent ImmutableRef
|
||||||
md *metadata.StorageItem
|
md *metadata.StorageItem
|
||||||
view string
|
|
||||||
viewMount []mount.Mount
|
// dead means record is marked as deleted
|
||||||
dead bool
|
dead bool
|
||||||
|
|
||||||
|
view string
|
||||||
|
viewMount []mount.Mount
|
||||||
|
|
||||||
sizeG flightcontrol.Group
|
sizeG flightcontrol.Group
|
||||||
// size int64
|
|
||||||
|
|
||||||
// these are filled if multiple refs point to same data
|
// these are filled if multiple refs point to same data
|
||||||
equalMutable *mutableRef
|
equalMutable *mutableRef
|
||||||
equalImmutable *immutableRef
|
equalImmutable *immutableRef
|
||||||
}
|
}
|
||||||
|
|
||||||
// hold manager lock before calling
|
// hold ref lock before calling
|
||||||
func (cr *cacheRecord) ref() *immutableRef {
|
func (cr *cacheRecord) ref() *immutableRef {
|
||||||
ref := &immutableRef{cacheRecord: cr}
|
ref := &immutableRef{cacheRecord: cr}
|
||||||
cr.refs[ref] = struct{}{}
|
cr.refs[ref] = struct{}{}
|
||||||
return ref
|
return ref
|
||||||
}
|
}
|
||||||
|
|
||||||
// hold manager lock before calling
|
// hold ref lock before calling
|
||||||
func (cr *cacheRecord) mref() *mutableRef {
|
func (cr *cacheRecord) mref() *mutableRef {
|
||||||
ref := &mutableRef{cacheRecord: cr}
|
ref := &mutableRef{cacheRecord: cr}
|
||||||
cr.refs[ref] = struct{}{}
|
cr.refs[ref] = struct{}{}
|
||||||
return ref
|
return ref
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hold ref lock before calling
|
||||||
|
func (cr *cacheRecord) isDead() bool {
|
||||||
|
return cr.dead || (cr.equalImmutable != nil && cr.equalImmutable.dead) || (cr.equalMutable != nil && cr.equalMutable.dead)
|
||||||
|
}
|
||||||
|
|
||||||
func (cr *cacheRecord) Size(ctx context.Context) (int64, error) {
|
func (cr *cacheRecord) Size(ctx context.Context) (int64, error) {
|
||||||
// this expects that usage() is implemented lazily
|
// this expects that usage() is implemented lazily
|
||||||
s, err := cr.sizeG.Do(ctx, cr.ID(), func(ctx context.Context) (interface{}, error) {
|
s, err := cr.sizeG.Do(ctx, cr.ID(), func(ctx context.Context) (interface{}, error) {
|
||||||
|
@ -88,6 +93,10 @@ func (cr *cacheRecord) Size(ctx context.Context) (int64, error) {
|
||||||
cr.mu.Unlock()
|
cr.mu.Unlock()
|
||||||
usage, err := cr.cm.ManagerOpt.Snapshotter.Usage(ctx, driverID)
|
usage, err := cr.cm.ManagerOpt.Snapshotter.Usage(ctx, driverID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if cr.isDead() {
|
||||||
|
cr.mu.Unlock()
|
||||||
|
return int64(0), nil
|
||||||
|
}
|
||||||
return s, errors.Wrapf(err, "failed to get usage for %s", cr.ID())
|
return s, errors.Wrapf(err, "failed to get usage for %s", cr.ID())
|
||||||
}
|
}
|
||||||
cr.mu.Lock()
|
cr.mu.Lock()
|
||||||
|
@ -105,7 +114,10 @@ func (cr *cacheRecord) Parent() ImmutableRef {
|
||||||
if cr.parent == nil {
|
if cr.parent == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
return cr.parent.(*immutableRef).ref()
|
p := cr.parent.(*immutableRef)
|
||||||
|
p.mu.Lock()
|
||||||
|
defer p.mu.Unlock()
|
||||||
|
return p.ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cr *cacheRecord) Mount(ctx context.Context, readonly bool) ([]mount.Mount, error) {
|
func (cr *cacheRecord) Mount(ctx context.Context, readonly bool) ([]mount.Mount, error) {
|
||||||
|
@ -136,10 +148,7 @@ func (cr *cacheRecord) Mount(ctx context.Context, readonly bool) ([]mount.Mount,
|
||||||
}
|
}
|
||||||
if cr.viewMount == nil { // TODO: handle this better
|
if cr.viewMount == nil { // TODO: handle this better
|
||||||
cr.view = identity.NewID()
|
cr.view = identity.NewID()
|
||||||
labels := map[string]string{
|
m, err := cr.cm.Snapshotter.View(ctx, cr.view, cr.ID())
|
||||||
"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339Nano),
|
|
||||||
}
|
|
||||||
m, err := cr.cm.Snapshotter.View(ctx, cr.view, cr.ID(), cdsnapshot.WithLabels(labels))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
cr.view = ""
|
cr.view = ""
|
||||||
return nil, errors.Wrapf(err, "failed to mount %s", cr.ID())
|
return nil, errors.Wrapf(err, "failed to mount %s", cr.ID())
|
||||||
|
@ -149,16 +158,22 @@ func (cr *cacheRecord) Mount(ctx context.Context, readonly bool) ([]mount.Mount,
|
||||||
return cr.viewMount, nil
|
return cr.viewMount, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// call when holding the manager lock
|
||||||
func (cr *cacheRecord) remove(ctx context.Context, removeSnapshot bool) error {
|
func (cr *cacheRecord) remove(ctx context.Context, removeSnapshot bool) error {
|
||||||
delete(cr.cm.records, cr.ID())
|
delete(cr.cm.records, cr.ID())
|
||||||
if err := cr.cm.md.Clear(cr.ID()); err != nil {
|
if cr.parent != nil {
|
||||||
|
if err := cr.parent.(*immutableRef).release(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if removeSnapshot {
|
if removeSnapshot {
|
||||||
if err := cr.cm.Snapshotter.Remove(ctx, cr.ID()); err != nil {
|
if err := cr.cm.Snapshotter.Remove(ctx, cr.ID()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if err := cr.cm.md.Clear(cr.ID()); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -223,10 +238,7 @@ func (cr *cacheRecord) finalize(ctx context.Context) error {
|
||||||
if mutable == nil {
|
if mutable == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
labels := map[string]string{
|
err := cr.cm.Snapshotter.Commit(ctx, cr.ID(), mutable.ID())
|
||||||
"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339Nano),
|
|
||||||
}
|
|
||||||
err := cr.cm.Snapshotter.Commit(ctx, cr.ID(), mutable.ID(), cdsnapshot.WithLabels(labels))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrapf(err, "failed to commit %s", mutable.ID())
|
return errors.Wrapf(err, "failed to commit %s", mutable.ID())
|
||||||
}
|
}
|
||||||
|
@ -245,15 +257,16 @@ func (cr *cacheRecord) finalize(ctx context.Context) error {
|
||||||
|
|
||||||
func (sr *mutableRef) commit(ctx context.Context) (ImmutableRef, error) {
|
func (sr *mutableRef) commit(ctx context.Context) (ImmutableRef, error) {
|
||||||
if !sr.mutable || len(sr.refs) == 0 {
|
if !sr.mutable || len(sr.refs) == 0 {
|
||||||
return nil, errors.Wrapf(errInvalid, "invalid mutable")
|
return nil, errors.Wrapf(errInvalid, "invalid mutable ref")
|
||||||
}
|
}
|
||||||
|
|
||||||
id := identity.NewID()
|
id := identity.NewID()
|
||||||
md, _ := sr.cm.md.Get(id)
|
md, _ := sr.cm.md.Get(id)
|
||||||
|
|
||||||
rec := &cacheRecord{
|
rec := &cacheRecord{
|
||||||
|
mu: sr.mu,
|
||||||
cm: sr.cm,
|
cm: sr.cm,
|
||||||
parent: sr.parent,
|
parent: sr.Parent(),
|
||||||
equalMutable: sr,
|
equalMutable: sr,
|
||||||
refs: make(map[Mountable]struct{}),
|
refs: make(map[Mountable]struct{}),
|
||||||
md: md,
|
md: md,
|
||||||
|
|
|
@ -18,7 +18,9 @@ import (
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/images"
|
||||||
"github.com/containerd/containerd/namespaces"
|
"github.com/containerd/containerd/namespaces"
|
||||||
|
"github.com/containerd/containerd/snapshots"
|
||||||
"github.com/docker/distribution/manifest/schema2"
|
"github.com/docker/distribution/manifest/schema2"
|
||||||
"github.com/moby/buildkit/client/llb"
|
"github.com/moby/buildkit/client/llb"
|
||||||
"github.com/moby/buildkit/identity"
|
"github.com/moby/buildkit/identity"
|
||||||
|
@ -68,6 +70,8 @@ func testBuildMultiMount(t *testing.T, sb integration.Sandbox) {
|
||||||
|
|
||||||
err = c.Solve(context.TODO(), def, SolveOpt{}, nil)
|
err = c.Solve(context.TODO(), def, SolveOpt{}, nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
checkAllReleasable(t, c, sb, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testBuildHTTPSource(t *testing.T, sb integration.Sandbox) {
|
func testBuildHTTPSource(t *testing.T, sb integration.Sandbox) {
|
||||||
|
@ -157,6 +161,8 @@ func testBuildHTTPSource(t *testing.T, sb integration.Sandbox) {
|
||||||
require.Equal(t, fi.ModTime().Format(http.TimeFormat), modTime.Format(http.TimeFormat))
|
require.Equal(t, fi.ModTime().Format(http.TimeFormat), modTime.Format(http.TimeFormat))
|
||||||
require.Equal(t, int(fi.Mode()&0777), 0741)
|
require.Equal(t, int(fi.Mode()&0777), 0741)
|
||||||
|
|
||||||
|
checkAllReleasable(t, c, sb, true)
|
||||||
|
|
||||||
// TODO: check that second request was marked as cached
|
// TODO: check that second request was marked as cached
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,6 +259,8 @@ func testUser(t *testing.T, sb integration.Sandbox) {
|
||||||
dt, err = ioutil.ReadFile(filepath.Join(destDir, "userone"))
|
dt, err = ioutil.ReadFile(filepath.Join(destDir, "userone"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Contains(t, string(dt), "1")
|
require.Contains(t, string(dt), "1")
|
||||||
|
|
||||||
|
checkAllReleasable(t, c, sb, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testOCIExporter(t *testing.T, sb integration.Sandbox) {
|
func testOCIExporter(t *testing.T, sb integration.Sandbox) {
|
||||||
|
@ -347,8 +355,9 @@ func testOCIExporter(t *testing.T, sb integration.Sandbox) {
|
||||||
_, ok := m[l]
|
_, ok := m[l]
|
||||||
require.True(t, ok)
|
require.True(t, ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
checkAllReleasable(t, c, sb, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testBuildPushAndValidate(t *testing.T, sb integration.Sandbox) {
|
func testBuildPushAndValidate(t *testing.T, sb integration.Sandbox) {
|
||||||
|
@ -419,6 +428,8 @@ func testBuildPushAndValidate(t *testing.T, sb integration.Sandbox) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Equal(t, 0741, int(fi.Mode()&0777))
|
require.Equal(t, 0741, int(fi.Mode()&0777))
|
||||||
|
|
||||||
|
checkAllReleasable(t, c, sb, false)
|
||||||
|
|
||||||
// examine contents of exported tars (requires containerd)
|
// examine contents of exported tars (requires containerd)
|
||||||
var cdAddress string
|
var cdAddress string
|
||||||
if cd, ok := sb.(interface {
|
if cd, ok := sb.(interface {
|
||||||
|
@ -437,6 +448,16 @@ func testBuildPushAndValidate(t *testing.T, sb integration.Sandbox) {
|
||||||
|
|
||||||
ctx := namespaces.WithNamespace(context.Background(), "buildkit")
|
ctx := namespaces.WithNamespace(context.Background(), "buildkit")
|
||||||
|
|
||||||
|
// check image in containerd
|
||||||
|
_, err = client.ImageService().Get(ctx, target)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// deleting image should release all content
|
||||||
|
err = client.ImageService().Delete(ctx, target, images.SynchronousDelete())
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
checkAllReleasable(t, c, sb, true)
|
||||||
|
|
||||||
img, err := client.Pull(ctx, target)
|
img, err := client.Pull(ctx, target)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
@ -563,3 +584,67 @@ func readTarToMap(dt []byte, compressed bool) (map[string]*tarItem, error) {
|
||||||
m[h.Name] = &tarItem{header: h, data: dt}
|
m[h.Name] = &tarItem{header: h, data: dt}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func checkAllReleasable(t *testing.T, c *Client, sb integration.Sandbox, checkContent bool) {
|
||||||
|
err := c.Prune(context.TODO(), nil)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
du, err := c.DiskUsage(context.TODO())
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 0, len(du))
|
||||||
|
|
||||||
|
// examine contents of exported tars (requires containerd)
|
||||||
|
var cdAddress string
|
||||||
|
if cd, ok := sb.(interface {
|
||||||
|
ContainerdAddress() string
|
||||||
|
}); !ok {
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
cdAddress = cd.ContainerdAddress()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: make public pull helper function so this can be checked for standalone as well
|
||||||
|
|
||||||
|
client, err := containerd.New(cdAddress)
|
||||||
|
require.NoError(t, err)
|
||||||
|
defer client.Close()
|
||||||
|
|
||||||
|
ctx := namespaces.WithNamespace(context.Background(), "buildkit")
|
||||||
|
snapshotService := client.SnapshotService("overlayfs")
|
||||||
|
|
||||||
|
retries := 0
|
||||||
|
for {
|
||||||
|
count := 0
|
||||||
|
err = snapshotService.Walk(ctx, func(context.Context, snapshots.Info) error {
|
||||||
|
count++
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
if count == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
require.True(t, 20 > retries)
|
||||||
|
retries++
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !checkContent {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
retries = 0
|
||||||
|
for {
|
||||||
|
count := 0
|
||||||
|
err = client.ContentStore().Walk(ctx, func(content.Info) error {
|
||||||
|
count++
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
require.NoError(t, err)
|
||||||
|
if count == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
require.True(t, 20 > retries)
|
||||||
|
retries++
|
||||||
|
time.Sleep(500 * time.Millisecond)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ func (c *Client) DiskUsage(ctx context.Context, opts ...DiskUsageOption) ([]*Usa
|
||||||
req := &controlapi.DiskUsageRequest{Filter: info.Filter}
|
req := &controlapi.DiskUsageRequest{Filter: info.Filter}
|
||||||
resp, err := c.controlClient().DiskUsage(ctx, req)
|
resp, err := c.controlClient().DiskUsage(ctx, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to get diskusage")
|
return nil, errors.Wrap(err, "failed to call diskusage")
|
||||||
}
|
}
|
||||||
|
|
||||||
var du []*UsageInfo
|
var du []*UsageInfo
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
controlapi "github.com/moby/buildkit/api/services/control"
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (c *Client) Prune(ctx context.Context, ch chan UsageInfo, opts ...PruneOption) error {
|
||||||
|
info := &PruneInfo{}
|
||||||
|
for _, o := range opts {
|
||||||
|
o(info)
|
||||||
|
}
|
||||||
|
|
||||||
|
req := &controlapi.PruneRequest{}
|
||||||
|
cl, err := c.controlClient().Prune(ctx, req)
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to call prune")
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
d, err := cl.Recv()
|
||||||
|
if err != nil {
|
||||||
|
if err == io.EOF {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if ch != nil {
|
||||||
|
ch <- UsageInfo{
|
||||||
|
ID: d.ID,
|
||||||
|
Mutable: d.Mutable,
|
||||||
|
InUse: d.InUse,
|
||||||
|
Size: d.Size_,
|
||||||
|
Parent: d.Parent,
|
||||||
|
CreatedAt: d.CreatedAt,
|
||||||
|
Description: d.Description,
|
||||||
|
UsageCount: int(d.UsageCount),
|
||||||
|
LastUsedAt: d.LastUsedAt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type PruneOption func(*PruneInfo)
|
||||||
|
|
||||||
|
type PruneInfo struct {
|
||||||
|
}
|
|
@ -12,5 +12,6 @@ func TestCLIIntegration(t *testing.T) {
|
||||||
testBuildWithLocalFiles,
|
testBuildWithLocalFiles,
|
||||||
testBuildLocalExporter,
|
testBuildLocalExporter,
|
||||||
testBuildContainerdExporter,
|
testBuildContainerdExporter,
|
||||||
|
testPrune,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,17 +83,25 @@ func printVerbose(tw *tabwriter.Writer, du []*client.UsageInfo) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func printTable(tw *tabwriter.Writer, du []*client.UsageInfo) {
|
func printTable(tw *tabwriter.Writer, du []*client.UsageInfo) {
|
||||||
fmt.Fprintln(tw, "ID\tRECLAIMABLE\tSIZE\tLAST ACCESSED")
|
printTableHeader(tw)
|
||||||
|
|
||||||
for _, di := range du {
|
for _, di := range du {
|
||||||
|
printTableRow(tw, di)
|
||||||
|
}
|
||||||
|
|
||||||
|
tw.Flush()
|
||||||
|
}
|
||||||
|
|
||||||
|
func printTableHeader(tw *tabwriter.Writer) {
|
||||||
|
fmt.Fprintln(tw, "ID\tRECLAIMABLE\tSIZE\tLAST ACCESSED")
|
||||||
|
}
|
||||||
|
|
||||||
|
func printTableRow(tw *tabwriter.Writer, di *client.UsageInfo) {
|
||||||
id := di.ID
|
id := di.ID
|
||||||
if di.Mutable {
|
if di.Mutable {
|
||||||
id += "*"
|
id += "*"
|
||||||
}
|
}
|
||||||
fmt.Fprintf(tw, "%s\t%v\t%.2f\t\n", id, !di.InUse, units.Bytes(di.Size))
|
fmt.Fprintf(tw, "%-71s\t%-11v\t%.2f\t\n", id, !di.InUse, units.Bytes(di.Size))
|
||||||
}
|
|
||||||
|
|
||||||
tw.Flush()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func printSummary(tw *tabwriter.Writer, du []*client.UsageInfo) {
|
func printSummary(tw *tabwriter.Writer, du []*client.UsageInfo) {
|
||||||
|
|
|
@ -56,6 +56,7 @@ func main() {
|
||||||
|
|
||||||
app.Commands = []cli.Command{
|
app.Commands = []cli.Command{
|
||||||
diskUsageCommand,
|
diskUsageCommand,
|
||||||
|
pruneCommand,
|
||||||
buildCommand,
|
buildCommand,
|
||||||
debugCommand,
|
debugCommand,
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"text/tabwriter"
|
||||||
|
|
||||||
|
"github.com/moby/buildkit/client"
|
||||||
|
"github.com/moby/buildkit/util/appcontext"
|
||||||
|
"github.com/tonistiigi/units"
|
||||||
|
"github.com/urfave/cli"
|
||||||
|
)
|
||||||
|
|
||||||
|
var pruneCommand = cli.Command{
|
||||||
|
Name: "prune",
|
||||||
|
Usage: "clean up build cache",
|
||||||
|
Action: prune,
|
||||||
|
Flags: []cli.Flag{
|
||||||
|
cli.BoolFlag{
|
||||||
|
Name: "verbose, v",
|
||||||
|
Usage: "Verbose output",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func prune(clicontext *cli.Context) error {
|
||||||
|
c, err := resolveClient(clicontext)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
ch := make(chan client.UsageInfo)
|
||||||
|
printed := make(chan struct{})
|
||||||
|
|
||||||
|
tw := tabwriter.NewWriter(os.Stdout, 1, 8, 1, '\t', 0)
|
||||||
|
first := true
|
||||||
|
total := int64(0)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer close(printed)
|
||||||
|
for du := range ch {
|
||||||
|
total += du.Size
|
||||||
|
if clicontext.Bool("verbose") {
|
||||||
|
printVerbose(tw, []*client.UsageInfo{&du})
|
||||||
|
} else {
|
||||||
|
if first {
|
||||||
|
printTableHeader(tw)
|
||||||
|
first = false
|
||||||
|
}
|
||||||
|
printTableRow(tw, &du)
|
||||||
|
tw.Flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
err = c.Prune(appcontext.Context(), ch)
|
||||||
|
close(ch)
|
||||||
|
<-printed
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
tw = tabwriter.NewWriter(os.Stdout, 1, 8, 1, '\t', 0)
|
||||||
|
fmt.Fprintf(tw, "Total:\t%.2f\n", units.Bytes(total))
|
||||||
|
tw.Flush()
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
|
@ -0,0 +1,15 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/moby/buildkit/util/testutil/integration"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func testPrune(t *testing.T, sb integration.Sandbox) {
|
||||||
|
t.Parallel()
|
||||||
|
cmd := sb.Cmd("prune")
|
||||||
|
err := cmd.Run()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
|
@ -81,6 +81,53 @@ func (c *Controller) DiskUsage(ctx context.Context, r *controlapi.DiskUsageReque
|
||||||
return resp, nil
|
return resp, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Controller) Prune(req *controlapi.PruneRequest, stream controlapi.Control_PruneServer) error {
|
||||||
|
ch := make(chan client.UsageInfo)
|
||||||
|
|
||||||
|
eg, ctx := errgroup.WithContext(stream.Context())
|
||||||
|
workers, err := c.opt.WorkerController.List()
|
||||||
|
if err != nil {
|
||||||
|
return errors.Wrap(err, "failed to list workers for prune")
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, w := range workers {
|
||||||
|
func(w worker.Worker) {
|
||||||
|
eg.Go(func() error {
|
||||||
|
return w.Prune(ctx, ch)
|
||||||
|
})
|
||||||
|
}(w)
|
||||||
|
}
|
||||||
|
|
||||||
|
eg2, ctx := errgroup.WithContext(stream.Context())
|
||||||
|
|
||||||
|
eg2.Go(func() error {
|
||||||
|
defer close(ch)
|
||||||
|
return eg.Wait()
|
||||||
|
})
|
||||||
|
|
||||||
|
eg2.Go(func() error {
|
||||||
|
for r := range ch {
|
||||||
|
if err := stream.Send(&controlapi.UsageRecord{
|
||||||
|
// TODO: add worker info
|
||||||
|
ID: r.ID,
|
||||||
|
Mutable: r.Mutable,
|
||||||
|
InUse: r.InUse,
|
||||||
|
Size_: r.Size,
|
||||||
|
Parent: r.Parent,
|
||||||
|
UsageCount: int64(r.UsageCount),
|
||||||
|
Description: r.Description,
|
||||||
|
CreatedAt: r.CreatedAt,
|
||||||
|
LastUsedAt: r.LastUsedAt,
|
||||||
|
}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
return eg2.Wait()
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Controller) Solve(ctx context.Context, req *controlapi.SolveRequest) (*controlapi.SolveResponse, error) {
|
func (c *Controller) Solve(ctx context.Context, req *controlapi.SolveRequest) (*controlapi.SolveResponse, error) {
|
||||||
var frontend frontend.Frontend
|
var frontend frontend.Frontend
|
||||||
if req.Frontend != "" {
|
if req.Frontend != "" {
|
||||||
|
|
|
@ -75,6 +75,10 @@ func (e *imageExporterInstance) Export(ctx context.Context, ref cache.ImmutableR
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer func() {
|
||||||
|
e.opt.ImageWriter.ContentStore().Delete(context.TODO(), desc.Digest)
|
||||||
|
}()
|
||||||
|
|
||||||
if e.targetName != "" {
|
if e.targetName != "" {
|
||||||
if e.opt.Images != nil {
|
if e.opt.Images != nil {
|
||||||
tagDone := oneOffProgress(ctx, "naming to "+e.targetName)
|
tagDone := oneOffProgress(ctx, "naming to "+e.targetName)
|
||||||
|
|
|
@ -3,6 +3,7 @@ package containerimage
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
@ -68,17 +69,7 @@ func (ic *ImageWriter) Commit(ctx context.Context, ref cache.ImmutableRef, confi
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
addAsRoot := content.WithLabels(map[string]string{
|
|
||||||
"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339Nano),
|
|
||||||
})
|
|
||||||
|
|
||||||
configDigest := digest.FromBytes(config)
|
configDigest := digest.FromBytes(config)
|
||||||
configDone := oneOffProgress(ctx, "exporting config "+configDigest.String())
|
|
||||||
|
|
||||||
if err := content.WriteBlob(ctx, ic.opt.ContentStore, configDigest.String(), bytes.NewReader(config), int64(len(config)), configDigest, addAsRoot); err != nil {
|
|
||||||
return nil, configDone(errors.Wrap(err, "error writing config blob"))
|
|
||||||
}
|
|
||||||
configDone(nil)
|
|
||||||
|
|
||||||
mfst := schema2.Manifest{
|
mfst := schema2.Manifest{
|
||||||
Config: distribution.Descriptor{
|
Config: distribution.Descriptor{
|
||||||
|
@ -90,16 +81,21 @@ func (ic *ImageWriter) Commit(ctx context.Context, ref cache.ImmutableRef, confi
|
||||||
mfst.SchemaVersion = 2
|
mfst.SchemaVersion = 2
|
||||||
mfst.MediaType = schema2.MediaTypeManifest
|
mfst.MediaType = schema2.MediaTypeManifest
|
||||||
|
|
||||||
for _, dp := range diffPairs {
|
labels := map[string]string{
|
||||||
|
"containerd.io/gc.ref.content.0": configDigest.String(),
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, dp := range diffPairs {
|
||||||
info, err := ic.opt.ContentStore.Info(ctx, dp.Blobsum)
|
info, err := ic.opt.ContentStore.Info(ctx, dp.Blobsum)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, configDone(errors.Wrapf(err, "could not find blob %s from contentstore", dp.Blobsum))
|
return nil, errors.Wrapf(err, "could not find blob %s from contentstore", dp.Blobsum)
|
||||||
}
|
}
|
||||||
mfst.Layers = append(mfst.Layers, distribution.Descriptor{
|
mfst.Layers = append(mfst.Layers, distribution.Descriptor{
|
||||||
Digest: dp.Blobsum,
|
Digest: dp.Blobsum,
|
||||||
Size: info.Size,
|
Size: info.Size,
|
||||||
MediaType: schema2.MediaTypeLayer,
|
MediaType: schema2.MediaTypeLayer,
|
||||||
})
|
})
|
||||||
|
labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i+1)] = dp.Blobsum.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
mfstJSON, err := json.Marshal(mfst)
|
mfstJSON, err := json.Marshal(mfst)
|
||||||
|
@ -110,11 +106,23 @@ func (ic *ImageWriter) Commit(ctx context.Context, ref cache.ImmutableRef, confi
|
||||||
mfstDigest := digest.FromBytes(mfstJSON)
|
mfstDigest := digest.FromBytes(mfstJSON)
|
||||||
mfstDone := oneOffProgress(ctx, "exporting manifest "+mfstDigest.String())
|
mfstDone := oneOffProgress(ctx, "exporting manifest "+mfstDigest.String())
|
||||||
|
|
||||||
if err := content.WriteBlob(ctx, ic.opt.ContentStore, mfstDigest.String(), bytes.NewReader(mfstJSON), int64(len(mfstJSON)), mfstDigest, addAsRoot); err != nil {
|
if err := content.WriteBlob(ctx, ic.opt.ContentStore, mfstDigest.String(), bytes.NewReader(mfstJSON), int64(len(mfstJSON)), mfstDigest, content.WithLabels(labels)); err != nil {
|
||||||
return nil, mfstDone(errors.Wrapf(err, "error writing manifest blob %s", mfstDigest))
|
return nil, mfstDone(errors.Wrapf(err, "error writing manifest blob %s", mfstDigest))
|
||||||
}
|
}
|
||||||
mfstDone(nil)
|
mfstDone(nil)
|
||||||
|
|
||||||
|
configDone := oneOffProgress(ctx, "exporting config "+configDigest.String())
|
||||||
|
|
||||||
|
if err := content.WriteBlob(ctx, ic.opt.ContentStore, configDigest.String(), bytes.NewReader(config), int64(len(config)), configDigest); err != nil {
|
||||||
|
return nil, configDone(errors.Wrap(err, "error writing config blob"))
|
||||||
|
}
|
||||||
|
configDone(nil)
|
||||||
|
|
||||||
|
// delete config root. config will remain linked to the manifest
|
||||||
|
if err := ic.opt.ContentStore.Delete(context.TODO(), configDigest); err != nil {
|
||||||
|
return nil, errors.Wrap(err, "error removing config root")
|
||||||
|
}
|
||||||
|
|
||||||
return &ocispec.Descriptor{
|
return &ocispec.Descriptor{
|
||||||
Digest: mfstDigest,
|
Digest: mfstDigest,
|
||||||
Size: int64(len(mfstJSON)),
|
Size: int64(len(mfstJSON)),
|
||||||
|
@ -240,7 +248,11 @@ func getRefDesciptions(ref cache.ImmutableRef, limit int) []string {
|
||||||
if descr == "" {
|
if descr == "" {
|
||||||
descr = defaultMsg
|
descr = defaultMsg
|
||||||
}
|
}
|
||||||
return append(getRefDesciptions(ref.Parent(), limit-1), descr)
|
p := ref.Parent()
|
||||||
|
if p != nil {
|
||||||
|
defer p.Release(context.TODO())
|
||||||
|
}
|
||||||
|
return append(getRefDesciptions(p, limit-1), descr)
|
||||||
}
|
}
|
||||||
|
|
||||||
func oneOffProgress(ctx context.Context, id string) func(err error) error {
|
func oneOffProgress(ctx context.Context, id string) func(err error) error {
|
||||||
|
|
|
@ -93,6 +93,9 @@ func (e *imageExporterInstance) Export(ctx context.Context, ref cache.ImmutableR
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
defer func() {
|
||||||
|
e.opt.ImageWriter.ContentStore().Delete(context.TODO(), desc.Digest)
|
||||||
|
}()
|
||||||
if desc.Annotations == nil {
|
if desc.Annotations == nil {
|
||||||
desc.Annotations = map[string]string{}
|
desc.Annotations = map[string]string{}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
"github.com/containerd/containerd/snapshots"
|
"github.com/containerd/containerd/snapshots"
|
||||||
"github.com/moby/buildkit/cache/metadata"
|
"github.com/moby/buildkit/cache/metadata"
|
||||||
|
"github.com/moby/buildkit/snapshot"
|
||||||
digest "github.com/opencontainers/go-digest"
|
digest "github.com/opencontainers/go-digest"
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
@ -36,13 +37,13 @@ type Snapshotter struct {
|
||||||
opt Opt
|
opt Opt
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSnapshotter(opt Opt) (*Snapshotter, error) {
|
func NewSnapshotter(opt Opt) snapshot.Snapshotter {
|
||||||
s := &Snapshotter{
|
s := &Snapshotter{
|
||||||
Snapshotter: opt.Snapshotter,
|
Snapshotter: opt.Snapshotter,
|
||||||
opt: opt,
|
opt: opt,
|
||||||
}
|
}
|
||||||
|
|
||||||
return s, nil
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove also removes a reference to a blob. If it is a last reference then it deletes it the blob as well
|
// Remove also removes a reference to a blob. If it is a last reference then it deletes it the blob as well
|
||||||
|
@ -64,7 +65,7 @@ func (s *Snapshotter) Remove(ctx context.Context, key string) error {
|
||||||
|
|
||||||
if len(blobs) == 1 && blobs[0].ID() == key { // last snapshot
|
if len(blobs) == 1 && blobs[0].ID() == key { // last snapshot
|
||||||
if err := s.opt.Content.Delete(ctx, blob); err != nil {
|
if err := s.opt.Content.Delete(ctx, blob); err != nil {
|
||||||
logrus.Errorf("failed to delete blob %v", blob)
|
logrus.Errorf("failed to delete blob %v: %+v", blob, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -0,0 +1,98 @@
|
||||||
|
package containerd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/namespaces"
|
||||||
|
"github.com/opencontainers/go-digest"
|
||||||
|
)
|
||||||
|
|
||||||
|
type garbageCollectFn func(context.Context) error
|
||||||
|
|
||||||
|
func NewContentStore(store content.Store, ns string, gc func(context.Context) error) content.Store {
|
||||||
|
return &noGCContentStore{&nsContent{ns, store, gc}}
|
||||||
|
}
|
||||||
|
|
||||||
|
type nsContent struct {
|
||||||
|
ns string
|
||||||
|
content.Store
|
||||||
|
gc garbageCollectFn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *nsContent) Info(ctx context.Context, dgst digest.Digest) (content.Info, error) {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, c.ns)
|
||||||
|
return c.Store.Info(ctx, dgst)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *nsContent) Update(ctx context.Context, info content.Info, fieldpaths ...string) (content.Info, error) {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, c.ns)
|
||||||
|
return c.Store.Update(ctx, info, fieldpaths...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *nsContent) Walk(ctx context.Context, fn content.WalkFunc, filters ...string) error {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, c.ns)
|
||||||
|
return c.Store.Walk(ctx, fn, filters...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *nsContent) Delete(ctx context.Context, dgst digest.Digest) error {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, c.ns)
|
||||||
|
if _, err := c.Update(ctx, content.Info{
|
||||||
|
Digest: dgst,
|
||||||
|
}, "labels.containerd.io/gc.root"); err != nil {
|
||||||
|
return err
|
||||||
|
} // calling snapshotter.Remove here causes a race in containerd
|
||||||
|
if c.gc == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return c.gc(ctx)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *nsContent) Status(ctx context.Context, ref string) (content.Status, error) {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, c.ns)
|
||||||
|
return c.Store.Status(ctx, ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *nsContent) ListStatuses(ctx context.Context, filters ...string) ([]content.Status, error) {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, c.ns)
|
||||||
|
return c.Store.ListStatuses(ctx, filters...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *nsContent) Abort(ctx context.Context, ref string) error {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, c.ns)
|
||||||
|
return c.Store.Abort(ctx, ref)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *nsContent) ReaderAt(ctx context.Context, dgst digest.Digest) (content.ReaderAt, error) {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, c.ns)
|
||||||
|
return c.Store.ReaderAt(ctx, dgst)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *nsContent) Writer(ctx context.Context, ref string, size int64, expected digest.Digest) (content.Writer, error) {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, c.ns)
|
||||||
|
return c.Store.Writer(ctx, ref, size, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
type noGCContentStore struct {
|
||||||
|
content.Store
|
||||||
|
}
|
||||||
|
type noGCWriter struct {
|
||||||
|
content.Writer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (cs *noGCContentStore) Writer(ctx context.Context, ref string, size int64, expected digest.Digest) (content.Writer, error) {
|
||||||
|
w, err := cs.Store.Writer(ctx, ref, size, expected)
|
||||||
|
return &noGCWriter{w}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *noGCWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error {
|
||||||
|
opts = append(opts, func(info *content.Info) error {
|
||||||
|
if info.Labels == nil {
|
||||||
|
info.Labels = map[string]string{}
|
||||||
|
}
|
||||||
|
info.Labels["containerd.io/gc.root"] = time.Now().UTC().Format(time.RFC3339Nano)
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
return w.Writer.Commit(ctx, size, expected, opts...)
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
package containerd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/containerd/containerd/content"
|
||||||
|
"github.com/containerd/containerd/mount"
|
||||||
|
"github.com/containerd/containerd/namespaces"
|
||||||
|
ctdsnapshot "github.com/containerd/containerd/snapshots"
|
||||||
|
"github.com/moby/buildkit/cache/metadata"
|
||||||
|
"github.com/moby/buildkit/snapshot"
|
||||||
|
"github.com/moby/buildkit/snapshot/blobmapping"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewSnapshotter(snapshotter ctdsnapshot.Snapshotter, store content.Store, mdstore *metadata.Store, ns string, gc func(context.Context) error) snapshot.Snapshotter {
|
||||||
|
return blobmapping.NewSnapshotter(blobmapping.Opt{
|
||||||
|
Content: store,
|
||||||
|
Snapshotter: &nsSnapshotter{ns, snapshotter, gc},
|
||||||
|
MetadataStore: mdstore,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
type nsSnapshotter struct {
|
||||||
|
ns string
|
||||||
|
ctdsnapshot.Snapshotter
|
||||||
|
gc garbageCollectFn
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *nsSnapshotter) Stat(ctx context.Context, key string) (ctdsnapshot.Info, error) {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, s.ns)
|
||||||
|
return s.Snapshotter.Stat(ctx, key)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *nsSnapshotter) Update(ctx context.Context, info ctdsnapshot.Info, fieldpaths ...string) (ctdsnapshot.Info, error) {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, s.ns)
|
||||||
|
return s.Snapshotter.Update(ctx, info, fieldpaths...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *nsSnapshotter) Usage(ctx context.Context, key string) (ctdsnapshot.Usage, error) {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, s.ns)
|
||||||
|
return s.Snapshotter.Usage(ctx, key)
|
||||||
|
}
|
||||||
|
func (s *nsSnapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, error) {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, s.ns)
|
||||||
|
return s.Snapshotter.Mounts(ctx, key)
|
||||||
|
}
|
||||||
|
func (s *nsSnapshotter) Prepare(ctx context.Context, key, parent string, opts ...ctdsnapshot.Opt) ([]mount.Mount, error) {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, s.ns)
|
||||||
|
return s.Snapshotter.Prepare(ctx, key, parent, addRootLabel(opts...))
|
||||||
|
}
|
||||||
|
func (s *nsSnapshotter) View(ctx context.Context, key, parent string, opts ...ctdsnapshot.Opt) ([]mount.Mount, error) {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, s.ns)
|
||||||
|
return s.Snapshotter.View(ctx, key, parent, addRootLabel(opts...))
|
||||||
|
}
|
||||||
|
func (s *nsSnapshotter) Commit(ctx context.Context, name, key string, opts ...ctdsnapshot.Opt) error {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, s.ns)
|
||||||
|
return s.Snapshotter.Commit(ctx, name, key, addRootLabel(opts...))
|
||||||
|
}
|
||||||
|
func (s *nsSnapshotter) Remove(ctx context.Context, key string) error {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, s.ns)
|
||||||
|
if _, err := s.Update(ctx, ctdsnapshot.Info{
|
||||||
|
Name: key,
|
||||||
|
}, "labels.containerd.io/gc.root"); err != nil {
|
||||||
|
return err
|
||||||
|
} // calling snapshotter.Remove here causes a race in containerd
|
||||||
|
if s.gc == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return s.gc(ctx)
|
||||||
|
}
|
||||||
|
func (s *nsSnapshotter) Walk(ctx context.Context, fn func(context.Context, ctdsnapshot.Info) error) error {
|
||||||
|
ctx = namespaces.WithNamespace(ctx, s.ns)
|
||||||
|
return s.Snapshotter.Walk(ctx, fn)
|
||||||
|
}
|
||||||
|
|
||||||
|
func addRootLabel(opts ...ctdsnapshot.Opt) ctdsnapshot.Opt {
|
||||||
|
return func(info *ctdsnapshot.Info) error {
|
||||||
|
for _, opt := range opts {
|
||||||
|
if err := opt(info); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if info.Labels == nil {
|
||||||
|
info.Labels = map[string]string{}
|
||||||
|
}
|
||||||
|
info.Labels["containerd.io/gc.root"] = time.Now().UTC().Format(time.RFC3339Nano)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,10 +1,19 @@
|
||||||
package snapshot
|
package snapshot
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"github.com/containerd/containerd/snapshots"
|
"github.com/containerd/containerd/snapshots"
|
||||||
|
digest "github.com/opencontainers/go-digest"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Snapshotter defines interface that any snapshot implementation should satisfy
|
// Snapshotter defines interface that any snapshot implementation should satisfy
|
||||||
type Snapshotter interface {
|
type Snapshotter interface {
|
||||||
snapshots.Snapshotter
|
snapshots.Snapshotter
|
||||||
|
Blobmapper
|
||||||
|
}
|
||||||
|
|
||||||
|
type Blobmapper interface {
|
||||||
|
GetBlob(ctx context.Context, key string) (digest.Digest, digest.Digest, error)
|
||||||
|
SetBlob(ctx context.Context, key string, diffID, blob digest.Digest) error
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"github.com/moby/buildkit/cache"
|
"github.com/moby/buildkit/cache"
|
||||||
"github.com/moby/buildkit/session"
|
"github.com/moby/buildkit/session"
|
||||||
"github.com/moby/buildkit/session/auth"
|
"github.com/moby/buildkit/session/auth"
|
||||||
|
"github.com/moby/buildkit/snapshot"
|
||||||
"github.com/moby/buildkit/source"
|
"github.com/moby/buildkit/source"
|
||||||
"github.com/moby/buildkit/util/flightcontrol"
|
"github.com/moby/buildkit/util/flightcontrol"
|
||||||
"github.com/moby/buildkit/util/imageutil"
|
"github.com/moby/buildkit/util/imageutil"
|
||||||
|
@ -36,17 +37,12 @@ import (
|
||||||
|
|
||||||
type SourceOpt struct {
|
type SourceOpt struct {
|
||||||
SessionManager *session.Manager
|
SessionManager *session.Manager
|
||||||
Snapshotter snapshots.Snapshotter
|
Snapshotter snapshot.Snapshotter
|
||||||
ContentStore content.Store
|
ContentStore content.Store
|
||||||
Applier diff.Differ
|
Applier diff.Differ
|
||||||
CacheAccessor cache.Accessor
|
CacheAccessor cache.Accessor
|
||||||
}
|
}
|
||||||
|
|
||||||
type blobmapper interface {
|
|
||||||
GetBlob(ctx gocontext.Context, key string) (digest.Digest, digest.Digest, error)
|
|
||||||
SetBlob(ctx gocontext.Context, key string, diffID, blob digest.Digest) error
|
|
||||||
}
|
|
||||||
|
|
||||||
type resolveRecord struct {
|
type resolveRecord struct {
|
||||||
desc ocispec.Descriptor
|
desc ocispec.Descriptor
|
||||||
ts time.Time
|
ts time.Time
|
||||||
|
@ -62,10 +58,6 @@ func NewSource(opt SourceOpt) (source.Source, error) {
|
||||||
SourceOpt: opt,
|
SourceOpt: opt,
|
||||||
}
|
}
|
||||||
|
|
||||||
if _, ok := opt.Snapshotter.(blobmapper); !ok {
|
|
||||||
return nil, errors.Errorf("imagesource requires snapshotter with blobs mapping support")
|
|
||||||
}
|
|
||||||
|
|
||||||
return is, nil
|
return is, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -236,6 +228,40 @@ func (p *puller) Snapshot(ctx context.Context) (cache.ImmutableRef, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// split all pulled data to layers and rest. layers remain roots and are deleted with snapshots. rest will be linked to layers.
|
||||||
|
var notLayerBlobs []ocispec.Descriptor
|
||||||
|
var layerBlobs []ocispec.Descriptor
|
||||||
|
for _, j := range ongoing.added {
|
||||||
|
switch j.MediaType {
|
||||||
|
case ocispec.MediaTypeImageLayer, images.MediaTypeDockerSchema2Layer, ocispec.MediaTypeImageLayerGzip, images.MediaTypeDockerSchema2LayerGzip:
|
||||||
|
layerBlobs = append(layerBlobs, j.Descriptor)
|
||||||
|
default:
|
||||||
|
notLayerBlobs = append(notLayerBlobs, j.Descriptor)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, l := range layerBlobs {
|
||||||
|
labels := map[string]string{}
|
||||||
|
var fields []string
|
||||||
|
for _, nl := range notLayerBlobs {
|
||||||
|
k := "containerd.io/gc.ref.content." + nl.Digest.Hex()[:12]
|
||||||
|
labels[k] = nl.Digest.String()
|
||||||
|
fields = append(fields, "labels."+k)
|
||||||
|
}
|
||||||
|
if _, err := p.is.ContentStore.Update(ctx, content.Info{
|
||||||
|
Digest: l.Digest,
|
||||||
|
Labels: labels,
|
||||||
|
}, fields...); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, nl := range notLayerBlobs {
|
||||||
|
if err := p.is.ContentStore.Delete(ctx, nl.Digest); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unpackProgressDone := oneOffProgress(ctx, "unpacking "+p.src.Reference.String())
|
unpackProgressDone := oneOffProgress(ctx, "unpacking "+p.src.Reference.String())
|
||||||
chainid, err := p.is.unpack(ctx, p.desc)
|
chainid, err := p.is.unpack(ctx, p.desc)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -280,7 +306,7 @@ func (is *imageSource) fillBlobMapping(ctx context.Context, layers []rootfs.Laye
|
||||||
for _, l := range layers {
|
for _, l := range layers {
|
||||||
chain = append(chain, l.Diff.Digest)
|
chain = append(chain, l.Diff.Digest)
|
||||||
chainID := identity.ChainID(chain)
|
chainID := identity.ChainID(chain)
|
||||||
if err := is.SourceOpt.Snapshotter.(blobmapper).SetBlob(ctx, string(chainID), l.Diff.Digest, l.Blob.Digest); err != nil {
|
if err := is.SourceOpt.Snapshotter.SetBlob(ctx, string(chainID), l.Diff.Digest, l.Blob.Digest); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/content"
|
||||||
"github.com/containerd/containerd/diff"
|
"github.com/containerd/containerd/diff"
|
||||||
"github.com/containerd/containerd/images"
|
"github.com/containerd/containerd/images"
|
||||||
ctdsnapshot "github.com/containerd/containerd/snapshots"
|
|
||||||
"github.com/moby/buildkit/cache"
|
"github.com/moby/buildkit/cache"
|
||||||
"github.com/moby/buildkit/cache/cacheimport"
|
"github.com/moby/buildkit/cache/cacheimport"
|
||||||
"github.com/moby/buildkit/cache/instructioncache"
|
"github.com/moby/buildkit/cache/instructioncache"
|
||||||
|
@ -24,7 +23,7 @@ import (
|
||||||
ociexporter "github.com/moby/buildkit/exporter/oci"
|
ociexporter "github.com/moby/buildkit/exporter/oci"
|
||||||
"github.com/moby/buildkit/identity"
|
"github.com/moby/buildkit/identity"
|
||||||
"github.com/moby/buildkit/session"
|
"github.com/moby/buildkit/session"
|
||||||
"github.com/moby/buildkit/snapshot/blobmapping"
|
"github.com/moby/buildkit/snapshot"
|
||||||
"github.com/moby/buildkit/solver"
|
"github.com/moby/buildkit/solver"
|
||||||
"github.com/moby/buildkit/solver/llbop"
|
"github.com/moby/buildkit/solver/llbop"
|
||||||
"github.com/moby/buildkit/solver/pb"
|
"github.com/moby/buildkit/solver/pb"
|
||||||
|
@ -49,7 +48,7 @@ type WorkerOpt struct {
|
||||||
SessionManager *session.Manager
|
SessionManager *session.Manager
|
||||||
MetadataStore *metadata.Store
|
MetadataStore *metadata.Store
|
||||||
Executor executor.Executor
|
Executor executor.Executor
|
||||||
BaseSnapshotter ctdsnapshot.Snapshotter // not blobmapping one (FIXME: just require blobmapping snapshotter?)
|
Snapshotter snapshot.Snapshotter
|
||||||
ContentStore content.Store
|
ContentStore content.Store
|
||||||
Applier diff.Differ
|
Applier diff.Differ
|
||||||
Differ diff.Differ
|
Differ diff.Differ
|
||||||
|
@ -60,7 +59,6 @@ type WorkerOpt struct {
|
||||||
// TODO: s/Worker/OpWorker/g ?
|
// TODO: s/Worker/OpWorker/g ?
|
||||||
type Worker struct {
|
type Worker struct {
|
||||||
WorkerOpt
|
WorkerOpt
|
||||||
Snapshotter ctdsnapshot.Snapshotter // blobmapping snapshotter
|
|
||||||
CacheManager cache.Manager
|
CacheManager cache.Manager
|
||||||
SourceManager *source.Manager
|
SourceManager *source.Manager
|
||||||
cache instructioncache.InstructionCache
|
cache instructioncache.InstructionCache
|
||||||
|
@ -73,17 +71,8 @@ type Worker struct {
|
||||||
|
|
||||||
// NewWorker instantiates a local worker
|
// NewWorker instantiates a local worker
|
||||||
func NewWorker(opt WorkerOpt) (*Worker, error) {
|
func NewWorker(opt WorkerOpt) (*Worker, error) {
|
||||||
bmSnapshotter, err := blobmapping.NewSnapshotter(blobmapping.Opt{
|
|
||||||
Content: opt.ContentStore,
|
|
||||||
Snapshotter: opt.BaseSnapshotter,
|
|
||||||
MetadataStore: opt.MetadataStore,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
cm, err := cache.NewManager(cache.ManagerOpt{
|
cm, err := cache.NewManager(cache.ManagerOpt{
|
||||||
Snapshotter: bmSnapshotter,
|
Snapshotter: opt.Snapshotter,
|
||||||
MetadataStore: opt.MetadataStore,
|
MetadataStore: opt.MetadataStore,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -101,7 +90,7 @@ func NewWorker(opt WorkerOpt) (*Worker, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
is, err := containerimage.NewSource(containerimage.SourceOpt{
|
is, err := containerimage.NewSource(containerimage.SourceOpt{
|
||||||
Snapshotter: bmSnapshotter,
|
Snapshotter: opt.Snapshotter,
|
||||||
ContentStore: opt.ContentStore,
|
ContentStore: opt.ContentStore,
|
||||||
SessionManager: opt.SessionManager,
|
SessionManager: opt.SessionManager,
|
||||||
Applier: opt.Applier,
|
Applier: opt.Applier,
|
||||||
|
@ -146,7 +135,7 @@ func NewWorker(opt WorkerOpt) (*Worker, error) {
|
||||||
exporters := map[string]exporter.Exporter{}
|
exporters := map[string]exporter.Exporter{}
|
||||||
|
|
||||||
iw, err := imageexporter.NewImageWriter(imageexporter.WriterOpt{
|
iw, err := imageexporter.NewImageWriter(imageexporter.WriterOpt{
|
||||||
Snapshotter: bmSnapshotter,
|
Snapshotter: opt.Snapshotter,
|
||||||
ContentStore: opt.ContentStore,
|
ContentStore: opt.ContentStore,
|
||||||
Differ: opt.Differ,
|
Differ: opt.Differ,
|
||||||
})
|
})
|
||||||
|
@ -193,14 +182,14 @@ func NewWorker(opt WorkerOpt) (*Worker, error) {
|
||||||
exporters[client.ExporterDocker] = dockerExporter
|
exporters[client.ExporterDocker] = dockerExporter
|
||||||
|
|
||||||
ce := cacheimport.NewCacheExporter(cacheimport.ExporterOpt{
|
ce := cacheimport.NewCacheExporter(cacheimport.ExporterOpt{
|
||||||
Snapshotter: bmSnapshotter,
|
Snapshotter: opt.Snapshotter,
|
||||||
ContentStore: opt.ContentStore,
|
ContentStore: opt.ContentStore,
|
||||||
SessionManager: opt.SessionManager,
|
SessionManager: opt.SessionManager,
|
||||||
Differ: opt.Differ,
|
Differ: opt.Differ,
|
||||||
})
|
})
|
||||||
|
|
||||||
ci := cacheimport.NewCacheImporter(cacheimport.ImportOpt{
|
ci := cacheimport.NewCacheImporter(cacheimport.ImportOpt{
|
||||||
Snapshotter: bmSnapshotter,
|
Snapshotter: opt.Snapshotter,
|
||||||
ContentStore: opt.ContentStore,
|
ContentStore: opt.ContentStore,
|
||||||
Applier: opt.Applier,
|
Applier: opt.Applier,
|
||||||
CacheAccessor: cm,
|
CacheAccessor: cm,
|
||||||
|
@ -209,7 +198,6 @@ func NewWorker(opt WorkerOpt) (*Worker, error) {
|
||||||
|
|
||||||
return &Worker{
|
return &Worker{
|
||||||
WorkerOpt: opt,
|
WorkerOpt: opt,
|
||||||
Snapshotter: bmSnapshotter,
|
|
||||||
CacheManager: cm,
|
CacheManager: cm,
|
||||||
SourceManager: sm,
|
SourceManager: sm,
|
||||||
cache: ic,
|
cache: ic,
|
||||||
|
@ -267,6 +255,10 @@ func (w *Worker) DiskUsage(ctx context.Context, opt client.DiskUsageInfo) ([]*cl
|
||||||
return w.CacheManager.DiskUsage(ctx, opt)
|
return w.CacheManager.DiskUsage(ctx, opt)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (w *Worker) Prune(ctx context.Context, ch chan client.UsageInfo) error {
|
||||||
|
return w.CacheManager.Prune(ctx, ch)
|
||||||
|
}
|
||||||
|
|
||||||
func (w *Worker) Exporter(name string) (exporter.Exporter, error) {
|
func (w *Worker) Exporter(name string) (exporter.Exporter, error) {
|
||||||
exp, ok := w.Exporters[name]
|
exp, ok := w.Exporters[name]
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
|
@ -8,11 +8,13 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/containerd/containerd"
|
"github.com/containerd/containerd"
|
||||||
"github.com/containerd/containerd/content"
|
"github.com/containerd/containerd/namespaces"
|
||||||
|
"github.com/containerd/containerd/snapshots"
|
||||||
"github.com/moby/buildkit/cache/metadata"
|
"github.com/moby/buildkit/cache/metadata"
|
||||||
"github.com/moby/buildkit/executor/containerdexecutor"
|
"github.com/moby/buildkit/executor/containerdexecutor"
|
||||||
|
"github.com/moby/buildkit/identity"
|
||||||
|
containerdsnapshot "github.com/moby/buildkit/snapshot/containerd"
|
||||||
"github.com/moby/buildkit/worker/base"
|
"github.com/moby/buildkit/worker/base"
|
||||||
digest "github.com/opencontainers/go-digest"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -53,41 +55,35 @@ func newContainerd(root string, client *containerd.Client, snapshotterName strin
|
||||||
for k, v := range labels {
|
for k, v := range labels {
|
||||||
xlabels[k] = v
|
xlabels[k] = v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gc := func(ctx context.Context) error {
|
||||||
|
// TODO: how to avoid this?
|
||||||
|
snapshotter := client.SnapshotService(snapshotterName)
|
||||||
|
ctx = namespaces.WithNamespace(ctx, "buildkit")
|
||||||
|
key := identity.NewID()
|
||||||
|
if _, err := snapshotter.Prepare(ctx, key, "", snapshots.WithLabels(map[string]string{
|
||||||
|
"containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339Nano),
|
||||||
|
})); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if err := snapshotter.Remove(ctx, key); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
cs := containerdsnapshot.NewContentStore(client.ContentStore(), "buildkit", gc)
|
||||||
|
|
||||||
opt := base.WorkerOpt{
|
opt := base.WorkerOpt{
|
||||||
ID: id,
|
ID: id,
|
||||||
Labels: xlabels,
|
Labels: xlabels,
|
||||||
MetadataStore: md,
|
MetadataStore: md,
|
||||||
Executor: containerdexecutor.New(client, root),
|
Executor: containerdexecutor.New(client, root),
|
||||||
BaseSnapshotter: client.SnapshotService(snapshotterName),
|
Snapshotter: containerdsnapshot.NewSnapshotter(client.SnapshotService(snapshotterName), cs, md, "buildkit", gc),
|
||||||
ContentStore: &noGCContentStore{client.ContentStore()},
|
ContentStore: cs,
|
||||||
Applier: df,
|
Applier: df,
|
||||||
Differ: df,
|
Differ: df,
|
||||||
ImageStore: client.ImageService(),
|
ImageStore: client.ImageService(),
|
||||||
}
|
}
|
||||||
return opt, nil
|
return opt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Replace this with leases
|
|
||||||
|
|
||||||
type noGCContentStore struct {
|
|
||||||
content.Store
|
|
||||||
}
|
|
||||||
type noGCWriter struct {
|
|
||||||
content.Writer
|
|
||||||
}
|
|
||||||
|
|
||||||
func (cs *noGCContentStore) Writer(ctx context.Context, ref string, size int64, expected digest.Digest) (content.Writer, error) {
|
|
||||||
w, err := cs.Store.Writer(ctx, ref, size, expected)
|
|
||||||
return &noGCWriter{w}, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *noGCWriter) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error {
|
|
||||||
opts = append(opts, func(info *content.Info) error {
|
|
||||||
if info.Labels == nil {
|
|
||||||
info.Labels = map[string]string{}
|
|
||||||
}
|
|
||||||
info.Labels["containerd.io/gc.root"] = time.Now().UTC().Format(time.RFC3339Nano)
|
|
||||||
return nil
|
|
||||||
})
|
|
||||||
return w.Writer.Commit(ctx, size, expected, opts...)
|
|
||||||
}
|
|
||||||
|
|
|
@ -6,18 +6,15 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/boltdb/bolt"
|
"github.com/boltdb/bolt"
|
||||||
"github.com/containerd/containerd/content"
|
|
||||||
"github.com/containerd/containerd/content/local"
|
"github.com/containerd/containerd/content/local"
|
||||||
"github.com/containerd/containerd/diff/walking"
|
"github.com/containerd/containerd/diff/walking"
|
||||||
ctdmetadata "github.com/containerd/containerd/metadata"
|
ctdmetadata "github.com/containerd/containerd/metadata"
|
||||||
"github.com/containerd/containerd/mount"
|
|
||||||
"github.com/containerd/containerd/namespaces"
|
|
||||||
ctdsnapshot "github.com/containerd/containerd/snapshots"
|
ctdsnapshot "github.com/containerd/containerd/snapshots"
|
||||||
"github.com/containerd/containerd/snapshots/overlay"
|
"github.com/containerd/containerd/snapshots/overlay"
|
||||||
"github.com/moby/buildkit/cache/metadata"
|
"github.com/moby/buildkit/cache/metadata"
|
||||||
"github.com/moby/buildkit/executor/runcexecutor"
|
"github.com/moby/buildkit/executor/runcexecutor"
|
||||||
|
containerdsnapshot "github.com/moby/buildkit/snapshot/containerd"
|
||||||
"github.com/moby/buildkit/worker/base"
|
"github.com/moby/buildkit/worker/base"
|
||||||
"github.com/opencontainers/go-digest"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewWorkerOpt creates a WorkerOpt.
|
// NewWorkerOpt creates a WorkerOpt.
|
||||||
|
@ -60,14 +57,17 @@ func NewWorkerOpt(root string, labels map[string]string) (base.WorkerOpt, error)
|
||||||
return opt, err
|
return opt, err
|
||||||
}
|
}
|
||||||
|
|
||||||
c = &nsContent{mdb.ContentStore()}
|
gc := func(ctx context.Context) error {
|
||||||
|
_, err := mdb.GarbageCollect(ctx)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
c = containerdsnapshot.NewContentStore(mdb.ContentStore(), "buildkit", gc)
|
||||||
df, err := walking.NewWalkingDiff(c)
|
df, err := walking.NewWalkingDiff(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return opt, err
|
return opt, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: call mdb.GarbageCollect . maybe just inject it into nsSnapshotter.Remove and csContent.Delete
|
|
||||||
|
|
||||||
id, err := base.ID(root)
|
id, err := base.ID(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return opt, err
|
return opt, err
|
||||||
|
@ -81,7 +81,7 @@ func NewWorkerOpt(root string, labels map[string]string) (base.WorkerOpt, error)
|
||||||
Labels: xlabels,
|
Labels: xlabels,
|
||||||
MetadataStore: md,
|
MetadataStore: md,
|
||||||
Executor: exe,
|
Executor: exe,
|
||||||
BaseSnapshotter: &nsSnapshotter{mdb.Snapshotter("overlayfs")},
|
Snapshotter: containerdsnapshot.NewSnapshotter(mdb.Snapshotter("overlayfs"), c, md, "buildkit", gc),
|
||||||
ContentStore: c,
|
ContentStore: c,
|
||||||
Applier: df,
|
Applier: df,
|
||||||
Differ: df,
|
Differ: df,
|
||||||
|
@ -89,98 +89,3 @@ func NewWorkerOpt(root string, labels map[string]string) (base.WorkerOpt, error)
|
||||||
}
|
}
|
||||||
return opt, nil
|
return opt, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// this should be supported by containerd. currently packages are unusable without wrapping
|
|
||||||
const dummyNs = "buildkit"
|
|
||||||
|
|
||||||
type nsContent struct {
|
|
||||||
content.Store
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *nsContent) Info(ctx context.Context, dgst digest.Digest) (content.Info, error) {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, dummyNs)
|
|
||||||
return c.Store.Info(ctx, dgst)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *nsContent) Update(ctx context.Context, info content.Info, fieldpaths ...string) (content.Info, error) {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, dummyNs)
|
|
||||||
return c.Store.Update(ctx, info, fieldpaths...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *nsContent) Walk(ctx context.Context, fn content.WalkFunc, filters ...string) error {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, dummyNs)
|
|
||||||
return c.Store.Walk(ctx, fn, filters...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *nsContent) Delete(ctx context.Context, dgst digest.Digest) error {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, dummyNs)
|
|
||||||
return c.Store.Delete(ctx, dgst)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *nsContent) Status(ctx context.Context, ref string) (content.Status, error) {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, dummyNs)
|
|
||||||
return c.Store.Status(ctx, ref)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *nsContent) ListStatuses(ctx context.Context, filters ...string) ([]content.Status, error) {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, dummyNs)
|
|
||||||
return c.Store.ListStatuses(ctx, filters...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *nsContent) Abort(ctx context.Context, ref string) error {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, dummyNs)
|
|
||||||
return c.Store.Abort(ctx, ref)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *nsContent) ReaderAt(ctx context.Context, dgst digest.Digest) (content.ReaderAt, error) {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, dummyNs)
|
|
||||||
return c.Store.ReaderAt(ctx, dgst)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *nsContent) Writer(ctx context.Context, ref string, size int64, expected digest.Digest) (content.Writer, error) {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, dummyNs)
|
|
||||||
return c.Store.Writer(ctx, ref, size, expected)
|
|
||||||
}
|
|
||||||
|
|
||||||
type nsSnapshotter struct {
|
|
||||||
ctdsnapshot.Snapshotter
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *nsSnapshotter) Stat(ctx context.Context, key string) (ctdsnapshot.Info, error) {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, dummyNs)
|
|
||||||
return s.Snapshotter.Stat(ctx, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *nsSnapshotter) Update(ctx context.Context, info ctdsnapshot.Info, fieldpaths ...string) (ctdsnapshot.Info, error) {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, dummyNs)
|
|
||||||
return s.Snapshotter.Update(ctx, info, fieldpaths...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *nsSnapshotter) Usage(ctx context.Context, key string) (ctdsnapshot.Usage, error) {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, dummyNs)
|
|
||||||
return s.Snapshotter.Usage(ctx, key)
|
|
||||||
}
|
|
||||||
func (s *nsSnapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, error) {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, dummyNs)
|
|
||||||
return s.Snapshotter.Mounts(ctx, key)
|
|
||||||
}
|
|
||||||
func (s *nsSnapshotter) Prepare(ctx context.Context, key, parent string, opts ...ctdsnapshot.Opt) ([]mount.Mount, error) {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, dummyNs)
|
|
||||||
return s.Snapshotter.Prepare(ctx, key, parent, opts...)
|
|
||||||
}
|
|
||||||
func (s *nsSnapshotter) View(ctx context.Context, key, parent string, opts ...ctdsnapshot.Opt) ([]mount.Mount, error) {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, dummyNs)
|
|
||||||
return s.Snapshotter.View(ctx, key, parent, opts...)
|
|
||||||
}
|
|
||||||
func (s *nsSnapshotter) Commit(ctx context.Context, name, key string, opts ...ctdsnapshot.Opt) error {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, dummyNs)
|
|
||||||
return s.Snapshotter.Commit(ctx, name, key, opts...)
|
|
||||||
}
|
|
||||||
func (s *nsSnapshotter) Remove(ctx context.Context, key string) error {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, dummyNs)
|
|
||||||
return s.Snapshotter.Remove(ctx, key)
|
|
||||||
}
|
|
||||||
func (s *nsSnapshotter) Walk(ctx context.Context, fn func(context.Context, ctdsnapshot.Info) error) error {
|
|
||||||
ctx = namespaces.WithNamespace(ctx, dummyNs)
|
|
||||||
return s.Snapshotter.Walk(ctx, fn)
|
|
||||||
}
|
|
||||||
|
|
|
@ -29,6 +29,7 @@ type Worker interface {
|
||||||
Exec(ctx context.Context, meta executor.Meta, rootFS cache.ImmutableRef, stdin io.ReadCloser, stdout, stderr io.WriteCloser) error
|
Exec(ctx context.Context, meta executor.Meta, rootFS cache.ImmutableRef, stdin io.ReadCloser, stdout, stderr io.WriteCloser) error
|
||||||
DiskUsage(ctx context.Context, opt client.DiskUsageInfo) ([]*client.UsageInfo, error)
|
DiskUsage(ctx context.Context, opt client.DiskUsageInfo) ([]*client.UsageInfo, error)
|
||||||
Exporter(name string) (exporter.Exporter, error)
|
Exporter(name string) (exporter.Exporter, error)
|
||||||
|
Prune(ctx context.Context, ch chan client.UsageInfo) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pre-defined label keys
|
// Pre-defined label keys
|
||||||
|
|
Loading…
Reference in New Issue