Merge pull request #2493 from dmcgowan/sync-lease-removal

Add sync option to lease removal
This commit is contained in:
Phil Estes 2018-07-31 11:31:55 -04:00 committed by GitHub
commit 4249f44d81
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 196 additions and 60 deletions

View File

@ -2563,6 +2563,13 @@ file {
type: TYPE_STRING type: TYPE_STRING
json_name: "id" json_name: "id"
} }
field {
name: "sync"
number: 2
label: LABEL_OPTIONAL
type: TYPE_BOOL
json_name: "sync"
}
} }
message_type { message_type {
name: "ListRequest" name: "ListRequest"

View File

@ -82,6 +82,11 @@ func (*CreateResponse) Descriptor() ([]byte, []int) { return fileDescriptorLease
type DeleteRequest struct { type DeleteRequest struct {
ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
// Sync indicates that the delete and cleanup should be done
// synchronously before returning to the caller
//
// Default is false
Sync bool `protobuf:"varint,2,opt,name=sync,proto3" json:"sync,omitempty"`
} }
func (m *DeleteRequest) Reset() { *m = DeleteRequest{} } func (m *DeleteRequest) Reset() { *m = DeleteRequest{} }
@ -404,6 +409,16 @@ func (m *DeleteRequest) MarshalTo(dAtA []byte) (int, error) {
i = encodeVarintLeases(dAtA, i, uint64(len(m.ID))) i = encodeVarintLeases(dAtA, i, uint64(len(m.ID)))
i += copy(dAtA[i:], m.ID) i += copy(dAtA[i:], m.ID)
} }
if m.Sync {
dAtA[i] = 0x10
i++
if m.Sync {
dAtA[i] = 1
} else {
dAtA[i] = 0
}
i++
}
return i, nil return i, nil
} }
@ -534,6 +549,9 @@ func (m *DeleteRequest) Size() (n int) {
if l > 0 { if l > 0 {
n += 1 + l + sovLeases(uint64(l)) n += 1 + l + sovLeases(uint64(l))
} }
if m.Sync {
n += 2
}
return n return n
} }
@ -633,6 +651,7 @@ func (this *DeleteRequest) String() string {
} }
s := strings.Join([]string{`&DeleteRequest{`, s := strings.Join([]string{`&DeleteRequest{`,
`ID:` + fmt.Sprintf("%v", this.ID) + `,`, `ID:` + fmt.Sprintf("%v", this.ID) + `,`,
`Sync:` + fmt.Sprintf("%v", this.Sync) + `,`,
`}`, `}`,
}, "") }, "")
return s return s
@ -1230,6 +1249,26 @@ func (m *DeleteRequest) Unmarshal(dAtA []byte) error {
} }
m.ID = string(dAtA[iNdEx:postIndex]) m.ID = string(dAtA[iNdEx:postIndex])
iNdEx = postIndex iNdEx = postIndex
case 2:
if wireType != 0 {
return fmt.Errorf("proto: wrong wireType = %d for field Sync", wireType)
}
var v int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowLeases
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
v |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
m.Sync = bool(v != 0)
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipLeases(dAtA[iNdEx:]) skippy, err := skipLeases(dAtA[iNdEx:])
@ -1521,37 +1560,38 @@ func init() {
} }
var fileDescriptorLeases = []byte{ var fileDescriptorLeases = []byte{
// 504 bytes of a gzipped FileDescriptorProto // 515 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0xdf, 0x8a, 0xd3, 0x40, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0xdf, 0x8a, 0xd3, 0x40,
0x14, 0xc6, 0x3b, 0xa9, 0x8d, 0xf6, 0xc4, 0x15, 0x19, 0x96, 0x25, 0x44, 0x4c, 0x4b, 0x10, 0xb6, 0x14, 0xc6, 0x3b, 0xe9, 0x36, 0x6e, 0x4f, 0x5d, 0x91, 0x61, 0x59, 0x4a, 0xc4, 0xb4, 0x04, 0xc1,
0xf8, 0x67, 0xe2, 0xd6, 0x9b, 0x75, 0x15, 0xc1, 0x6e, 0x17, 0x14, 0x82, 0x48, 0xf0, 0x62, 0xf1, 0xe2, 0x9f, 0x89, 0x5b, 0x6f, 0xd6, 0x5d, 0x11, 0xec, 0x76, 0x41, 0x21, 0x88, 0x04, 0x2f, 0x16,
0x66, 0x49, 0xdb, 0xb3, 0x31, 0x98, 0x36, 0x31, 0x33, 0x2d, 0xf4, 0xce, 0x47, 0xf0, 0x11, 0x7c, 0x6f, 0x96, 0x34, 0x3d, 0x1b, 0x83, 0x69, 0x12, 0x33, 0xd3, 0x42, 0xef, 0x7c, 0x04, 0x1f, 0xc1,
0x08, 0x1f, 0xa2, 0x97, 0x5e, 0x7a, 0xb5, 0xba, 0xb9, 0xf3, 0x2d, 0x24, 0x33, 0x09, 0xbb, 0x5b, 0x87, 0xf0, 0x21, 0x7a, 0xe9, 0xa5, 0x57, 0xab, 0x9b, 0x3b, 0xdf, 0x42, 0x32, 0x93, 0xb0, 0x7f,
0xd1, 0x56, 0xd9, 0xbb, 0x33, 0x99, 0xef, 0x3b, 0xe7, 0x77, 0x3e, 0x98, 0x40, 0x3f, 0x8c, 0xc4, 0x44, 0x5b, 0x65, 0xef, 0xce, 0xcc, 0x7c, 0xdf, 0x99, 0xdf, 0xf9, 0xc2, 0x04, 0x86, 0x41, 0x28,
0xbb, 0xe9, 0x80, 0x0d, 0x93, 0xb1, 0x3b, 0x4c, 0x26, 0x22, 0x88, 0x26, 0x98, 0x8d, 0xce, 0x97, 0xde, 0x4d, 0x47, 0xcc, 0x4f, 0x26, 0xb6, 0x9f, 0xc4, 0xc2, 0x0b, 0x63, 0xcc, 0xc6, 0xe7, 0x4b,
0x41, 0x1a, 0xb9, 0x1c, 0xb3, 0x59, 0x34, 0x44, 0xee, 0xc6, 0x18, 0x70, 0xe4, 0xee, 0x6c, 0xa7, 0x2f, 0x0d, 0x6d, 0x8e, 0xd9, 0x2c, 0xf4, 0x91, 0xdb, 0x11, 0x7a, 0x1c, 0xb9, 0x3d, 0xdb, 0x2e,
0xac, 0x58, 0x9a, 0x25, 0x22, 0xa1, 0xb7, 0xcf, 0xf4, 0xac, 0xd2, 0xb2, 0x52, 0x31, 0xdb, 0xb1, 0x2b, 0x96, 0x66, 0x89, 0x48, 0xe8, 0xed, 0x33, 0x3d, 0xab, 0xb4, 0xac, 0x54, 0xcc, 0xb6, 0x8d,
0x36, 0xc3, 0x24, 0x4c, 0xa4, 0xd2, 0x2d, 0x2a, 0x65, 0xb2, 0x6e, 0x85, 0x49, 0x12, 0xc6, 0xe8, 0xcd, 0x20, 0x09, 0x12, 0xa9, 0xb4, 0x8b, 0x4a, 0x99, 0x8c, 0x5b, 0x41, 0x92, 0x04, 0x11, 0xda,
0xca, 0xd3, 0x60, 0x7a, 0xec, 0xe2, 0x38, 0x15, 0xf3, 0xf2, 0xb2, 0xb5, 0x7c, 0x29, 0xa2, 0x31, 0x72, 0x35, 0x9a, 0x1e, 0xdb, 0x38, 0x49, 0xc5, 0xbc, 0x3c, 0xec, 0x5c, 0x3e, 0x14, 0xe1, 0x04,
0x72, 0x11, 0x8c, 0x53, 0x25, 0x70, 0x7e, 0x12, 0x68, 0x78, 0xc5, 0x04, 0xba, 0x05, 0x5a, 0x34, 0xb9, 0xf0, 0x26, 0xa9, 0x12, 0x58, 0x3f, 0x09, 0x34, 0x9c, 0xe2, 0x06, 0xba, 0x05, 0x5a, 0x38,
0x32, 0x49, 0x9b, 0x74, 0x9a, 0x3d, 0x3d, 0x3f, 0x69, 0x69, 0x2f, 0xfb, 0xbe, 0x16, 0x8d, 0xe8, 0x6e, 0x93, 0x2e, 0xe9, 0x35, 0x07, 0x7a, 0x7e, 0xd2, 0xd1, 0x5e, 0x0e, 0x5d, 0x2d, 0x1c, 0xd3,
0x3e, 0xc0, 0x30, 0xc3, 0x40, 0xe0, 0xe8, 0x28, 0x10, 0xa6, 0xd6, 0x26, 0x1d, 0xa3, 0x6b, 0x31, 0x7d, 0x00, 0x3f, 0x43, 0x4f, 0xe0, 0xf8, 0xc8, 0x13, 0x6d, 0xad, 0x4b, 0x7a, 0xad, 0xbe, 0xc1,
0xd5, 0x97, 0x55, 0x7d, 0xd9, 0x9b, 0xaa, 0x6f, 0xef, 0xda, 0xe2, 0xa4, 0x55, 0xfb, 0xf4, 0xbd, 0x54, 0x5f, 0x56, 0xf5, 0x65, 0x6f, 0xaa, 0xbe, 0x83, 0xf5, 0xc5, 0x49, 0xa7, 0xf6, 0xe9, 0x7b,
0x45, 0xfc, 0x66, 0xe9, 0x7b, 0x2e, 0xe8, 0x0b, 0xd0, 0xe3, 0x60, 0x80, 0x31, 0x37, 0xeb, 0xed, 0x87, 0xb8, 0xcd, 0xd2, 0xf7, 0x5c, 0xd0, 0x17, 0xa0, 0x47, 0xde, 0x08, 0x23, 0xde, 0xae, 0x77,
0x7a, 0xc7, 0xe8, 0x3e, 0x64, 0x7f, 0x5d, 0x95, 0x49, 0x24, 0xe6, 0x49, 0xcb, 0xc1, 0x44, 0x64, 0xeb, 0xbd, 0x56, 0xff, 0x11, 0xfb, 0xeb, 0xa8, 0x4c, 0x22, 0x31, 0x47, 0x5a, 0x0e, 0x62, 0x91,
0x73, 0xbf, 0xf4, 0x5b, 0x8f, 0xc1, 0x38, 0xf7, 0x99, 0xde, 0x84, 0xfa, 0x7b, 0x9c, 0x2b, 0x6c, 0xcd, 0xdd, 0xd2, 0x6f, 0x3c, 0x81, 0xd6, 0xb9, 0x6d, 0x7a, 0x13, 0xea, 0xef, 0x71, 0xae, 0xb0,
0xbf, 0x28, 0xe9, 0x26, 0x34, 0x66, 0x41, 0x3c, 0x45, 0x89, 0xda, 0xf4, 0xd5, 0x61, 0x4f, 0xdb, 0xdd, 0xa2, 0xa4, 0x9b, 0xd0, 0x98, 0x79, 0xd1, 0x14, 0x25, 0x6a, 0xd3, 0x55, 0x8b, 0x5d, 0x6d,
0x25, 0xce, 0x17, 0x02, 0x1b, 0xfb, 0x12, 0xc9, 0xc7, 0x0f, 0x53, 0xe4, 0xe2, 0x8f, 0x3b, 0xbf, 0x87, 0x58, 0x5f, 0x08, 0x6c, 0xec, 0x4b, 0x24, 0x17, 0x3f, 0x4c, 0x91, 0x8b, 0x3f, 0xce, 0xfc,
0x5e, 0xc2, 0xdd, 0x5d, 0x81, 0x7b, 0xa1, 0xeb, 0x65, 0x63, 0x7b, 0x70, 0xa3, 0xea, 0xcf, 0xd3, 0xfa, 0x12, 0xee, 0xce, 0x12, 0xdc, 0x0b, 0x5d, 0xaf, 0x1a, 0xdb, 0x81, 0x1b, 0x55, 0x7f, 0x9e,
0x64, 0xc2, 0x91, 0xee, 0x41, 0x43, 0xce, 0x96, 0x7e, 0xa3, 0x7b, 0x67, 0x9d, 0x30, 0x7d, 0x65, 0x26, 0x31, 0x47, 0xba, 0x0b, 0x0d, 0x79, 0xb7, 0xf4, 0xb7, 0xfa, 0x77, 0x56, 0x09, 0xd3, 0x55,
0x71, 0xb6, 0x61, 0xa3, 0x8f, 0x31, 0xae, 0xcc, 0xc0, 0xd9, 0x06, 0xc3, 0x8b, 0xb8, 0xa8, 0x64, 0x16, 0x6b, 0x0f, 0x36, 0x86, 0x18, 0xe1, 0xf2, 0x0c, 0x28, 0xac, 0xf1, 0x79, 0xec, 0x4b, 0x9e,
0x26, 0x5c, 0x3d, 0x8e, 0x62, 0x81, 0x19, 0x37, 0x49, 0xbb, 0xde, 0x69, 0xfa, 0xd5, 0xd1, 0xf1, 0x75, 0x57, 0xd6, 0xd6, 0x5d, 0x68, 0x39, 0x21, 0x17, 0x95, 0xb5, 0x0d, 0xd7, 0x8e, 0xc3, 0x48,
0xe0, 0xba, 0x12, 0x96, 0x74, 0x4f, 0x41, 0x57, 0xb3, 0xa5, 0x70, 0x5d, 0xbc, 0xd2, 0xd3, 0xfd, 0x60, 0xc6, 0xdb, 0xa4, 0x5b, 0xef, 0x35, 0xdd, 0x6a, 0x69, 0x39, 0x70, 0x5d, 0x09, 0x4b, 0xe2,
0xac, 0x81, 0x2e, 0xbf, 0x70, 0x8a, 0xa0, 0xab, 0xc5, 0xe9, 0xfd, 0x7f, 0xc9, 0xdf, 0x7a, 0xb0, 0xa7, 0xa0, 0x2b, 0x1e, 0x29, 0x5c, 0x15, 0xb9, 0xf4, 0xf4, 0x3f, 0x6b, 0xa0, 0xcb, 0x1d, 0x4e,
0xa6, 0xba, 0xe4, 0x7d, 0x05, 0xba, 0x4a, 0x64, 0xe5, 0x98, 0x0b, 0xc1, 0x59, 0x5b, 0xbf, 0x3d, 0x11, 0x74, 0x15, 0x06, 0x7d, 0xf0, 0x2f, 0xdf, 0xc4, 0x78, 0xb8, 0xa2, 0xba, 0xe4, 0x7d, 0x05,
0x82, 0x83, 0xe2, 0xe5, 0xd1, 0x23, 0xb8, 0x52, 0xe4, 0x41, 0xef, 0xae, 0xda, 0xfb, 0x2c, 0x5d, 0xba, 0x4a, 0x69, 0xe9, 0x35, 0x17, 0xc2, 0x34, 0xb6, 0x7e, 0x7b, 0x18, 0x07, 0xc5, 0x6b, 0xa4,
0xeb, 0xde, 0x5a, 0x5a, 0x05, 0xdc, 0x3b, 0x5c, 0x9c, 0xda, 0xb5, 0x6f, 0xa7, 0x76, 0xed, 0x63, 0x47, 0xb0, 0x56, 0xe4, 0x41, 0xef, 0x2d, 0x9b, 0xfb, 0x2c, 0x5d, 0xe3, 0xfe, 0x4a, 0x5a, 0x05,
0x6e, 0x93, 0x45, 0x6e, 0x93, 0xaf, 0xb9, 0x4d, 0x7e, 0xe4, 0x36, 0x79, 0xfb, 0xec, 0x3f, 0x7f, 0x3c, 0x38, 0x5c, 0x9c, 0x9a, 0xb5, 0x6f, 0xa7, 0x66, 0xed, 0x63, 0x6e, 0x92, 0x45, 0x6e, 0x92,
0x43, 0x4f, 0x54, 0x75, 0x58, 0x1b, 0xe8, 0x72, 0x99, 0x47, 0xbf, 0x02, 0x00, 0x00, 0xff, 0xff, 0xaf, 0xb9, 0x49, 0x7e, 0xe4, 0x26, 0x79, 0xfb, 0xec, 0x3f, 0x7f, 0x4d, 0x7b, 0xaa, 0x3a, 0xac,
0xad, 0x77, 0xda, 0x73, 0xd1, 0x04, 0x00, 0x00, 0x8d, 0x74, 0x39, 0xcc, 0xe3, 0x5f, 0x01, 0x00, 0x00, 0xff, 0xff, 0x14, 0x74, 0xdd, 0x12, 0xe5,
0x04, 0x00, 0x00,
} }

View File

@ -47,6 +47,12 @@ message CreateResponse {
message DeleteRequest { message DeleteRequest {
string id = 1; string id = 1;
// Sync indicates that the delete and cleanup should be done
// synchronously before returning to the caller
//
// Default is false
bool sync = 2;
} }
message ListRequest { message ListRequest {

View File

@ -163,6 +163,12 @@ var deleteCommand = cli.Command{
Usage: "delete a lease", Usage: "delete a lease",
ArgsUsage: "[flags] <lease id> ...", ArgsUsage: "[flags] <lease id> ...",
Description: "delete a lease", Description: "delete a lease",
Flags: []cli.Flag{
cli.BoolFlag{
Name: "sync",
Usage: "Synchronously remove leases and all unreferenced resources",
},
},
Action: func(context *cli.Context) error { Action: func(context *cli.Context) error {
var lids = context.Args() var lids = context.Args()
if len(lids) == 0 { if len(lids) == 0 {
@ -175,11 +181,17 @@ var deleteCommand = cli.Command{
defer cancel() defer cancel()
ls := client.LeasesService() ls := client.LeasesService()
for _, lid := range lids { sync := context.Bool("sync")
for i, lid := range lids {
var opts []leases.DeleteOpt
if sync && i == len(lids)-1 {
opts = append(opts, leases.SynchronousDelete)
}
lease := leases.Lease{ lease := leases.Lease{
ID: lid, ID: lid,
} }
if err := ls.Delete(ctx, lease); err != nil { if err := ls.Delete(ctx, lease, opts...); err != nil {
return err return err
} }
fmt.Println(lid) fmt.Println(lid)

View File

@ -24,10 +24,13 @@ import (
// Opt is used to set options on a lease // Opt is used to set options on a lease
type Opt func(*Lease) error type Opt func(*Lease) error
// DeleteOpt allows configuring a delete operation
type DeleteOpt func(context.Context, *DeleteOptions) error
// Manager is used to create, list, and remove leases // Manager is used to create, list, and remove leases
type Manager interface { type Manager interface {
Create(context.Context, ...Opt) (Lease, error) Create(context.Context, ...Opt) (Lease, error)
Delete(context.Context, Lease) error Delete(context.Context, Lease, ...DeleteOpt) error
List(context.Context, ...string) ([]Lease, error) List(context.Context, ...string) ([]Lease, error)
} }
@ -39,6 +42,19 @@ type Lease struct {
Labels map[string]string Labels map[string]string
} }
// DeleteOptions provide options on image delete
type DeleteOptions struct {
Synchronous bool
}
// SynchronousDelete is used to indicate that a lease deletion and removal of
// any unreferenced resources should occur synchronously before returning the
// result.
func SynchronousDelete(ctx context.Context, o *DeleteOptions) error {
o.Synchronous = true
return nil
}
// WithLabels sets labels on a lease // WithLabels sets labels on a lease
func WithLabels(labels map[string]string) Opt { func WithLabels(labels map[string]string) Opt {
return func(l *Lease) error { return func(l *Lease) error {

View File

@ -20,6 +20,7 @@ import (
"context" "context"
leasesapi "github.com/containerd/containerd/api/services/leases/v1" leasesapi "github.com/containerd/containerd/api/services/leases/v1"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/leases" "github.com/containerd/containerd/leases"
) )
@ -47,7 +48,7 @@ func (pm *proxyManager) Create(ctx context.Context, opts ...leases.Opt) (leases.
Labels: l.Labels, Labels: l.Labels,
}) })
if err != nil { if err != nil {
return leases.Lease{}, err return leases.Lease{}, errdefs.FromGRPC(err)
} }
return leases.Lease{ return leases.Lease{
@ -57,11 +58,19 @@ func (pm *proxyManager) Create(ctx context.Context, opts ...leases.Opt) (leases.
}, nil }, nil
} }
func (pm *proxyManager) Delete(ctx context.Context, l leases.Lease) error { func (pm *proxyManager) Delete(ctx context.Context, l leases.Lease, opts ...leases.DeleteOpt) error {
var do leases.DeleteOptions
for _, opt := range opts {
if err := opt(ctx, &do); err != nil {
return err
}
}
_, err := pm.client.Delete(ctx, &leasesapi.DeleteRequest{ _, err := pm.client.Delete(ctx, &leasesapi.DeleteRequest{
ID: l.ID, ID: l.ID,
Sync: do.Synchronous,
}) })
return err return errdefs.FromGRPC(err)
} }
func (pm *proxyManager) List(ctx context.Context, filters ...string) ([]leases.Lease, error) { func (pm *proxyManager) List(ctx context.Context, filters ...string) ([]leases.Lease, error) {
@ -69,7 +78,7 @@ func (pm *proxyManager) List(ctx context.Context, filters ...string) ([]leases.L
Filters: filters, Filters: filters,
}) })
if err != nil { if err != nil {
return nil, err return nil, errdefs.FromGRPC(err)
} }
l := make([]leases.Lease, len(resp.Leases)) l := make([]leases.Lease, len(resp.Leases))
for i := range resp.Leases { for i := range resp.Leases {

View File

@ -94,7 +94,7 @@ func (lm *LeaseManager) Create(ctx context.Context, opts ...leases.Opt) (leases.
} }
// Delete delets the lease with the provided lease ID // Delete delets the lease with the provided lease ID
func (lm *LeaseManager) Delete(ctx context.Context, lease leases.Lease) error { func (lm *LeaseManager) Delete(ctx context.Context, lease leases.Lease, _ ...leases.DeleteOpt) error {
namespace, err := namespaces.NamespaceRequired(ctx) namespace, err := namespaces.NamespaceRequired(ctx)
if err != nil { if err != nil {
return err return err
@ -102,9 +102,12 @@ func (lm *LeaseManager) Delete(ctx context.Context, lease leases.Lease) error {
topbkt := getBucket(lm.tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases) topbkt := getBucket(lm.tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases)
if topbkt == nil { if topbkt == nil {
return nil return errors.Wrapf(errdefs.ErrNotFound, "lease %q", lease.ID)
} }
if err := topbkt.DeleteBucket([]byte(lease.ID)); err != nil && err != bolt.ErrBucketNotFound { if err := topbkt.DeleteBucket([]byte(lease.ID)); err != nil {
if err == bolt.ErrBucketNotFound {
err = errors.Wrapf(errdefs.ErrNotFound, "lease %q", lease.ID)
}
return err return err
} }
return nil return nil

View File

@ -30,15 +30,17 @@ func TestLeases(t *testing.T) {
defer cancel() defer cancel()
testCases := []struct { testCases := []struct {
ID string ID string
Cause error CreateErr error
DeleteErr error
}{ }{
{ {
ID: "tx1", ID: "tx1",
}, },
{ {
ID: "tx1", ID: "tx1",
Cause: errdefs.ErrAlreadyExists, CreateErr: errdefs.ErrAlreadyExists,
DeleteErr: errdefs.ErrNotFound,
}, },
{ {
ID: "tx2", ID: "tx2",
@ -51,7 +53,7 @@ func TestLeases(t *testing.T) {
if err := db.Update(func(tx *bolt.Tx) error { if err := db.Update(func(tx *bolt.Tx) error {
lease, err := NewLeaseManager(tx).Create(ctx, leases.WithID(tc.ID)) lease, err := NewLeaseManager(tx).Create(ctx, leases.WithID(tc.ID))
if err != nil { if err != nil {
if tc.Cause != nil && errors.Cause(err) == tc.Cause { if tc.CreateErr != nil && errors.Cause(err) == tc.CreateErr {
return nil return nil
} }
return err return err
@ -91,7 +93,10 @@ func TestLeases(t *testing.T) {
ID: tc.ID, ID: tc.ID,
}) })
}); err != nil { }); err != nil {
t.Fatal(err) if tc.DeleteErr == nil && errors.Cause(err) != tc.DeleteErr {
t.Fatal(err)
}
} }
} }
@ -248,12 +253,14 @@ func TestLeasesList(t *testing.T) {
t.Fatal(err) t.Fatal(err)
} }
// try it again, get nil // try it again, get not found
if err := db.Update(func(tx *bolt.Tx) error { if err := db.Update(func(tx *bolt.Tx) error {
lm := NewLeaseManager(tx) lm := NewLeaseManager(tx)
return lm.Delete(ctx, lease) return lm.Delete(ctx, lease)
}); err != nil { }); err == nil {
t.Fatalf("unexpected error %v", err) t.Fatalf("expected error deleting non-existent lease")
} else if !errdefs.IsNotFound(err) {
t.Fatalf("unexpected error: %s", err)
} }
} }
} }

View File

@ -20,6 +20,7 @@ import (
"context" "context"
"github.com/boltdb/bolt" "github.com/boltdb/bolt"
"github.com/containerd/containerd/gc"
"github.com/containerd/containerd/leases" "github.com/containerd/containerd/leases"
"github.com/containerd/containerd/metadata" "github.com/containerd/containerd/metadata"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
@ -38,13 +39,25 @@ func init() {
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &local{db: m.(*metadata.DB)}, nil g, err := ic.Get(plugin.GCPlugin)
if err != nil {
return nil, err
}
return &local{
db: m.(*metadata.DB),
gc: g.(gcScheduler),
}, nil
}, },
}) })
} }
type gcScheduler interface {
ScheduleAndWait(context.Context) (gc.Stats, error)
}
type local struct { type local struct {
db *metadata.DB db *metadata.DB
gc gcScheduler
} }
func (l *local) Create(ctx context.Context, opts ...leases.Opt) (leases.Lease, error) { func (l *local) Create(ctx context.Context, opts ...leases.Opt) (leases.Lease, error) {
@ -59,10 +72,28 @@ func (l *local) Create(ctx context.Context, opts ...leases.Opt) (leases.Lease, e
return lease, nil return lease, nil
} }
func (l *local) Delete(ctx context.Context, lease leases.Lease) error { func (l *local) Delete(ctx context.Context, lease leases.Lease, opts ...leases.DeleteOpt) error {
return l.db.Update(func(tx *bolt.Tx) error { var do leases.DeleteOptions
for _, opt := range opts {
if err := opt(ctx, &do); err != nil {
return err
}
}
if err := l.db.Update(func(tx *bolt.Tx) error {
return metadata.NewLeaseManager(tx).Delete(ctx, lease) return metadata.NewLeaseManager(tx).Delete(ctx, lease)
}) }); err != nil {
return err
}
if do.Synchronous {
if _, err := l.gc.ScheduleAndWait(ctx); err != nil {
return err
}
}
return nil
} }
func (l *local) List(ctx context.Context, filters ...string) ([]leases.Lease, error) { func (l *local) List(ctx context.Context, filters ...string) ([]leases.Lease, error) {

View File

@ -22,6 +22,7 @@ import (
"google.golang.org/grpc" "google.golang.org/grpc"
api "github.com/containerd/containerd/api/services/leases/v1" api "github.com/containerd/containerd/api/services/leases/v1"
"github.com/containerd/containerd/errdefs"
"github.com/containerd/containerd/leases" "github.com/containerd/containerd/leases"
"github.com/containerd/containerd/plugin" "github.com/containerd/containerd/plugin"
"github.com/containerd/containerd/services" "github.com/containerd/containerd/services"
@ -75,7 +76,7 @@ func (s *service) Create(ctx context.Context, r *api.CreateRequest) (*api.Create
l, err := s.lm.Create(ctx, opts...) l, err := s.lm.Create(ctx, opts...)
if err != nil { if err != nil {
return nil, err return nil, errdefs.ToGRPC(err)
} }
return &api.CreateResponse{ return &api.CreateResponse{
@ -84,10 +85,14 @@ func (s *service) Create(ctx context.Context, r *api.CreateRequest) (*api.Create
} }
func (s *service) Delete(ctx context.Context, r *api.DeleteRequest) (*ptypes.Empty, error) { func (s *service) Delete(ctx context.Context, r *api.DeleteRequest) (*ptypes.Empty, error) {
var opts []leases.DeleteOpt
if r.Sync {
opts = append(opts, leases.SynchronousDelete)
}
if err := s.lm.Delete(ctx, leases.Lease{ if err := s.lm.Delete(ctx, leases.Lease{
ID: r.ID, ID: r.ID,
}); err != nil { }, opts...); err != nil {
return nil, err return nil, errdefs.ToGRPC(err)
} }
return &ptypes.Empty{}, nil return &ptypes.Empty{}, nil
} }
@ -95,7 +100,7 @@ func (s *service) Delete(ctx context.Context, r *api.DeleteRequest) (*ptypes.Emp
func (s *service) List(ctx context.Context, r *api.ListRequest) (*api.ListResponse, error) { func (s *service) List(ctx context.Context, r *api.ListRequest) (*api.ListResponse, error) {
l, err := s.lm.List(ctx, r.Filters...) l, err := s.lm.List(ctx, r.Filters...)
if err != nil { if err != nil {
return nil, err return nil, errdefs.ToGRPC(err)
} }
apileases := make([]*api.Lease, len(l)) apileases := make([]*api.Lease, len(l))