1/* 2 Copyright The containerd Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15*/ 16 17package leases 18 19import ( 20 "context" 21 22 "google.golang.org/grpc" 23 24 api "github.com/containerd/containerd/api/services/leases/v1" 25 "github.com/containerd/containerd/errdefs" 26 "github.com/containerd/containerd/leases" 27 "github.com/containerd/containerd/plugin" 28 "github.com/containerd/containerd/services" 29 ptypes "github.com/gogo/protobuf/types" 30 "github.com/pkg/errors" 31) 32 33func init() { 34 plugin.Register(&plugin.Registration{ 35 Type: plugin.GRPCPlugin, 36 ID: "leases", 37 Requires: []plugin.Type{ 38 plugin.ServicePlugin, 39 }, 40 InitFn: func(ic *plugin.InitContext) (interface{}, error) { 41 plugins, err := ic.GetByType(plugin.ServicePlugin) 42 if err != nil { 43 return nil, err 44 } 45 p, ok := plugins[services.LeasesService] 46 if !ok { 47 return nil, errors.New("leases service not found") 48 } 49 i, err := p.Instance() 50 if err != nil { 51 return nil, err 52 } 53 return &service{lm: i.(leases.Manager)}, nil 54 }, 55 }) 56} 57 58type service struct { 59 lm leases.Manager 60} 61 62func (s *service) Register(server *grpc.Server) error { 63 api.RegisterLeasesServer(server, s) 64 return nil 65} 66 67func (s *service) Create(ctx context.Context, r *api.CreateRequest) (*api.CreateResponse, error) { 68 opts := []leases.Opt{ 69 leases.WithLabels(r.Labels), 70 } 71 if r.ID == "" { 72 opts = append(opts, leases.WithRandomID()) 73 } else { 74 opts = append(opts, leases.WithID(r.ID)) 75 } 76 77 l, err := s.lm.Create(ctx, opts...) 78 if err != nil { 79 return nil, errdefs.ToGRPC(err) 80 } 81 82 return &api.CreateResponse{ 83 Lease: leaseToGRPC(l), 84 }, nil 85} 86 87func (s *service) Delete(ctx context.Context, r *api.DeleteRequest) (*ptypes.Empty, error) { 88 var opts []leases.DeleteOpt 89 if r.Sync { 90 opts = append(opts, leases.SynchronousDelete) 91 } 92 if err := s.lm.Delete(ctx, leases.Lease{ 93 ID: r.ID, 94 }, opts...); err != nil { 95 return nil, errdefs.ToGRPC(err) 96 } 97 return &ptypes.Empty{}, nil 98} 99 100func (s *service) List(ctx context.Context, r *api.ListRequest) (*api.ListResponse, error) { 101 l, err := s.lm.List(ctx, r.Filters...) 102 if err != nil { 103 return nil, errdefs.ToGRPC(err) 104 } 105 106 apileases := make([]*api.Lease, len(l)) 107 for i := range l { 108 apileases[i] = leaseToGRPC(l[i]) 109 } 110 111 return &api.ListResponse{ 112 Leases: apileases, 113 }, nil 114} 115 116func (s *service) AddResource(ctx context.Context, r *api.AddResourceRequest) (*ptypes.Empty, error) { 117 lease := leases.Lease{ 118 ID: r.ID, 119 } 120 121 if err := s.lm.AddResource(ctx, lease, leases.Resource{ 122 ID: r.Resource.ID, 123 Type: r.Resource.Type, 124 }); err != nil { 125 return nil, errdefs.ToGRPC(err) 126 } 127 return &ptypes.Empty{}, nil 128} 129 130func (s *service) DeleteResource(ctx context.Context, r *api.DeleteResourceRequest) (*ptypes.Empty, error) { 131 lease := leases.Lease{ 132 ID: r.ID, 133 } 134 135 if err := s.lm.DeleteResource(ctx, lease, leases.Resource{ 136 ID: r.Resource.ID, 137 Type: r.Resource.Type, 138 }); err != nil { 139 return nil, errdefs.ToGRPC(err) 140 } 141 return &ptypes.Empty{}, nil 142} 143 144func (s *service) ListResources(ctx context.Context, r *api.ListResourcesRequest) (*api.ListResourcesResponse, error) { 145 lease := leases.Lease{ 146 ID: r.ID, 147 } 148 149 rs, err := s.lm.ListResources(ctx, lease) 150 if err != nil { 151 return nil, errdefs.ToGRPC(err) 152 } 153 154 apiResources := make([]api.Resource, 0, len(rs)) 155 for _, i := range rs { 156 apiResources = append(apiResources, api.Resource{ 157 ID: i.ID, 158 Type: i.Type, 159 }) 160 } 161 return &api.ListResourcesResponse{ 162 Resources: apiResources, 163 }, nil 164} 165 166func leaseToGRPC(l leases.Lease) *api.Lease { 167 return &api.Lease{ 168 ID: l.ID, 169 Labels: l.Labels, 170 CreatedAt: l.CreatedAt, 171 } 172} 173