Signed-off-by: Brian Goff <cpuguy83@gmail.com>
Brian Goff authored on 2017/11/11 05:44:10... | ... |
@@ -4,7 +4,7 @@ TOMLV_COMMIT=9baf8a8a9f2ed20a8e54160840c492f937eeaf9a |
4 | 4 |
|
5 | 5 |
# When updating RUNC_COMMIT, also update runc in vendor.conf accordingly |
6 | 6 |
RUNC_COMMIT=0351df1c5a66838d0c392b4ac4cf9450de844e2d |
7 |
-CONTAINERD_COMMIT=992280e8e265f491f7a624ab82f3e238be086e49 |
|
7 |
+CONTAINERD_COMMIT=v1.0.0-beta.3 |
|
8 | 8 |
TINI_COMMIT=949e6facb77383876aeff8a6944dde66b3089574 |
9 | 9 |
LIBNETWORK_COMMIT=7b2b1feb1de4817d522cc372af149ff48d25028e |
10 | 10 |
VNDR_COMMIT=a6e196d8b4b0cbbdc29aebdb20c59ac6926bb384 |
... | ... |
@@ -31,8 +31,8 @@ type rpcUser struct { |
31 | 31 |
|
32 | 32 |
func (u rpcUser) Apply(r Remote) error { |
33 | 33 |
if remote, ok := r.(*remote); ok { |
34 |
- remote.GRPC.Uid = u.uid |
|
35 |
- remote.GRPC.Gid = u.gid |
|
34 |
+ remote.GRPC.UID = u.uid |
|
35 |
+ remote.GRPC.GID = u.gid |
|
36 | 36 |
return nil |
37 | 37 |
} |
38 | 38 |
return fmt.Errorf("WithRemoteAddr option not supported for this remote") |
... | ... |
@@ -103,7 +103,7 @@ github.com/googleapis/gax-go da06d194a00e19ce00d9011a13931c3f6f6887c7 |
103 | 103 |
google.golang.org/genproto d80a6e20e776b0b17a324d0ba1ab50a39c8e8944 |
104 | 104 |
|
105 | 105 |
# containerd |
106 |
-github.com/containerd/containerd 992280e8e265f491f7a624ab82f3e238be086e49 |
|
106 |
+github.com/containerd/containerd v1.0.0-beta.3 |
|
107 | 107 |
github.com/containerd/fifo fbfb6a11ec671efbe94ad1c12c2e98773f19e1e6 |
108 | 108 |
github.com/containerd/continuity 35d55c5e8dd23b32037d56cf97174aff3efdfa83 |
109 | 109 |
github.com/containerd/cgroups f7dd103d3e4e696aa67152f6b4ddd1779a3455a9 |
... | ... |
@@ -1,4 +1,4 @@ |
1 |
-Attribution-ShareAlike 4.0 International |
|
1 |
+Attribution 4.0 International |
|
2 | 2 |
|
3 | 3 |
======================================================================= |
4 | 4 |
|
... | ... |
@@ -54,18 +54,16 @@ exhaustive, and do not form part of our licenses. |
54 | 54 |
|
55 | 55 |
======================================================================= |
56 | 56 |
|
57 |
-Creative Commons Attribution-ShareAlike 4.0 International Public |
|
58 |
-License |
|
57 |
+Creative Commons Attribution 4.0 International Public License |
|
59 | 58 |
|
60 | 59 |
By exercising the Licensed Rights (defined below), You accept and agree |
61 | 60 |
to be bound by the terms and conditions of this Creative Commons |
62 |
-Attribution-ShareAlike 4.0 International Public License ("Public |
|
63 |
-License"). To the extent this Public License may be interpreted as a |
|
64 |
-contract, You are granted the Licensed Rights in consideration of Your |
|
65 |
-acceptance of these terms and conditions, and the Licensor grants You |
|
66 |
-such rights in consideration of benefits the Licensor receives from |
|
67 |
-making the Licensed Material available under these terms and |
|
68 |
-conditions. |
|
61 |
+Attribution 4.0 International Public License ("Public License"). To the |
|
62 |
+extent this Public License may be interpreted as a contract, You are |
|
63 |
+granted the Licensed Rights in consideration of Your acceptance of |
|
64 |
+these terms and conditions, and the Licensor grants You such rights in |
|
65 |
+consideration of benefits the Licensor receives from making the |
|
66 |
+Licensed Material available under these terms and conditions. |
|
69 | 67 |
|
70 | 68 |
|
71 | 69 |
Section 1 -- Definitions. |
... | ... |
@@ -84,11 +82,7 @@ Section 1 -- Definitions. |
84 | 84 |
and Similar Rights in Your contributions to Adapted Material in |
85 | 85 |
accordance with the terms and conditions of this Public License. |
86 | 86 |
|
87 |
- c. BY-SA Compatible License means a license listed at |
|
88 |
- creativecommons.org/compatiblelicenses, approved by Creative |
|
89 |
- Commons as essentially the equivalent of this Public License. |
|
90 |
- |
|
91 |
- d. Copyright and Similar Rights means copyright and/or similar rights |
|
87 |
+ c. Copyright and Similar Rights means copyright and/or similar rights |
|
92 | 88 |
closely related to copyright including, without limitation, |
93 | 89 |
performance, broadcast, sound recording, and Sui Generis Database |
94 | 90 |
Rights, without regard to how the rights are labeled or |
... | ... |
@@ -96,33 +90,29 @@ Section 1 -- Definitions. |
96 | 96 |
specified in Section 2(b)(1)-(2) are not Copyright and Similar |
97 | 97 |
Rights. |
98 | 98 |
|
99 |
- e. Effective Technological Measures means those measures that, in the |
|
99 |
+ d. Effective Technological Measures means those measures that, in the |
|
100 | 100 |
absence of proper authority, may not be circumvented under laws |
101 | 101 |
fulfilling obligations under Article 11 of the WIPO Copyright |
102 | 102 |
Treaty adopted on December 20, 1996, and/or similar international |
103 | 103 |
agreements. |
104 | 104 |
|
105 |
- f. Exceptions and Limitations means fair use, fair dealing, and/or |
|
105 |
+ e. Exceptions and Limitations means fair use, fair dealing, and/or |
|
106 | 106 |
any other exception or limitation to Copyright and Similar Rights |
107 | 107 |
that applies to Your use of the Licensed Material. |
108 | 108 |
|
109 |
- g. License Elements means the license attributes listed in the name |
|
110 |
- of a Creative Commons Public License. The License Elements of this |
|
111 |
- Public License are Attribution and ShareAlike. |
|
112 |
- |
|
113 |
- h. Licensed Material means the artistic or literary work, database, |
|
109 |
+ f. Licensed Material means the artistic or literary work, database, |
|
114 | 110 |
or other material to which the Licensor applied this Public |
115 | 111 |
License. |
116 | 112 |
|
117 |
- i. Licensed Rights means the rights granted to You subject to the |
|
113 |
+ g. Licensed Rights means the rights granted to You subject to the |
|
118 | 114 |
terms and conditions of this Public License, which are limited to |
119 | 115 |
all Copyright and Similar Rights that apply to Your use of the |
120 | 116 |
Licensed Material and that the Licensor has authority to license. |
121 | 117 |
|
122 |
- j. Licensor means the individual(s) or entity(ies) granting rights |
|
118 |
+ h. Licensor means the individual(s) or entity(ies) granting rights |
|
123 | 119 |
under this Public License. |
124 | 120 |
|
125 |
- k. Share means to provide material to the public by any means or |
|
121 |
+ i. Share means to provide material to the public by any means or |
|
126 | 122 |
process that requires permission under the Licensed Rights, such |
127 | 123 |
as reproduction, public display, public performance, distribution, |
128 | 124 |
dissemination, communication, or importation, and to make material |
... | ... |
@@ -130,13 +120,13 @@ Section 1 -- Definitions. |
130 | 130 |
public may access the material from a place and at a time |
131 | 131 |
individually chosen by them. |
132 | 132 |
|
133 |
- l. Sui Generis Database Rights means rights other than copyright |
|
133 |
+ j. Sui Generis Database Rights means rights other than copyright |
|
134 | 134 |
resulting from Directive 96/9/EC of the European Parliament and of |
135 | 135 |
the Council of 11 March 1996 on the legal protection of databases, |
136 | 136 |
as amended and/or succeeded, as well as other essentially |
137 | 137 |
equivalent rights anywhere in the world. |
138 | 138 |
|
139 |
- m. You means the individual or entity exercising the Licensed Rights |
|
139 |
+ k. You means the individual or entity exercising the Licensed Rights |
|
140 | 140 |
under this Public License. Your has a corresponding meaning. |
141 | 141 |
|
142 | 142 |
|
... | ... |
@@ -182,13 +172,7 @@ Section 2 -- Scope. |
182 | 182 |
Licensed Rights under the terms and conditions of this |
183 | 183 |
Public License. |
184 | 184 |
|
185 |
- b. Additional offer from the Licensor -- Adapted Material. |
|
186 |
- Every recipient of Adapted Material from You |
|
187 |
- automatically receives an offer from the Licensor to |
|
188 |
- exercise the Licensed Rights in the Adapted Material |
|
189 |
- under the conditions of the Adapter's License You apply. |
|
190 |
- |
|
191 |
- c. No downstream restrictions. You may not offer or impose |
|
185 |
+ b. No downstream restrictions. You may not offer or impose |
|
192 | 186 |
any additional or different terms or conditions on, or |
193 | 187 |
apply any Effective Technological Measures to, the |
194 | 188 |
Licensed Material if doing so restricts exercise of the |
... | ... |
@@ -270,24 +254,9 @@ following conditions. |
270 | 270 |
information required by Section 3(a)(1)(A) to the extent |
271 | 271 |
reasonably practicable. |
272 | 272 |
|
273 |
- b. ShareAlike. |
|
274 |
- |
|
275 |
- In addition to the conditions in Section 3(a), if You Share |
|
276 |
- Adapted Material You produce, the following conditions also apply. |
|
277 |
- |
|
278 |
- 1. The Adapter's License You apply must be a Creative Commons |
|
279 |
- license with the same License Elements, this version or |
|
280 |
- later, or a BY-SA Compatible License. |
|
281 |
- |
|
282 |
- 2. You must include the text of, or the URI or hyperlink to, the |
|
283 |
- Adapter's License You apply. You may satisfy this condition |
|
284 |
- in any reasonable manner based on the medium, means, and |
|
285 |
- context in which You Share Adapted Material. |
|
286 |
- |
|
287 |
- 3. You may not offer or impose any additional or different terms |
|
288 |
- or conditions on, or apply any Effective Technological |
|
289 |
- Measures to, Adapted Material that restrict exercise of the |
|
290 |
- rights granted under the Adapter's License You apply. |
|
273 |
+ 4. If You Share Adapted Material You produce, the Adapter's |
|
274 |
+ License You apply must not prevent recipients of the Adapted |
|
275 |
+ Material from complying with this Public License. |
|
291 | 276 |
|
292 | 277 |
|
293 | 278 |
Section 4 -- Sui Generis Database Rights. |
... | ... |
@@ -302,9 +271,8 @@ apply to Your use of the Licensed Material: |
302 | 302 |
b. if You include all or a substantial portion of the database |
303 | 303 |
contents in a database in which You have Sui Generis Database |
304 | 304 |
Rights, then the database in which You have Sui Generis Database |
305 |
- Rights (but not its individual contents) is Adapted Material, |
|
305 |
+ Rights (but not its individual contents) is Adapted Material; and |
|
306 | 306 |
|
307 |
- including for purposes of Section 3(b); and |
|
308 | 307 |
c. You must comply with the conditions in Section 3(a) if You Share |
309 | 308 |
all or a substantial portion of the contents of the database. |
310 | 309 |
|
... | ... |
@@ -407,11 +375,13 @@ Section 8 -- Interpretation. |
407 | 407 |
|
408 | 408 |
======================================================================= |
409 | 409 |
|
410 |
-Creative Commons is not a party to its public licenses. |
|
411 |
-Notwithstanding, Creative Commons may elect to apply one of its public |
|
412 |
-licenses to material it publishes and in those instances will be |
|
413 |
-considered the "Licensor." Except for the limited purpose of indicating |
|
414 |
-that material is shared under a Creative Commons public license or as |
|
410 |
+Creative Commons is not a party to its public |
|
411 |
+licenses. Notwithstanding, Creative Commons may elect to apply one of |
|
412 |
+its public licenses to material it publishes and in those instances |
|
413 |
+will be considered the “Licensor.” The text of the Creative Commons |
|
414 |
+public licenses is dedicated to the public domain under the CC0 Public |
|
415 |
+Domain Dedication. Except for the limited purpose of indicating that |
|
416 |
+material is shared under a Creative Commons public license or as |
|
415 | 417 |
otherwise permitted by the Creative Commons policies published at |
416 | 418 |
creativecommons.org/policies, Creative Commons does not authorize the |
417 | 419 |
use of the trademark "Creative Commons" or any other trademark or logo |
... | ... |
@@ -419,7 +389,7 @@ of Creative Commons without its prior written consent including, |
419 | 419 |
without limitation, in connection with any unauthorized modifications |
420 | 420 |
to any of its public licenses or any other arrangements, |
421 | 421 |
understandings, or agreements concerning use of licensed material. For |
422 |
-the avoidance of doubt, this paragraph does not form part of the public |
|
423 |
-licenses. |
|
422 |
+the avoidance of doubt, this paragraph does not form part of the |
|
423 |
+public licenses. |
|
424 | 424 |
|
425 | 425 |
Creative Commons may be contacted at creativecommons.org. |
... | ... |
@@ -198,11 +198,10 @@ For sync communication we have a community slack with a #containerd channel that |
198 | 198 |
|
199 | 199 |
__If you are reporting a security issue, please reach out discreetly at security@containerd.io__. |
200 | 200 |
|
201 |
-## Copyright and license |
|
202 |
- |
|
203 |
-Copyright ©2016-2017 Docker, Inc. All rights reserved, except as follows. Code |
|
204 |
-is released under the Apache 2.0 license. The README.md file, and files in the |
|
205 |
-"docs" folder are licensed under the Creative Commons Attribution 4.0 |
|
206 |
-International License under the terms and conditions set forth in the file |
|
207 |
-"LICENSE.docs". You may obtain a duplicate copy of the same license, titled |
|
208 |
-CC-BY-SA-4.0, at http://creativecommons.org/licenses/by/4.0/. |
|
201 |
+## Licenses |
|
202 |
+ |
|
203 |
+The containerd codebase is released under the [Apache 2.0 license](LICENSE.code). |
|
204 |
+The README.md file, and files in the "docs" folder are licensed under the |
|
205 |
+Creative Commons Attribution 4.0 International License under the terms and |
|
206 |
+conditions set forth in the file "[LICENSE.docs](LICENSE.docs)". You may obtain a duplicate |
|
207 |
+copy of the same license, titled CC-BY-4.0, at http://creativecommons.org/licenses/by/4.0/. |
0 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,1573 @@ |
0 |
+// Code generated by protoc-gen-gogo. |
|
1 |
+// source: github.com/containerd/containerd/api/services/leases/v1/leases.proto |
|
2 |
+// DO NOT EDIT! |
|
3 |
+ |
|
4 |
+/* |
|
5 |
+ Package leases is a generated protocol buffer package. |
|
6 |
+ |
|
7 |
+ It is generated from these files: |
|
8 |
+ github.com/containerd/containerd/api/services/leases/v1/leases.proto |
|
9 |
+ |
|
10 |
+ It has these top-level messages: |
|
11 |
+ Lease |
|
12 |
+ CreateRequest |
|
13 |
+ CreateResponse |
|
14 |
+ DeleteRequest |
|
15 |
+ ListRequest |
|
16 |
+ ListResponse |
|
17 |
+*/ |
|
18 |
+package leases |
|
19 |
+ |
|
20 |
+import proto "github.com/gogo/protobuf/proto" |
|
21 |
+import fmt "fmt" |
|
22 |
+import math "math" |
|
23 |
+import _ "github.com/gogo/protobuf/gogoproto" |
|
24 |
+import google_protobuf1 "github.com/golang/protobuf/ptypes/empty" |
|
25 |
+import _ "github.com/gogo/protobuf/types" |
|
26 |
+ |
|
27 |
+import time "time" |
|
28 |
+ |
|
29 |
+import ( |
|
30 |
+ context "golang.org/x/net/context" |
|
31 |
+ grpc "google.golang.org/grpc" |
|
32 |
+) |
|
33 |
+ |
|
34 |
+import github_com_gogo_protobuf_types "github.com/gogo/protobuf/types" |
|
35 |
+ |
|
36 |
+import strings "strings" |
|
37 |
+import reflect "reflect" |
|
38 |
+import github_com_gogo_protobuf_sortkeys "github.com/gogo/protobuf/sortkeys" |
|
39 |
+ |
|
40 |
+import io "io" |
|
41 |
+ |
|
42 |
+// Reference imports to suppress errors if they are not otherwise used. |
|
43 |
+var _ = proto.Marshal |
|
44 |
+var _ = fmt.Errorf |
|
45 |
+var _ = math.Inf |
|
46 |
+var _ = time.Kitchen |
|
47 |
+ |
|
48 |
+// This is a compile-time assertion to ensure that this generated file |
|
49 |
+// is compatible with the proto package it is being compiled against. |
|
50 |
+// A compilation error at this line likely means your copy of the |
|
51 |
+// proto package needs to be updated. |
|
52 |
+const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package |
|
53 |
+ |
|
54 |
+// Lease is an object which retains resources while it exists. |
|
55 |
+type Lease struct { |
|
56 |
+ ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` |
|
57 |
+ CreatedAt time.Time `protobuf:"bytes,2,opt,name=created_at,json=createdAt,stdtime" json:"created_at"` |
|
58 |
+ Labels map[string]string `protobuf:"bytes,3,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` |
|
59 |
+} |
|
60 |
+ |
|
61 |
+func (m *Lease) Reset() { *m = Lease{} } |
|
62 |
+func (*Lease) ProtoMessage() {} |
|
63 |
+func (*Lease) Descriptor() ([]byte, []int) { return fileDescriptorLeases, []int{0} } |
|
64 |
+ |
|
65 |
+type CreateRequest struct { |
|
66 |
+ // ID is used to identity the lease, when the id is not set the service |
|
67 |
+ // generates a random identifier for the lease. |
|
68 |
+ ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` |
|
69 |
+ Labels map[string]string `protobuf:"bytes,3,rep,name=labels" json:"labels,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"` |
|
70 |
+} |
|
71 |
+ |
|
72 |
+func (m *CreateRequest) Reset() { *m = CreateRequest{} } |
|
73 |
+func (*CreateRequest) ProtoMessage() {} |
|
74 |
+func (*CreateRequest) Descriptor() ([]byte, []int) { return fileDescriptorLeases, []int{1} } |
|
75 |
+ |
|
76 |
+type CreateResponse struct { |
|
77 |
+ Lease *Lease `protobuf:"bytes,1,opt,name=lease" json:"lease,omitempty"` |
|
78 |
+} |
|
79 |
+ |
|
80 |
+func (m *CreateResponse) Reset() { *m = CreateResponse{} } |
|
81 |
+func (*CreateResponse) ProtoMessage() {} |
|
82 |
+func (*CreateResponse) Descriptor() ([]byte, []int) { return fileDescriptorLeases, []int{2} } |
|
83 |
+ |
|
84 |
+type DeleteRequest struct { |
|
85 |
+ ID string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` |
|
86 |
+} |
|
87 |
+ |
|
88 |
+func (m *DeleteRequest) Reset() { *m = DeleteRequest{} } |
|
89 |
+func (*DeleteRequest) ProtoMessage() {} |
|
90 |
+func (*DeleteRequest) Descriptor() ([]byte, []int) { return fileDescriptorLeases, []int{3} } |
|
91 |
+ |
|
92 |
+type ListRequest struct { |
|
93 |
+ Filters []string `protobuf:"bytes,1,rep,name=filters" json:"filters,omitempty"` |
|
94 |
+} |
|
95 |
+ |
|
96 |
+func (m *ListRequest) Reset() { *m = ListRequest{} } |
|
97 |
+func (*ListRequest) ProtoMessage() {} |
|
98 |
+func (*ListRequest) Descriptor() ([]byte, []int) { return fileDescriptorLeases, []int{4} } |
|
99 |
+ |
|
100 |
+type ListResponse struct { |
|
101 |
+ Leases []*Lease `protobuf:"bytes,1,rep,name=leases" json:"leases,omitempty"` |
|
102 |
+} |
|
103 |
+ |
|
104 |
+func (m *ListResponse) Reset() { *m = ListResponse{} } |
|
105 |
+func (*ListResponse) ProtoMessage() {} |
|
106 |
+func (*ListResponse) Descriptor() ([]byte, []int) { return fileDescriptorLeases, []int{5} } |
|
107 |
+ |
|
108 |
+func init() { |
|
109 |
+ proto.RegisterType((*Lease)(nil), "containerd.services.leases.v1.Lease") |
|
110 |
+ proto.RegisterType((*CreateRequest)(nil), "containerd.services.leases.v1.CreateRequest") |
|
111 |
+ proto.RegisterType((*CreateResponse)(nil), "containerd.services.leases.v1.CreateResponse") |
|
112 |
+ proto.RegisterType((*DeleteRequest)(nil), "containerd.services.leases.v1.DeleteRequest") |
|
113 |
+ proto.RegisterType((*ListRequest)(nil), "containerd.services.leases.v1.ListRequest") |
|
114 |
+ proto.RegisterType((*ListResponse)(nil), "containerd.services.leases.v1.ListResponse") |
|
115 |
+} |
|
116 |
+ |
|
117 |
+// Reference imports to suppress errors if they are not otherwise used. |
|
118 |
+var _ context.Context |
|
119 |
+var _ grpc.ClientConn |
|
120 |
+ |
|
121 |
+// This is a compile-time assertion to ensure that this generated file |
|
122 |
+// is compatible with the grpc package it is being compiled against. |
|
123 |
+const _ = grpc.SupportPackageIsVersion4 |
|
124 |
+ |
|
125 |
+// Client API for Leases service |
|
126 |
+ |
|
127 |
+type LeasesClient interface { |
|
128 |
+ // Create creates a new lease for managing changes to metadata. A lease |
|
129 |
+ // can be used to protect objects from being removed. |
|
130 |
+ Create(ctx context.Context, in *CreateRequest, opts ...grpc.CallOption) (*CreateResponse, error) |
|
131 |
+ // Delete deletes the lease and makes any unreferenced objects created |
|
132 |
+ // during the lease eligible for garbage collection if not referenced |
|
133 |
+ // or retained by other resources during the lease. |
|
134 |
+ Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*google_protobuf1.Empty, error) |
|
135 |
+ // ListTransactions lists all active leases, returning the full list of |
|
136 |
+ // leases and optionally including the referenced resources. |
|
137 |
+ List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) |
|
138 |
+} |
|
139 |
+ |
|
140 |
+type leasesClient struct { |
|
141 |
+ cc *grpc.ClientConn |
|
142 |
+} |
|
143 |
+ |
|
144 |
+func NewLeasesClient(cc *grpc.ClientConn) LeasesClient { |
|
145 |
+ return &leasesClient{cc} |
|
146 |
+} |
|
147 |
+ |
|
148 |
+func (c *leasesClient) Create(ctx context.Context, in *CreateRequest, opts ...grpc.CallOption) (*CreateResponse, error) { |
|
149 |
+ out := new(CreateResponse) |
|
150 |
+ err := grpc.Invoke(ctx, "/containerd.services.leases.v1.Leases/Create", in, out, c.cc, opts...) |
|
151 |
+ if err != nil { |
|
152 |
+ return nil, err |
|
153 |
+ } |
|
154 |
+ return out, nil |
|
155 |
+} |
|
156 |
+ |
|
157 |
+func (c *leasesClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*google_protobuf1.Empty, error) { |
|
158 |
+ out := new(google_protobuf1.Empty) |
|
159 |
+ err := grpc.Invoke(ctx, "/containerd.services.leases.v1.Leases/Delete", in, out, c.cc, opts...) |
|
160 |
+ if err != nil { |
|
161 |
+ return nil, err |
|
162 |
+ } |
|
163 |
+ return out, nil |
|
164 |
+} |
|
165 |
+ |
|
166 |
+func (c *leasesClient) List(ctx context.Context, in *ListRequest, opts ...grpc.CallOption) (*ListResponse, error) { |
|
167 |
+ out := new(ListResponse) |
|
168 |
+ err := grpc.Invoke(ctx, "/containerd.services.leases.v1.Leases/List", in, out, c.cc, opts...) |
|
169 |
+ if err != nil { |
|
170 |
+ return nil, err |
|
171 |
+ } |
|
172 |
+ return out, nil |
|
173 |
+} |
|
174 |
+ |
|
175 |
+// Server API for Leases service |
|
176 |
+ |
|
177 |
+type LeasesServer interface { |
|
178 |
+ // Create creates a new lease for managing changes to metadata. A lease |
|
179 |
+ // can be used to protect objects from being removed. |
|
180 |
+ Create(context.Context, *CreateRequest) (*CreateResponse, error) |
|
181 |
+ // Delete deletes the lease and makes any unreferenced objects created |
|
182 |
+ // during the lease eligible for garbage collection if not referenced |
|
183 |
+ // or retained by other resources during the lease. |
|
184 |
+ Delete(context.Context, *DeleteRequest) (*google_protobuf1.Empty, error) |
|
185 |
+ // ListTransactions lists all active leases, returning the full list of |
|
186 |
+ // leases and optionally including the referenced resources. |
|
187 |
+ List(context.Context, *ListRequest) (*ListResponse, error) |
|
188 |
+} |
|
189 |
+ |
|
190 |
+func RegisterLeasesServer(s *grpc.Server, srv LeasesServer) { |
|
191 |
+ s.RegisterService(&_Leases_serviceDesc, srv) |
|
192 |
+} |
|
193 |
+ |
|
194 |
+func _Leases_Create_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { |
|
195 |
+ in := new(CreateRequest) |
|
196 |
+ if err := dec(in); err != nil { |
|
197 |
+ return nil, err |
|
198 |
+ } |
|
199 |
+ if interceptor == nil { |
|
200 |
+ return srv.(LeasesServer).Create(ctx, in) |
|
201 |
+ } |
|
202 |
+ info := &grpc.UnaryServerInfo{ |
|
203 |
+ Server: srv, |
|
204 |
+ FullMethod: "/containerd.services.leases.v1.Leases/Create", |
|
205 |
+ } |
|
206 |
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) { |
|
207 |
+ return srv.(LeasesServer).Create(ctx, req.(*CreateRequest)) |
|
208 |
+ } |
|
209 |
+ return interceptor(ctx, in, info, handler) |
|
210 |
+} |
|
211 |
+ |
|
212 |
+func _Leases_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { |
|
213 |
+ in := new(DeleteRequest) |
|
214 |
+ if err := dec(in); err != nil { |
|
215 |
+ return nil, err |
|
216 |
+ } |
|
217 |
+ if interceptor == nil { |
|
218 |
+ return srv.(LeasesServer).Delete(ctx, in) |
|
219 |
+ } |
|
220 |
+ info := &grpc.UnaryServerInfo{ |
|
221 |
+ Server: srv, |
|
222 |
+ FullMethod: "/containerd.services.leases.v1.Leases/Delete", |
|
223 |
+ } |
|
224 |
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) { |
|
225 |
+ return srv.(LeasesServer).Delete(ctx, req.(*DeleteRequest)) |
|
226 |
+ } |
|
227 |
+ return interceptor(ctx, in, info, handler) |
|
228 |
+} |
|
229 |
+ |
|
230 |
+func _Leases_List_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { |
|
231 |
+ in := new(ListRequest) |
|
232 |
+ if err := dec(in); err != nil { |
|
233 |
+ return nil, err |
|
234 |
+ } |
|
235 |
+ if interceptor == nil { |
|
236 |
+ return srv.(LeasesServer).List(ctx, in) |
|
237 |
+ } |
|
238 |
+ info := &grpc.UnaryServerInfo{ |
|
239 |
+ Server: srv, |
|
240 |
+ FullMethod: "/containerd.services.leases.v1.Leases/List", |
|
241 |
+ } |
|
242 |
+ handler := func(ctx context.Context, req interface{}) (interface{}, error) { |
|
243 |
+ return srv.(LeasesServer).List(ctx, req.(*ListRequest)) |
|
244 |
+ } |
|
245 |
+ return interceptor(ctx, in, info, handler) |
|
246 |
+} |
|
247 |
+ |
|
248 |
+var _Leases_serviceDesc = grpc.ServiceDesc{ |
|
249 |
+ ServiceName: "containerd.services.leases.v1.Leases", |
|
250 |
+ HandlerType: (*LeasesServer)(nil), |
|
251 |
+ Methods: []grpc.MethodDesc{ |
|
252 |
+ { |
|
253 |
+ MethodName: "Create", |
|
254 |
+ Handler: _Leases_Create_Handler, |
|
255 |
+ }, |
|
256 |
+ { |
|
257 |
+ MethodName: "Delete", |
|
258 |
+ Handler: _Leases_Delete_Handler, |
|
259 |
+ }, |
|
260 |
+ { |
|
261 |
+ MethodName: "List", |
|
262 |
+ Handler: _Leases_List_Handler, |
|
263 |
+ }, |
|
264 |
+ }, |
|
265 |
+ Streams: []grpc.StreamDesc{}, |
|
266 |
+ Metadata: "github.com/containerd/containerd/api/services/leases/v1/leases.proto", |
|
267 |
+} |
|
268 |
+ |
|
269 |
+func (m *Lease) Marshal() (dAtA []byte, err error) { |
|
270 |
+ size := m.Size() |
|
271 |
+ dAtA = make([]byte, size) |
|
272 |
+ n, err := m.MarshalTo(dAtA) |
|
273 |
+ if err != nil { |
|
274 |
+ return nil, err |
|
275 |
+ } |
|
276 |
+ return dAtA[:n], nil |
|
277 |
+} |
|
278 |
+ |
|
279 |
+func (m *Lease) MarshalTo(dAtA []byte) (int, error) { |
|
280 |
+ var i int |
|
281 |
+ _ = i |
|
282 |
+ var l int |
|
283 |
+ _ = l |
|
284 |
+ if len(m.ID) > 0 { |
|
285 |
+ dAtA[i] = 0xa |
|
286 |
+ i++ |
|
287 |
+ i = encodeVarintLeases(dAtA, i, uint64(len(m.ID))) |
|
288 |
+ i += copy(dAtA[i:], m.ID) |
|
289 |
+ } |
|
290 |
+ dAtA[i] = 0x12 |
|
291 |
+ i++ |
|
292 |
+ i = encodeVarintLeases(dAtA, i, uint64(github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt))) |
|
293 |
+ n1, err := github_com_gogo_protobuf_types.StdTimeMarshalTo(m.CreatedAt, dAtA[i:]) |
|
294 |
+ if err != nil { |
|
295 |
+ return 0, err |
|
296 |
+ } |
|
297 |
+ i += n1 |
|
298 |
+ if len(m.Labels) > 0 { |
|
299 |
+ for k, _ := range m.Labels { |
|
300 |
+ dAtA[i] = 0x1a |
|
301 |
+ i++ |
|
302 |
+ v := m.Labels[k] |
|
303 |
+ mapSize := 1 + len(k) + sovLeases(uint64(len(k))) + 1 + len(v) + sovLeases(uint64(len(v))) |
|
304 |
+ i = encodeVarintLeases(dAtA, i, uint64(mapSize)) |
|
305 |
+ dAtA[i] = 0xa |
|
306 |
+ i++ |
|
307 |
+ i = encodeVarintLeases(dAtA, i, uint64(len(k))) |
|
308 |
+ i += copy(dAtA[i:], k) |
|
309 |
+ dAtA[i] = 0x12 |
|
310 |
+ i++ |
|
311 |
+ i = encodeVarintLeases(dAtA, i, uint64(len(v))) |
|
312 |
+ i += copy(dAtA[i:], v) |
|
313 |
+ } |
|
314 |
+ } |
|
315 |
+ return i, nil |
|
316 |
+} |
|
317 |
+ |
|
318 |
+func (m *CreateRequest) Marshal() (dAtA []byte, err error) { |
|
319 |
+ size := m.Size() |
|
320 |
+ dAtA = make([]byte, size) |
|
321 |
+ n, err := m.MarshalTo(dAtA) |
|
322 |
+ if err != nil { |
|
323 |
+ return nil, err |
|
324 |
+ } |
|
325 |
+ return dAtA[:n], nil |
|
326 |
+} |
|
327 |
+ |
|
328 |
+func (m *CreateRequest) MarshalTo(dAtA []byte) (int, error) { |
|
329 |
+ var i int |
|
330 |
+ _ = i |
|
331 |
+ var l int |
|
332 |
+ _ = l |
|
333 |
+ if len(m.ID) > 0 { |
|
334 |
+ dAtA[i] = 0xa |
|
335 |
+ i++ |
|
336 |
+ i = encodeVarintLeases(dAtA, i, uint64(len(m.ID))) |
|
337 |
+ i += copy(dAtA[i:], m.ID) |
|
338 |
+ } |
|
339 |
+ if len(m.Labels) > 0 { |
|
340 |
+ for k, _ := range m.Labels { |
|
341 |
+ dAtA[i] = 0x1a |
|
342 |
+ i++ |
|
343 |
+ v := m.Labels[k] |
|
344 |
+ mapSize := 1 + len(k) + sovLeases(uint64(len(k))) + 1 + len(v) + sovLeases(uint64(len(v))) |
|
345 |
+ i = encodeVarintLeases(dAtA, i, uint64(mapSize)) |
|
346 |
+ dAtA[i] = 0xa |
|
347 |
+ i++ |
|
348 |
+ i = encodeVarintLeases(dAtA, i, uint64(len(k))) |
|
349 |
+ i += copy(dAtA[i:], k) |
|
350 |
+ dAtA[i] = 0x12 |
|
351 |
+ i++ |
|
352 |
+ i = encodeVarintLeases(dAtA, i, uint64(len(v))) |
|
353 |
+ i += copy(dAtA[i:], v) |
|
354 |
+ } |
|
355 |
+ } |
|
356 |
+ return i, nil |
|
357 |
+} |
|
358 |
+ |
|
359 |
+func (m *CreateResponse) Marshal() (dAtA []byte, err error) { |
|
360 |
+ size := m.Size() |
|
361 |
+ dAtA = make([]byte, size) |
|
362 |
+ n, err := m.MarshalTo(dAtA) |
|
363 |
+ if err != nil { |
|
364 |
+ return nil, err |
|
365 |
+ } |
|
366 |
+ return dAtA[:n], nil |
|
367 |
+} |
|
368 |
+ |
|
369 |
+func (m *CreateResponse) MarshalTo(dAtA []byte) (int, error) { |
|
370 |
+ var i int |
|
371 |
+ _ = i |
|
372 |
+ var l int |
|
373 |
+ _ = l |
|
374 |
+ if m.Lease != nil { |
|
375 |
+ dAtA[i] = 0xa |
|
376 |
+ i++ |
|
377 |
+ i = encodeVarintLeases(dAtA, i, uint64(m.Lease.Size())) |
|
378 |
+ n2, err := m.Lease.MarshalTo(dAtA[i:]) |
|
379 |
+ if err != nil { |
|
380 |
+ return 0, err |
|
381 |
+ } |
|
382 |
+ i += n2 |
|
383 |
+ } |
|
384 |
+ return i, nil |
|
385 |
+} |
|
386 |
+ |
|
387 |
+func (m *DeleteRequest) Marshal() (dAtA []byte, err error) { |
|
388 |
+ size := m.Size() |
|
389 |
+ dAtA = make([]byte, size) |
|
390 |
+ n, err := m.MarshalTo(dAtA) |
|
391 |
+ if err != nil { |
|
392 |
+ return nil, err |
|
393 |
+ } |
|
394 |
+ return dAtA[:n], nil |
|
395 |
+} |
|
396 |
+ |
|
397 |
+func (m *DeleteRequest) MarshalTo(dAtA []byte) (int, error) { |
|
398 |
+ var i int |
|
399 |
+ _ = i |
|
400 |
+ var l int |
|
401 |
+ _ = l |
|
402 |
+ if len(m.ID) > 0 { |
|
403 |
+ dAtA[i] = 0xa |
|
404 |
+ i++ |
|
405 |
+ i = encodeVarintLeases(dAtA, i, uint64(len(m.ID))) |
|
406 |
+ i += copy(dAtA[i:], m.ID) |
|
407 |
+ } |
|
408 |
+ return i, nil |
|
409 |
+} |
|
410 |
+ |
|
411 |
+func (m *ListRequest) Marshal() (dAtA []byte, err error) { |
|
412 |
+ size := m.Size() |
|
413 |
+ dAtA = make([]byte, size) |
|
414 |
+ n, err := m.MarshalTo(dAtA) |
|
415 |
+ if err != nil { |
|
416 |
+ return nil, err |
|
417 |
+ } |
|
418 |
+ return dAtA[:n], nil |
|
419 |
+} |
|
420 |
+ |
|
421 |
+func (m *ListRequest) MarshalTo(dAtA []byte) (int, error) { |
|
422 |
+ var i int |
|
423 |
+ _ = i |
|
424 |
+ var l int |
|
425 |
+ _ = l |
|
426 |
+ if len(m.Filters) > 0 { |
|
427 |
+ for _, s := range m.Filters { |
|
428 |
+ dAtA[i] = 0xa |
|
429 |
+ i++ |
|
430 |
+ l = len(s) |
|
431 |
+ for l >= 1<<7 { |
|
432 |
+ dAtA[i] = uint8(uint64(l)&0x7f | 0x80) |
|
433 |
+ l >>= 7 |
|
434 |
+ i++ |
|
435 |
+ } |
|
436 |
+ dAtA[i] = uint8(l) |
|
437 |
+ i++ |
|
438 |
+ i += copy(dAtA[i:], s) |
|
439 |
+ } |
|
440 |
+ } |
|
441 |
+ return i, nil |
|
442 |
+} |
|
443 |
+ |
|
444 |
+func (m *ListResponse) Marshal() (dAtA []byte, err error) { |
|
445 |
+ size := m.Size() |
|
446 |
+ dAtA = make([]byte, size) |
|
447 |
+ n, err := m.MarshalTo(dAtA) |
|
448 |
+ if err != nil { |
|
449 |
+ return nil, err |
|
450 |
+ } |
|
451 |
+ return dAtA[:n], nil |
|
452 |
+} |
|
453 |
+ |
|
454 |
+func (m *ListResponse) MarshalTo(dAtA []byte) (int, error) { |
|
455 |
+ var i int |
|
456 |
+ _ = i |
|
457 |
+ var l int |
|
458 |
+ _ = l |
|
459 |
+ if len(m.Leases) > 0 { |
|
460 |
+ for _, msg := range m.Leases { |
|
461 |
+ dAtA[i] = 0xa |
|
462 |
+ i++ |
|
463 |
+ i = encodeVarintLeases(dAtA, i, uint64(msg.Size())) |
|
464 |
+ n, err := msg.MarshalTo(dAtA[i:]) |
|
465 |
+ if err != nil { |
|
466 |
+ return 0, err |
|
467 |
+ } |
|
468 |
+ i += n |
|
469 |
+ } |
|
470 |
+ } |
|
471 |
+ return i, nil |
|
472 |
+} |
|
473 |
+ |
|
474 |
+func encodeFixed64Leases(dAtA []byte, offset int, v uint64) int { |
|
475 |
+ dAtA[offset] = uint8(v) |
|
476 |
+ dAtA[offset+1] = uint8(v >> 8) |
|
477 |
+ dAtA[offset+2] = uint8(v >> 16) |
|
478 |
+ dAtA[offset+3] = uint8(v >> 24) |
|
479 |
+ dAtA[offset+4] = uint8(v >> 32) |
|
480 |
+ dAtA[offset+5] = uint8(v >> 40) |
|
481 |
+ dAtA[offset+6] = uint8(v >> 48) |
|
482 |
+ dAtA[offset+7] = uint8(v >> 56) |
|
483 |
+ return offset + 8 |
|
484 |
+} |
|
485 |
+func encodeFixed32Leases(dAtA []byte, offset int, v uint32) int { |
|
486 |
+ dAtA[offset] = uint8(v) |
|
487 |
+ dAtA[offset+1] = uint8(v >> 8) |
|
488 |
+ dAtA[offset+2] = uint8(v >> 16) |
|
489 |
+ dAtA[offset+3] = uint8(v >> 24) |
|
490 |
+ return offset + 4 |
|
491 |
+} |
|
492 |
+func encodeVarintLeases(dAtA []byte, offset int, v uint64) int { |
|
493 |
+ for v >= 1<<7 { |
|
494 |
+ dAtA[offset] = uint8(v&0x7f | 0x80) |
|
495 |
+ v >>= 7 |
|
496 |
+ offset++ |
|
497 |
+ } |
|
498 |
+ dAtA[offset] = uint8(v) |
|
499 |
+ return offset + 1 |
|
500 |
+} |
|
501 |
+func (m *Lease) Size() (n int) { |
|
502 |
+ var l int |
|
503 |
+ _ = l |
|
504 |
+ l = len(m.ID) |
|
505 |
+ if l > 0 { |
|
506 |
+ n += 1 + l + sovLeases(uint64(l)) |
|
507 |
+ } |
|
508 |
+ l = github_com_gogo_protobuf_types.SizeOfStdTime(m.CreatedAt) |
|
509 |
+ n += 1 + l + sovLeases(uint64(l)) |
|
510 |
+ if len(m.Labels) > 0 { |
|
511 |
+ for k, v := range m.Labels { |
|
512 |
+ _ = k |
|
513 |
+ _ = v |
|
514 |
+ mapEntrySize := 1 + len(k) + sovLeases(uint64(len(k))) + 1 + len(v) + sovLeases(uint64(len(v))) |
|
515 |
+ n += mapEntrySize + 1 + sovLeases(uint64(mapEntrySize)) |
|
516 |
+ } |
|
517 |
+ } |
|
518 |
+ return n |
|
519 |
+} |
|
520 |
+ |
|
521 |
+func (m *CreateRequest) Size() (n int) { |
|
522 |
+ var l int |
|
523 |
+ _ = l |
|
524 |
+ l = len(m.ID) |
|
525 |
+ if l > 0 { |
|
526 |
+ n += 1 + l + sovLeases(uint64(l)) |
|
527 |
+ } |
|
528 |
+ if len(m.Labels) > 0 { |
|
529 |
+ for k, v := range m.Labels { |
|
530 |
+ _ = k |
|
531 |
+ _ = v |
|
532 |
+ mapEntrySize := 1 + len(k) + sovLeases(uint64(len(k))) + 1 + len(v) + sovLeases(uint64(len(v))) |
|
533 |
+ n += mapEntrySize + 1 + sovLeases(uint64(mapEntrySize)) |
|
534 |
+ } |
|
535 |
+ } |
|
536 |
+ return n |
|
537 |
+} |
|
538 |
+ |
|
539 |
+func (m *CreateResponse) Size() (n int) { |
|
540 |
+ var l int |
|
541 |
+ _ = l |
|
542 |
+ if m.Lease != nil { |
|
543 |
+ l = m.Lease.Size() |
|
544 |
+ n += 1 + l + sovLeases(uint64(l)) |
|
545 |
+ } |
|
546 |
+ return n |
|
547 |
+} |
|
548 |
+ |
|
549 |
+func (m *DeleteRequest) Size() (n int) { |
|
550 |
+ var l int |
|
551 |
+ _ = l |
|
552 |
+ l = len(m.ID) |
|
553 |
+ if l > 0 { |
|
554 |
+ n += 1 + l + sovLeases(uint64(l)) |
|
555 |
+ } |
|
556 |
+ return n |
|
557 |
+} |
|
558 |
+ |
|
559 |
+func (m *ListRequest) Size() (n int) { |
|
560 |
+ var l int |
|
561 |
+ _ = l |
|
562 |
+ if len(m.Filters) > 0 { |
|
563 |
+ for _, s := range m.Filters { |
|
564 |
+ l = len(s) |
|
565 |
+ n += 1 + l + sovLeases(uint64(l)) |
|
566 |
+ } |
|
567 |
+ } |
|
568 |
+ return n |
|
569 |
+} |
|
570 |
+ |
|
571 |
+func (m *ListResponse) Size() (n int) { |
|
572 |
+ var l int |
|
573 |
+ _ = l |
|
574 |
+ if len(m.Leases) > 0 { |
|
575 |
+ for _, e := range m.Leases { |
|
576 |
+ l = e.Size() |
|
577 |
+ n += 1 + l + sovLeases(uint64(l)) |
|
578 |
+ } |
|
579 |
+ } |
|
580 |
+ return n |
|
581 |
+} |
|
582 |
+ |
|
583 |
+func sovLeases(x uint64) (n int) { |
|
584 |
+ for { |
|
585 |
+ n++ |
|
586 |
+ x >>= 7 |
|
587 |
+ if x == 0 { |
|
588 |
+ break |
|
589 |
+ } |
|
590 |
+ } |
|
591 |
+ return n |
|
592 |
+} |
|
593 |
+func sozLeases(x uint64) (n int) { |
|
594 |
+ return sovLeases(uint64((x << 1) ^ uint64((int64(x) >> 63)))) |
|
595 |
+} |
|
596 |
+func (this *Lease) String() string { |
|
597 |
+ if this == nil { |
|
598 |
+ return "nil" |
|
599 |
+ } |
|
600 |
+ keysForLabels := make([]string, 0, len(this.Labels)) |
|
601 |
+ for k, _ := range this.Labels { |
|
602 |
+ keysForLabels = append(keysForLabels, k) |
|
603 |
+ } |
|
604 |
+ github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) |
|
605 |
+ mapStringForLabels := "map[string]string{" |
|
606 |
+ for _, k := range keysForLabels { |
|
607 |
+ mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) |
|
608 |
+ } |
|
609 |
+ mapStringForLabels += "}" |
|
610 |
+ s := strings.Join([]string{`&Lease{`, |
|
611 |
+ `ID:` + fmt.Sprintf("%v", this.ID) + `,`, |
|
612 |
+ `CreatedAt:` + strings.Replace(strings.Replace(this.CreatedAt.String(), "Timestamp", "google_protobuf2.Timestamp", 1), `&`, ``, 1) + `,`, |
|
613 |
+ `Labels:` + mapStringForLabels + `,`, |
|
614 |
+ `}`, |
|
615 |
+ }, "") |
|
616 |
+ return s |
|
617 |
+} |
|
618 |
+func (this *CreateRequest) String() string { |
|
619 |
+ if this == nil { |
|
620 |
+ return "nil" |
|
621 |
+ } |
|
622 |
+ keysForLabels := make([]string, 0, len(this.Labels)) |
|
623 |
+ for k, _ := range this.Labels { |
|
624 |
+ keysForLabels = append(keysForLabels, k) |
|
625 |
+ } |
|
626 |
+ github_com_gogo_protobuf_sortkeys.Strings(keysForLabels) |
|
627 |
+ mapStringForLabels := "map[string]string{" |
|
628 |
+ for _, k := range keysForLabels { |
|
629 |
+ mapStringForLabels += fmt.Sprintf("%v: %v,", k, this.Labels[k]) |
|
630 |
+ } |
|
631 |
+ mapStringForLabels += "}" |
|
632 |
+ s := strings.Join([]string{`&CreateRequest{`, |
|
633 |
+ `ID:` + fmt.Sprintf("%v", this.ID) + `,`, |
|
634 |
+ `Labels:` + mapStringForLabels + `,`, |
|
635 |
+ `}`, |
|
636 |
+ }, "") |
|
637 |
+ return s |
|
638 |
+} |
|
639 |
+func (this *CreateResponse) String() string { |
|
640 |
+ if this == nil { |
|
641 |
+ return "nil" |
|
642 |
+ } |
|
643 |
+ s := strings.Join([]string{`&CreateResponse{`, |
|
644 |
+ `Lease:` + strings.Replace(fmt.Sprintf("%v", this.Lease), "Lease", "Lease", 1) + `,`, |
|
645 |
+ `}`, |
|
646 |
+ }, "") |
|
647 |
+ return s |
|
648 |
+} |
|
649 |
+func (this *DeleteRequest) String() string { |
|
650 |
+ if this == nil { |
|
651 |
+ return "nil" |
|
652 |
+ } |
|
653 |
+ s := strings.Join([]string{`&DeleteRequest{`, |
|
654 |
+ `ID:` + fmt.Sprintf("%v", this.ID) + `,`, |
|
655 |
+ `}`, |
|
656 |
+ }, "") |
|
657 |
+ return s |
|
658 |
+} |
|
659 |
+func (this *ListRequest) String() string { |
|
660 |
+ if this == nil { |
|
661 |
+ return "nil" |
|
662 |
+ } |
|
663 |
+ s := strings.Join([]string{`&ListRequest{`, |
|
664 |
+ `Filters:` + fmt.Sprintf("%v", this.Filters) + `,`, |
|
665 |
+ `}`, |
|
666 |
+ }, "") |
|
667 |
+ return s |
|
668 |
+} |
|
669 |
+func (this *ListResponse) String() string { |
|
670 |
+ if this == nil { |
|
671 |
+ return "nil" |
|
672 |
+ } |
|
673 |
+ s := strings.Join([]string{`&ListResponse{`, |
|
674 |
+ `Leases:` + strings.Replace(fmt.Sprintf("%v", this.Leases), "Lease", "Lease", 1) + `,`, |
|
675 |
+ `}`, |
|
676 |
+ }, "") |
|
677 |
+ return s |
|
678 |
+} |
|
679 |
+func valueToStringLeases(v interface{}) string { |
|
680 |
+ rv := reflect.ValueOf(v) |
|
681 |
+ if rv.IsNil() { |
|
682 |
+ return "nil" |
|
683 |
+ } |
|
684 |
+ pv := reflect.Indirect(rv).Interface() |
|
685 |
+ return fmt.Sprintf("*%v", pv) |
|
686 |
+} |
|
687 |
+func (m *Lease) Unmarshal(dAtA []byte) error { |
|
688 |
+ l := len(dAtA) |
|
689 |
+ iNdEx := 0 |
|
690 |
+ for iNdEx < l { |
|
691 |
+ preIndex := iNdEx |
|
692 |
+ var wire uint64 |
|
693 |
+ for shift := uint(0); ; shift += 7 { |
|
694 |
+ if shift >= 64 { |
|
695 |
+ return ErrIntOverflowLeases |
|
696 |
+ } |
|
697 |
+ if iNdEx >= l { |
|
698 |
+ return io.ErrUnexpectedEOF |
|
699 |
+ } |
|
700 |
+ b := dAtA[iNdEx] |
|
701 |
+ iNdEx++ |
|
702 |
+ wire |= (uint64(b) & 0x7F) << shift |
|
703 |
+ if b < 0x80 { |
|
704 |
+ break |
|
705 |
+ } |
|
706 |
+ } |
|
707 |
+ fieldNum := int32(wire >> 3) |
|
708 |
+ wireType := int(wire & 0x7) |
|
709 |
+ if wireType == 4 { |
|
710 |
+ return fmt.Errorf("proto: Lease: wiretype end group for non-group") |
|
711 |
+ } |
|
712 |
+ if fieldNum <= 0 { |
|
713 |
+ return fmt.Errorf("proto: Lease: illegal tag %d (wire type %d)", fieldNum, wire) |
|
714 |
+ } |
|
715 |
+ switch fieldNum { |
|
716 |
+ case 1: |
|
717 |
+ if wireType != 2 { |
|
718 |
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) |
|
719 |
+ } |
|
720 |
+ var stringLen uint64 |
|
721 |
+ for shift := uint(0); ; shift += 7 { |
|
722 |
+ if shift >= 64 { |
|
723 |
+ return ErrIntOverflowLeases |
|
724 |
+ } |
|
725 |
+ if iNdEx >= l { |
|
726 |
+ return io.ErrUnexpectedEOF |
|
727 |
+ } |
|
728 |
+ b := dAtA[iNdEx] |
|
729 |
+ iNdEx++ |
|
730 |
+ stringLen |= (uint64(b) & 0x7F) << shift |
|
731 |
+ if b < 0x80 { |
|
732 |
+ break |
|
733 |
+ } |
|
734 |
+ } |
|
735 |
+ intStringLen := int(stringLen) |
|
736 |
+ if intStringLen < 0 { |
|
737 |
+ return ErrInvalidLengthLeases |
|
738 |
+ } |
|
739 |
+ postIndex := iNdEx + intStringLen |
|
740 |
+ if postIndex > l { |
|
741 |
+ return io.ErrUnexpectedEOF |
|
742 |
+ } |
|
743 |
+ m.ID = string(dAtA[iNdEx:postIndex]) |
|
744 |
+ iNdEx = postIndex |
|
745 |
+ case 2: |
|
746 |
+ if wireType != 2 { |
|
747 |
+ return fmt.Errorf("proto: wrong wireType = %d for field CreatedAt", wireType) |
|
748 |
+ } |
|
749 |
+ var msglen int |
|
750 |
+ for shift := uint(0); ; shift += 7 { |
|
751 |
+ if shift >= 64 { |
|
752 |
+ return ErrIntOverflowLeases |
|
753 |
+ } |
|
754 |
+ if iNdEx >= l { |
|
755 |
+ return io.ErrUnexpectedEOF |
|
756 |
+ } |
|
757 |
+ b := dAtA[iNdEx] |
|
758 |
+ iNdEx++ |
|
759 |
+ msglen |= (int(b) & 0x7F) << shift |
|
760 |
+ if b < 0x80 { |
|
761 |
+ break |
|
762 |
+ } |
|
763 |
+ } |
|
764 |
+ if msglen < 0 { |
|
765 |
+ return ErrInvalidLengthLeases |
|
766 |
+ } |
|
767 |
+ postIndex := iNdEx + msglen |
|
768 |
+ if postIndex > l { |
|
769 |
+ return io.ErrUnexpectedEOF |
|
770 |
+ } |
|
771 |
+ if err := github_com_gogo_protobuf_types.StdTimeUnmarshal(&m.CreatedAt, dAtA[iNdEx:postIndex]); err != nil { |
|
772 |
+ return err |
|
773 |
+ } |
|
774 |
+ iNdEx = postIndex |
|
775 |
+ case 3: |
|
776 |
+ if wireType != 2 { |
|
777 |
+ return fmt.Errorf("proto: wrong wireType = %d for field Labels", wireType) |
|
778 |
+ } |
|
779 |
+ var msglen int |
|
780 |
+ for shift := uint(0); ; shift += 7 { |
|
781 |
+ if shift >= 64 { |
|
782 |
+ return ErrIntOverflowLeases |
|
783 |
+ } |
|
784 |
+ if iNdEx >= l { |
|
785 |
+ return io.ErrUnexpectedEOF |
|
786 |
+ } |
|
787 |
+ b := dAtA[iNdEx] |
|
788 |
+ iNdEx++ |
|
789 |
+ msglen |= (int(b) & 0x7F) << shift |
|
790 |
+ if b < 0x80 { |
|
791 |
+ break |
|
792 |
+ } |
|
793 |
+ } |
|
794 |
+ if msglen < 0 { |
|
795 |
+ return ErrInvalidLengthLeases |
|
796 |
+ } |
|
797 |
+ postIndex := iNdEx + msglen |
|
798 |
+ if postIndex > l { |
|
799 |
+ return io.ErrUnexpectedEOF |
|
800 |
+ } |
|
801 |
+ var keykey uint64 |
|
802 |
+ for shift := uint(0); ; shift += 7 { |
|
803 |
+ if shift >= 64 { |
|
804 |
+ return ErrIntOverflowLeases |
|
805 |
+ } |
|
806 |
+ if iNdEx >= l { |
|
807 |
+ return io.ErrUnexpectedEOF |
|
808 |
+ } |
|
809 |
+ b := dAtA[iNdEx] |
|
810 |
+ iNdEx++ |
|
811 |
+ keykey |= (uint64(b) & 0x7F) << shift |
|
812 |
+ if b < 0x80 { |
|
813 |
+ break |
|
814 |
+ } |
|
815 |
+ } |
|
816 |
+ var stringLenmapkey uint64 |
|
817 |
+ for shift := uint(0); ; shift += 7 { |
|
818 |
+ if shift >= 64 { |
|
819 |
+ return ErrIntOverflowLeases |
|
820 |
+ } |
|
821 |
+ if iNdEx >= l { |
|
822 |
+ return io.ErrUnexpectedEOF |
|
823 |
+ } |
|
824 |
+ b := dAtA[iNdEx] |
|
825 |
+ iNdEx++ |
|
826 |
+ stringLenmapkey |= (uint64(b) & 0x7F) << shift |
|
827 |
+ if b < 0x80 { |
|
828 |
+ break |
|
829 |
+ } |
|
830 |
+ } |
|
831 |
+ intStringLenmapkey := int(stringLenmapkey) |
|
832 |
+ if intStringLenmapkey < 0 { |
|
833 |
+ return ErrInvalidLengthLeases |
|
834 |
+ } |
|
835 |
+ postStringIndexmapkey := iNdEx + intStringLenmapkey |
|
836 |
+ if postStringIndexmapkey > l { |
|
837 |
+ return io.ErrUnexpectedEOF |
|
838 |
+ } |
|
839 |
+ mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) |
|
840 |
+ iNdEx = postStringIndexmapkey |
|
841 |
+ if m.Labels == nil { |
|
842 |
+ m.Labels = make(map[string]string) |
|
843 |
+ } |
|
844 |
+ if iNdEx < postIndex { |
|
845 |
+ var valuekey uint64 |
|
846 |
+ for shift := uint(0); ; shift += 7 { |
|
847 |
+ if shift >= 64 { |
|
848 |
+ return ErrIntOverflowLeases |
|
849 |
+ } |
|
850 |
+ if iNdEx >= l { |
|
851 |
+ return io.ErrUnexpectedEOF |
|
852 |
+ } |
|
853 |
+ b := dAtA[iNdEx] |
|
854 |
+ iNdEx++ |
|
855 |
+ valuekey |= (uint64(b) & 0x7F) << shift |
|
856 |
+ if b < 0x80 { |
|
857 |
+ break |
|
858 |
+ } |
|
859 |
+ } |
|
860 |
+ var stringLenmapvalue uint64 |
|
861 |
+ for shift := uint(0); ; shift += 7 { |
|
862 |
+ if shift >= 64 { |
|
863 |
+ return ErrIntOverflowLeases |
|
864 |
+ } |
|
865 |
+ if iNdEx >= l { |
|
866 |
+ return io.ErrUnexpectedEOF |
|
867 |
+ } |
|
868 |
+ b := dAtA[iNdEx] |
|
869 |
+ iNdEx++ |
|
870 |
+ stringLenmapvalue |= (uint64(b) & 0x7F) << shift |
|
871 |
+ if b < 0x80 { |
|
872 |
+ break |
|
873 |
+ } |
|
874 |
+ } |
|
875 |
+ intStringLenmapvalue := int(stringLenmapvalue) |
|
876 |
+ if intStringLenmapvalue < 0 { |
|
877 |
+ return ErrInvalidLengthLeases |
|
878 |
+ } |
|
879 |
+ postStringIndexmapvalue := iNdEx + intStringLenmapvalue |
|
880 |
+ if postStringIndexmapvalue > l { |
|
881 |
+ return io.ErrUnexpectedEOF |
|
882 |
+ } |
|
883 |
+ mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue]) |
|
884 |
+ iNdEx = postStringIndexmapvalue |
|
885 |
+ m.Labels[mapkey] = mapvalue |
|
886 |
+ } else { |
|
887 |
+ var mapvalue string |
|
888 |
+ m.Labels[mapkey] = mapvalue |
|
889 |
+ } |
|
890 |
+ iNdEx = postIndex |
|
891 |
+ default: |
|
892 |
+ iNdEx = preIndex |
|
893 |
+ skippy, err := skipLeases(dAtA[iNdEx:]) |
|
894 |
+ if err != nil { |
|
895 |
+ return err |
|
896 |
+ } |
|
897 |
+ if skippy < 0 { |
|
898 |
+ return ErrInvalidLengthLeases |
|
899 |
+ } |
|
900 |
+ if (iNdEx + skippy) > l { |
|
901 |
+ return io.ErrUnexpectedEOF |
|
902 |
+ } |
|
903 |
+ iNdEx += skippy |
|
904 |
+ } |
|
905 |
+ } |
|
906 |
+ |
|
907 |
+ if iNdEx > l { |
|
908 |
+ return io.ErrUnexpectedEOF |
|
909 |
+ } |
|
910 |
+ return nil |
|
911 |
+} |
|
912 |
+func (m *CreateRequest) Unmarshal(dAtA []byte) error { |
|
913 |
+ l := len(dAtA) |
|
914 |
+ iNdEx := 0 |
|
915 |
+ for iNdEx < l { |
|
916 |
+ preIndex := iNdEx |
|
917 |
+ var wire uint64 |
|
918 |
+ for shift := uint(0); ; shift += 7 { |
|
919 |
+ if shift >= 64 { |
|
920 |
+ return ErrIntOverflowLeases |
|
921 |
+ } |
|
922 |
+ if iNdEx >= l { |
|
923 |
+ return io.ErrUnexpectedEOF |
|
924 |
+ } |
|
925 |
+ b := dAtA[iNdEx] |
|
926 |
+ iNdEx++ |
|
927 |
+ wire |= (uint64(b) & 0x7F) << shift |
|
928 |
+ if b < 0x80 { |
|
929 |
+ break |
|
930 |
+ } |
|
931 |
+ } |
|
932 |
+ fieldNum := int32(wire >> 3) |
|
933 |
+ wireType := int(wire & 0x7) |
|
934 |
+ if wireType == 4 { |
|
935 |
+ return fmt.Errorf("proto: CreateRequest: wiretype end group for non-group") |
|
936 |
+ } |
|
937 |
+ if fieldNum <= 0 { |
|
938 |
+ return fmt.Errorf("proto: CreateRequest: illegal tag %d (wire type %d)", fieldNum, wire) |
|
939 |
+ } |
|
940 |
+ switch fieldNum { |
|
941 |
+ case 1: |
|
942 |
+ if wireType != 2 { |
|
943 |
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) |
|
944 |
+ } |
|
945 |
+ var stringLen uint64 |
|
946 |
+ for shift := uint(0); ; shift += 7 { |
|
947 |
+ if shift >= 64 { |
|
948 |
+ return ErrIntOverflowLeases |
|
949 |
+ } |
|
950 |
+ if iNdEx >= l { |
|
951 |
+ return io.ErrUnexpectedEOF |
|
952 |
+ } |
|
953 |
+ b := dAtA[iNdEx] |
|
954 |
+ iNdEx++ |
|
955 |
+ stringLen |= (uint64(b) & 0x7F) << shift |
|
956 |
+ if b < 0x80 { |
|
957 |
+ break |
|
958 |
+ } |
|
959 |
+ } |
|
960 |
+ intStringLen := int(stringLen) |
|
961 |
+ if intStringLen < 0 { |
|
962 |
+ return ErrInvalidLengthLeases |
|
963 |
+ } |
|
964 |
+ postIndex := iNdEx + intStringLen |
|
965 |
+ if postIndex > l { |
|
966 |
+ return io.ErrUnexpectedEOF |
|
967 |
+ } |
|
968 |
+ m.ID = string(dAtA[iNdEx:postIndex]) |
|
969 |
+ iNdEx = postIndex |
|
970 |
+ case 3: |
|
971 |
+ if wireType != 2 { |
|
972 |
+ return fmt.Errorf("proto: wrong wireType = %d for field Labels", wireType) |
|
973 |
+ } |
|
974 |
+ var msglen int |
|
975 |
+ for shift := uint(0); ; shift += 7 { |
|
976 |
+ if shift >= 64 { |
|
977 |
+ return ErrIntOverflowLeases |
|
978 |
+ } |
|
979 |
+ if iNdEx >= l { |
|
980 |
+ return io.ErrUnexpectedEOF |
|
981 |
+ } |
|
982 |
+ b := dAtA[iNdEx] |
|
983 |
+ iNdEx++ |
|
984 |
+ msglen |= (int(b) & 0x7F) << shift |
|
985 |
+ if b < 0x80 { |
|
986 |
+ break |
|
987 |
+ } |
|
988 |
+ } |
|
989 |
+ if msglen < 0 { |
|
990 |
+ return ErrInvalidLengthLeases |
|
991 |
+ } |
|
992 |
+ postIndex := iNdEx + msglen |
|
993 |
+ if postIndex > l { |
|
994 |
+ return io.ErrUnexpectedEOF |
|
995 |
+ } |
|
996 |
+ var keykey uint64 |
|
997 |
+ for shift := uint(0); ; shift += 7 { |
|
998 |
+ if shift >= 64 { |
|
999 |
+ return ErrIntOverflowLeases |
|
1000 |
+ } |
|
1001 |
+ if iNdEx >= l { |
|
1002 |
+ return io.ErrUnexpectedEOF |
|
1003 |
+ } |
|
1004 |
+ b := dAtA[iNdEx] |
|
1005 |
+ iNdEx++ |
|
1006 |
+ keykey |= (uint64(b) & 0x7F) << shift |
|
1007 |
+ if b < 0x80 { |
|
1008 |
+ break |
|
1009 |
+ } |
|
1010 |
+ } |
|
1011 |
+ var stringLenmapkey uint64 |
|
1012 |
+ for shift := uint(0); ; shift += 7 { |
|
1013 |
+ if shift >= 64 { |
|
1014 |
+ return ErrIntOverflowLeases |
|
1015 |
+ } |
|
1016 |
+ if iNdEx >= l { |
|
1017 |
+ return io.ErrUnexpectedEOF |
|
1018 |
+ } |
|
1019 |
+ b := dAtA[iNdEx] |
|
1020 |
+ iNdEx++ |
|
1021 |
+ stringLenmapkey |= (uint64(b) & 0x7F) << shift |
|
1022 |
+ if b < 0x80 { |
|
1023 |
+ break |
|
1024 |
+ } |
|
1025 |
+ } |
|
1026 |
+ intStringLenmapkey := int(stringLenmapkey) |
|
1027 |
+ if intStringLenmapkey < 0 { |
|
1028 |
+ return ErrInvalidLengthLeases |
|
1029 |
+ } |
|
1030 |
+ postStringIndexmapkey := iNdEx + intStringLenmapkey |
|
1031 |
+ if postStringIndexmapkey > l { |
|
1032 |
+ return io.ErrUnexpectedEOF |
|
1033 |
+ } |
|
1034 |
+ mapkey := string(dAtA[iNdEx:postStringIndexmapkey]) |
|
1035 |
+ iNdEx = postStringIndexmapkey |
|
1036 |
+ if m.Labels == nil { |
|
1037 |
+ m.Labels = make(map[string]string) |
|
1038 |
+ } |
|
1039 |
+ if iNdEx < postIndex { |
|
1040 |
+ var valuekey uint64 |
|
1041 |
+ for shift := uint(0); ; shift += 7 { |
|
1042 |
+ if shift >= 64 { |
|
1043 |
+ return ErrIntOverflowLeases |
|
1044 |
+ } |
|
1045 |
+ if iNdEx >= l { |
|
1046 |
+ return io.ErrUnexpectedEOF |
|
1047 |
+ } |
|
1048 |
+ b := dAtA[iNdEx] |
|
1049 |
+ iNdEx++ |
|
1050 |
+ valuekey |= (uint64(b) & 0x7F) << shift |
|
1051 |
+ if b < 0x80 { |
|
1052 |
+ break |
|
1053 |
+ } |
|
1054 |
+ } |
|
1055 |
+ var stringLenmapvalue uint64 |
|
1056 |
+ for shift := uint(0); ; shift += 7 { |
|
1057 |
+ if shift >= 64 { |
|
1058 |
+ return ErrIntOverflowLeases |
|
1059 |
+ } |
|
1060 |
+ if iNdEx >= l { |
|
1061 |
+ return io.ErrUnexpectedEOF |
|
1062 |
+ } |
|
1063 |
+ b := dAtA[iNdEx] |
|
1064 |
+ iNdEx++ |
|
1065 |
+ stringLenmapvalue |= (uint64(b) & 0x7F) << shift |
|
1066 |
+ if b < 0x80 { |
|
1067 |
+ break |
|
1068 |
+ } |
|
1069 |
+ } |
|
1070 |
+ intStringLenmapvalue := int(stringLenmapvalue) |
|
1071 |
+ if intStringLenmapvalue < 0 { |
|
1072 |
+ return ErrInvalidLengthLeases |
|
1073 |
+ } |
|
1074 |
+ postStringIndexmapvalue := iNdEx + intStringLenmapvalue |
|
1075 |
+ if postStringIndexmapvalue > l { |
|
1076 |
+ return io.ErrUnexpectedEOF |
|
1077 |
+ } |
|
1078 |
+ mapvalue := string(dAtA[iNdEx:postStringIndexmapvalue]) |
|
1079 |
+ iNdEx = postStringIndexmapvalue |
|
1080 |
+ m.Labels[mapkey] = mapvalue |
|
1081 |
+ } else { |
|
1082 |
+ var mapvalue string |
|
1083 |
+ m.Labels[mapkey] = mapvalue |
|
1084 |
+ } |
|
1085 |
+ iNdEx = postIndex |
|
1086 |
+ default: |
|
1087 |
+ iNdEx = preIndex |
|
1088 |
+ skippy, err := skipLeases(dAtA[iNdEx:]) |
|
1089 |
+ if err != nil { |
|
1090 |
+ return err |
|
1091 |
+ } |
|
1092 |
+ if skippy < 0 { |
|
1093 |
+ return ErrInvalidLengthLeases |
|
1094 |
+ } |
|
1095 |
+ if (iNdEx + skippy) > l { |
|
1096 |
+ return io.ErrUnexpectedEOF |
|
1097 |
+ } |
|
1098 |
+ iNdEx += skippy |
|
1099 |
+ } |
|
1100 |
+ } |
|
1101 |
+ |
|
1102 |
+ if iNdEx > l { |
|
1103 |
+ return io.ErrUnexpectedEOF |
|
1104 |
+ } |
|
1105 |
+ return nil |
|
1106 |
+} |
|
1107 |
+func (m *CreateResponse) Unmarshal(dAtA []byte) error { |
|
1108 |
+ l := len(dAtA) |
|
1109 |
+ iNdEx := 0 |
|
1110 |
+ for iNdEx < l { |
|
1111 |
+ preIndex := iNdEx |
|
1112 |
+ var wire uint64 |
|
1113 |
+ for shift := uint(0); ; shift += 7 { |
|
1114 |
+ if shift >= 64 { |
|
1115 |
+ return ErrIntOverflowLeases |
|
1116 |
+ } |
|
1117 |
+ if iNdEx >= l { |
|
1118 |
+ return io.ErrUnexpectedEOF |
|
1119 |
+ } |
|
1120 |
+ b := dAtA[iNdEx] |
|
1121 |
+ iNdEx++ |
|
1122 |
+ wire |= (uint64(b) & 0x7F) << shift |
|
1123 |
+ if b < 0x80 { |
|
1124 |
+ break |
|
1125 |
+ } |
|
1126 |
+ } |
|
1127 |
+ fieldNum := int32(wire >> 3) |
|
1128 |
+ wireType := int(wire & 0x7) |
|
1129 |
+ if wireType == 4 { |
|
1130 |
+ return fmt.Errorf("proto: CreateResponse: wiretype end group for non-group") |
|
1131 |
+ } |
|
1132 |
+ if fieldNum <= 0 { |
|
1133 |
+ return fmt.Errorf("proto: CreateResponse: illegal tag %d (wire type %d)", fieldNum, wire) |
|
1134 |
+ } |
|
1135 |
+ switch fieldNum { |
|
1136 |
+ case 1: |
|
1137 |
+ if wireType != 2 { |
|
1138 |
+ return fmt.Errorf("proto: wrong wireType = %d for field Lease", wireType) |
|
1139 |
+ } |
|
1140 |
+ var msglen int |
|
1141 |
+ for shift := uint(0); ; shift += 7 { |
|
1142 |
+ if shift >= 64 { |
|
1143 |
+ return ErrIntOverflowLeases |
|
1144 |
+ } |
|
1145 |
+ if iNdEx >= l { |
|
1146 |
+ return io.ErrUnexpectedEOF |
|
1147 |
+ } |
|
1148 |
+ b := dAtA[iNdEx] |
|
1149 |
+ iNdEx++ |
|
1150 |
+ msglen |= (int(b) & 0x7F) << shift |
|
1151 |
+ if b < 0x80 { |
|
1152 |
+ break |
|
1153 |
+ } |
|
1154 |
+ } |
|
1155 |
+ if msglen < 0 { |
|
1156 |
+ return ErrInvalidLengthLeases |
|
1157 |
+ } |
|
1158 |
+ postIndex := iNdEx + msglen |
|
1159 |
+ if postIndex > l { |
|
1160 |
+ return io.ErrUnexpectedEOF |
|
1161 |
+ } |
|
1162 |
+ if m.Lease == nil { |
|
1163 |
+ m.Lease = &Lease{} |
|
1164 |
+ } |
|
1165 |
+ if err := m.Lease.Unmarshal(dAtA[iNdEx:postIndex]); err != nil { |
|
1166 |
+ return err |
|
1167 |
+ } |
|
1168 |
+ iNdEx = postIndex |
|
1169 |
+ default: |
|
1170 |
+ iNdEx = preIndex |
|
1171 |
+ skippy, err := skipLeases(dAtA[iNdEx:]) |
|
1172 |
+ if err != nil { |
|
1173 |
+ return err |
|
1174 |
+ } |
|
1175 |
+ if skippy < 0 { |
|
1176 |
+ return ErrInvalidLengthLeases |
|
1177 |
+ } |
|
1178 |
+ if (iNdEx + skippy) > l { |
|
1179 |
+ return io.ErrUnexpectedEOF |
|
1180 |
+ } |
|
1181 |
+ iNdEx += skippy |
|
1182 |
+ } |
|
1183 |
+ } |
|
1184 |
+ |
|
1185 |
+ if iNdEx > l { |
|
1186 |
+ return io.ErrUnexpectedEOF |
|
1187 |
+ } |
|
1188 |
+ return nil |
|
1189 |
+} |
|
1190 |
+func (m *DeleteRequest) Unmarshal(dAtA []byte) error { |
|
1191 |
+ l := len(dAtA) |
|
1192 |
+ iNdEx := 0 |
|
1193 |
+ for iNdEx < l { |
|
1194 |
+ preIndex := iNdEx |
|
1195 |
+ var wire uint64 |
|
1196 |
+ for shift := uint(0); ; shift += 7 { |
|
1197 |
+ if shift >= 64 { |
|
1198 |
+ return ErrIntOverflowLeases |
|
1199 |
+ } |
|
1200 |
+ if iNdEx >= l { |
|
1201 |
+ return io.ErrUnexpectedEOF |
|
1202 |
+ } |
|
1203 |
+ b := dAtA[iNdEx] |
|
1204 |
+ iNdEx++ |
|
1205 |
+ wire |= (uint64(b) & 0x7F) << shift |
|
1206 |
+ if b < 0x80 { |
|
1207 |
+ break |
|
1208 |
+ } |
|
1209 |
+ } |
|
1210 |
+ fieldNum := int32(wire >> 3) |
|
1211 |
+ wireType := int(wire & 0x7) |
|
1212 |
+ if wireType == 4 { |
|
1213 |
+ return fmt.Errorf("proto: DeleteRequest: wiretype end group for non-group") |
|
1214 |
+ } |
|
1215 |
+ if fieldNum <= 0 { |
|
1216 |
+ return fmt.Errorf("proto: DeleteRequest: illegal tag %d (wire type %d)", fieldNum, wire) |
|
1217 |
+ } |
|
1218 |
+ switch fieldNum { |
|
1219 |
+ case 1: |
|
1220 |
+ if wireType != 2 { |
|
1221 |
+ return fmt.Errorf("proto: wrong wireType = %d for field ID", wireType) |
|
1222 |
+ } |
|
1223 |
+ var stringLen uint64 |
|
1224 |
+ for shift := uint(0); ; shift += 7 { |
|
1225 |
+ if shift >= 64 { |
|
1226 |
+ return ErrIntOverflowLeases |
|
1227 |
+ } |
|
1228 |
+ if iNdEx >= l { |
|
1229 |
+ return io.ErrUnexpectedEOF |
|
1230 |
+ } |
|
1231 |
+ b := dAtA[iNdEx] |
|
1232 |
+ iNdEx++ |
|
1233 |
+ stringLen |= (uint64(b) & 0x7F) << shift |
|
1234 |
+ if b < 0x80 { |
|
1235 |
+ break |
|
1236 |
+ } |
|
1237 |
+ } |
|
1238 |
+ intStringLen := int(stringLen) |
|
1239 |
+ if intStringLen < 0 { |
|
1240 |
+ return ErrInvalidLengthLeases |
|
1241 |
+ } |
|
1242 |
+ postIndex := iNdEx + intStringLen |
|
1243 |
+ if postIndex > l { |
|
1244 |
+ return io.ErrUnexpectedEOF |
|
1245 |
+ } |
|
1246 |
+ m.ID = string(dAtA[iNdEx:postIndex]) |
|
1247 |
+ iNdEx = postIndex |
|
1248 |
+ default: |
|
1249 |
+ iNdEx = preIndex |
|
1250 |
+ skippy, err := skipLeases(dAtA[iNdEx:]) |
|
1251 |
+ if err != nil { |
|
1252 |
+ return err |
|
1253 |
+ } |
|
1254 |
+ if skippy < 0 { |
|
1255 |
+ return ErrInvalidLengthLeases |
|
1256 |
+ } |
|
1257 |
+ if (iNdEx + skippy) > l { |
|
1258 |
+ return io.ErrUnexpectedEOF |
|
1259 |
+ } |
|
1260 |
+ iNdEx += skippy |
|
1261 |
+ } |
|
1262 |
+ } |
|
1263 |
+ |
|
1264 |
+ if iNdEx > l { |
|
1265 |
+ return io.ErrUnexpectedEOF |
|
1266 |
+ } |
|
1267 |
+ return nil |
|
1268 |
+} |
|
1269 |
+func (m *ListRequest) Unmarshal(dAtA []byte) error { |
|
1270 |
+ l := len(dAtA) |
|
1271 |
+ iNdEx := 0 |
|
1272 |
+ for iNdEx < l { |
|
1273 |
+ preIndex := iNdEx |
|
1274 |
+ var wire uint64 |
|
1275 |
+ for shift := uint(0); ; shift += 7 { |
|
1276 |
+ if shift >= 64 { |
|
1277 |
+ return ErrIntOverflowLeases |
|
1278 |
+ } |
|
1279 |
+ if iNdEx >= l { |
|
1280 |
+ return io.ErrUnexpectedEOF |
|
1281 |
+ } |
|
1282 |
+ b := dAtA[iNdEx] |
|
1283 |
+ iNdEx++ |
|
1284 |
+ wire |= (uint64(b) & 0x7F) << shift |
|
1285 |
+ if b < 0x80 { |
|
1286 |
+ break |
|
1287 |
+ } |
|
1288 |
+ } |
|
1289 |
+ fieldNum := int32(wire >> 3) |
|
1290 |
+ wireType := int(wire & 0x7) |
|
1291 |
+ if wireType == 4 { |
|
1292 |
+ return fmt.Errorf("proto: ListRequest: wiretype end group for non-group") |
|
1293 |
+ } |
|
1294 |
+ if fieldNum <= 0 { |
|
1295 |
+ return fmt.Errorf("proto: ListRequest: illegal tag %d (wire type %d)", fieldNum, wire) |
|
1296 |
+ } |
|
1297 |
+ switch fieldNum { |
|
1298 |
+ case 1: |
|
1299 |
+ if wireType != 2 { |
|
1300 |
+ return fmt.Errorf("proto: wrong wireType = %d for field Filters", wireType) |
|
1301 |
+ } |
|
1302 |
+ var stringLen uint64 |
|
1303 |
+ for shift := uint(0); ; shift += 7 { |
|
1304 |
+ if shift >= 64 { |
|
1305 |
+ return ErrIntOverflowLeases |
|
1306 |
+ } |
|
1307 |
+ if iNdEx >= l { |
|
1308 |
+ return io.ErrUnexpectedEOF |
|
1309 |
+ } |
|
1310 |
+ b := dAtA[iNdEx] |
|
1311 |
+ iNdEx++ |
|
1312 |
+ stringLen |= (uint64(b) & 0x7F) << shift |
|
1313 |
+ if b < 0x80 { |
|
1314 |
+ break |
|
1315 |
+ } |
|
1316 |
+ } |
|
1317 |
+ intStringLen := int(stringLen) |
|
1318 |
+ if intStringLen < 0 { |
|
1319 |
+ return ErrInvalidLengthLeases |
|
1320 |
+ } |
|
1321 |
+ postIndex := iNdEx + intStringLen |
|
1322 |
+ if postIndex > l { |
|
1323 |
+ return io.ErrUnexpectedEOF |
|
1324 |
+ } |
|
1325 |
+ m.Filters = append(m.Filters, string(dAtA[iNdEx:postIndex])) |
|
1326 |
+ iNdEx = postIndex |
|
1327 |
+ default: |
|
1328 |
+ iNdEx = preIndex |
|
1329 |
+ skippy, err := skipLeases(dAtA[iNdEx:]) |
|
1330 |
+ if err != nil { |
|
1331 |
+ return err |
|
1332 |
+ } |
|
1333 |
+ if skippy < 0 { |
|
1334 |
+ return ErrInvalidLengthLeases |
|
1335 |
+ } |
|
1336 |
+ if (iNdEx + skippy) > l { |
|
1337 |
+ return io.ErrUnexpectedEOF |
|
1338 |
+ } |
|
1339 |
+ iNdEx += skippy |
|
1340 |
+ } |
|
1341 |
+ } |
|
1342 |
+ |
|
1343 |
+ if iNdEx > l { |
|
1344 |
+ return io.ErrUnexpectedEOF |
|
1345 |
+ } |
|
1346 |
+ return nil |
|
1347 |
+} |
|
1348 |
+func (m *ListResponse) Unmarshal(dAtA []byte) error { |
|
1349 |
+ l := len(dAtA) |
|
1350 |
+ iNdEx := 0 |
|
1351 |
+ for iNdEx < l { |
|
1352 |
+ preIndex := iNdEx |
|
1353 |
+ var wire uint64 |
|
1354 |
+ for shift := uint(0); ; shift += 7 { |
|
1355 |
+ if shift >= 64 { |
|
1356 |
+ return ErrIntOverflowLeases |
|
1357 |
+ } |
|
1358 |
+ if iNdEx >= l { |
|
1359 |
+ return io.ErrUnexpectedEOF |
|
1360 |
+ } |
|
1361 |
+ b := dAtA[iNdEx] |
|
1362 |
+ iNdEx++ |
|
1363 |
+ wire |= (uint64(b) & 0x7F) << shift |
|
1364 |
+ if b < 0x80 { |
|
1365 |
+ break |
|
1366 |
+ } |
|
1367 |
+ } |
|
1368 |
+ fieldNum := int32(wire >> 3) |
|
1369 |
+ wireType := int(wire & 0x7) |
|
1370 |
+ if wireType == 4 { |
|
1371 |
+ return fmt.Errorf("proto: ListResponse: wiretype end group for non-group") |
|
1372 |
+ } |
|
1373 |
+ if fieldNum <= 0 { |
|
1374 |
+ return fmt.Errorf("proto: ListResponse: illegal tag %d (wire type %d)", fieldNum, wire) |
|
1375 |
+ } |
|
1376 |
+ switch fieldNum { |
|
1377 |
+ case 1: |
|
1378 |
+ if wireType != 2 { |
|
1379 |
+ return fmt.Errorf("proto: wrong wireType = %d for field Leases", wireType) |
|
1380 |
+ } |
|
1381 |
+ var msglen int |
|
1382 |
+ for shift := uint(0); ; shift += 7 { |
|
1383 |
+ if shift >= 64 { |
|
1384 |
+ return ErrIntOverflowLeases |
|
1385 |
+ } |
|
1386 |
+ if iNdEx >= l { |
|
1387 |
+ return io.ErrUnexpectedEOF |
|
1388 |
+ } |
|
1389 |
+ b := dAtA[iNdEx] |
|
1390 |
+ iNdEx++ |
|
1391 |
+ msglen |= (int(b) & 0x7F) << shift |
|
1392 |
+ if b < 0x80 { |
|
1393 |
+ break |
|
1394 |
+ } |
|
1395 |
+ } |
|
1396 |
+ if msglen < 0 { |
|
1397 |
+ return ErrInvalidLengthLeases |
|
1398 |
+ } |
|
1399 |
+ postIndex := iNdEx + msglen |
|
1400 |
+ if postIndex > l { |
|
1401 |
+ return io.ErrUnexpectedEOF |
|
1402 |
+ } |
|
1403 |
+ m.Leases = append(m.Leases, &Lease{}) |
|
1404 |
+ if err := m.Leases[len(m.Leases)-1].Unmarshal(dAtA[iNdEx:postIndex]); err != nil { |
|
1405 |
+ return err |
|
1406 |
+ } |
|
1407 |
+ iNdEx = postIndex |
|
1408 |
+ default: |
|
1409 |
+ iNdEx = preIndex |
|
1410 |
+ skippy, err := skipLeases(dAtA[iNdEx:]) |
|
1411 |
+ if err != nil { |
|
1412 |
+ return err |
|
1413 |
+ } |
|
1414 |
+ if skippy < 0 { |
|
1415 |
+ return ErrInvalidLengthLeases |
|
1416 |
+ } |
|
1417 |
+ if (iNdEx + skippy) > l { |
|
1418 |
+ return io.ErrUnexpectedEOF |
|
1419 |
+ } |
|
1420 |
+ iNdEx += skippy |
|
1421 |
+ } |
|
1422 |
+ } |
|
1423 |
+ |
|
1424 |
+ if iNdEx > l { |
|
1425 |
+ return io.ErrUnexpectedEOF |
|
1426 |
+ } |
|
1427 |
+ return nil |
|
1428 |
+} |
|
1429 |
+func skipLeases(dAtA []byte) (n int, err error) { |
|
1430 |
+ l := len(dAtA) |
|
1431 |
+ iNdEx := 0 |
|
1432 |
+ for iNdEx < l { |
|
1433 |
+ var wire uint64 |
|
1434 |
+ for shift := uint(0); ; shift += 7 { |
|
1435 |
+ if shift >= 64 { |
|
1436 |
+ return 0, ErrIntOverflowLeases |
|
1437 |
+ } |
|
1438 |
+ if iNdEx >= l { |
|
1439 |
+ return 0, io.ErrUnexpectedEOF |
|
1440 |
+ } |
|
1441 |
+ b := dAtA[iNdEx] |
|
1442 |
+ iNdEx++ |
|
1443 |
+ wire |= (uint64(b) & 0x7F) << shift |
|
1444 |
+ if b < 0x80 { |
|
1445 |
+ break |
|
1446 |
+ } |
|
1447 |
+ } |
|
1448 |
+ wireType := int(wire & 0x7) |
|
1449 |
+ switch wireType { |
|
1450 |
+ case 0: |
|
1451 |
+ for shift := uint(0); ; shift += 7 { |
|
1452 |
+ if shift >= 64 { |
|
1453 |
+ return 0, ErrIntOverflowLeases |
|
1454 |
+ } |
|
1455 |
+ if iNdEx >= l { |
|
1456 |
+ return 0, io.ErrUnexpectedEOF |
|
1457 |
+ } |
|
1458 |
+ iNdEx++ |
|
1459 |
+ if dAtA[iNdEx-1] < 0x80 { |
|
1460 |
+ break |
|
1461 |
+ } |
|
1462 |
+ } |
|
1463 |
+ return iNdEx, nil |
|
1464 |
+ case 1: |
|
1465 |
+ iNdEx += 8 |
|
1466 |
+ return iNdEx, nil |
|
1467 |
+ case 2: |
|
1468 |
+ var length int |
|
1469 |
+ for shift := uint(0); ; shift += 7 { |
|
1470 |
+ if shift >= 64 { |
|
1471 |
+ return 0, ErrIntOverflowLeases |
|
1472 |
+ } |
|
1473 |
+ if iNdEx >= l { |
|
1474 |
+ return 0, io.ErrUnexpectedEOF |
|
1475 |
+ } |
|
1476 |
+ b := dAtA[iNdEx] |
|
1477 |
+ iNdEx++ |
|
1478 |
+ length |= (int(b) & 0x7F) << shift |
|
1479 |
+ if b < 0x80 { |
|
1480 |
+ break |
|
1481 |
+ } |
|
1482 |
+ } |
|
1483 |
+ iNdEx += length |
|
1484 |
+ if length < 0 { |
|
1485 |
+ return 0, ErrInvalidLengthLeases |
|
1486 |
+ } |
|
1487 |
+ return iNdEx, nil |
|
1488 |
+ case 3: |
|
1489 |
+ for { |
|
1490 |
+ var innerWire uint64 |
|
1491 |
+ var start int = iNdEx |
|
1492 |
+ for shift := uint(0); ; shift += 7 { |
|
1493 |
+ if shift >= 64 { |
|
1494 |
+ return 0, ErrIntOverflowLeases |
|
1495 |
+ } |
|
1496 |
+ if iNdEx >= l { |
|
1497 |
+ return 0, io.ErrUnexpectedEOF |
|
1498 |
+ } |
|
1499 |
+ b := dAtA[iNdEx] |
|
1500 |
+ iNdEx++ |
|
1501 |
+ innerWire |= (uint64(b) & 0x7F) << shift |
|
1502 |
+ if b < 0x80 { |
|
1503 |
+ break |
|
1504 |
+ } |
|
1505 |
+ } |
|
1506 |
+ innerWireType := int(innerWire & 0x7) |
|
1507 |
+ if innerWireType == 4 { |
|
1508 |
+ break |
|
1509 |
+ } |
|
1510 |
+ next, err := skipLeases(dAtA[start:]) |
|
1511 |
+ if err != nil { |
|
1512 |
+ return 0, err |
|
1513 |
+ } |
|
1514 |
+ iNdEx = start + next |
|
1515 |
+ } |
|
1516 |
+ return iNdEx, nil |
|
1517 |
+ case 4: |
|
1518 |
+ return iNdEx, nil |
|
1519 |
+ case 5: |
|
1520 |
+ iNdEx += 4 |
|
1521 |
+ return iNdEx, nil |
|
1522 |
+ default: |
|
1523 |
+ return 0, fmt.Errorf("proto: illegal wireType %d", wireType) |
|
1524 |
+ } |
|
1525 |
+ } |
|
1526 |
+ panic("unreachable") |
|
1527 |
+} |
|
1528 |
+ |
|
1529 |
+var ( |
|
1530 |
+ ErrInvalidLengthLeases = fmt.Errorf("proto: negative length found during unmarshaling") |
|
1531 |
+ ErrIntOverflowLeases = fmt.Errorf("proto: integer overflow") |
|
1532 |
+) |
|
1533 |
+ |
|
1534 |
+func init() { |
|
1535 |
+ proto.RegisterFile("github.com/containerd/containerd/api/services/leases/v1/leases.proto", fileDescriptorLeases) |
|
1536 |
+} |
|
1537 |
+ |
|
1538 |
+var fileDescriptorLeases = []byte{ |
|
1539 |
+ // 501 bytes of a gzipped FileDescriptorProto |
|
1540 |
+ 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xac, 0x94, 0xdf, 0x8a, 0xd3, 0x40, |
|
1541 |
+ 0x14, 0xc6, 0x3b, 0xa9, 0x8d, 0xf6, 0xd4, 0x15, 0x19, 0x96, 0x25, 0x44, 0x4c, 0x4b, 0x10, 0xb6, |
|
1542 |
+ 0xf8, 0x67, 0xe2, 0xd6, 0x9b, 0x75, 0x15, 0xc1, 0x6e, 0x17, 0x14, 0x82, 0x48, 0xf0, 0x42, 0xbc, |
|
1543 |
+ 0x59, 0xd2, 0xf6, 0x6c, 0x0c, 0xa6, 0x9d, 0x98, 0x99, 0x16, 0x7a, 0xe7, 0x23, 0xf8, 0x08, 0x3e, |
|
1544 |
+ 0x84, 0x0f, 0xd1, 0x4b, 0x2f, 0xbd, 0x5a, 0xdd, 0xdc, 0xf9, 0x16, 0x92, 0x99, 0x84, 0xfd, 0x23, |
|
1545 |
+ 0xda, 0x2a, 0xde, 0x9d, 0xc9, 0x7c, 0xdf, 0x39, 0xbf, 0xf3, 0xc1, 0x04, 0x06, 0x51, 0x2c, 0xdf, |
|
1546 |
+ 0xce, 0x86, 0x6c, 0xc4, 0x27, 0xde, 0x88, 0x4f, 0x65, 0x18, 0x4f, 0x31, 0x1b, 0x9f, 0x2d, 0xc3, |
|
1547 |
+ 0x34, 0xf6, 0x04, 0x66, 0xf3, 0x78, 0x84, 0xc2, 0x4b, 0x30, 0x14, 0x28, 0xbc, 0xf9, 0x4e, 0x59, |
|
1548 |
+ 0xb1, 0x34, 0xe3, 0x92, 0xd3, 0x9b, 0xa7, 0x7a, 0x56, 0x69, 0x59, 0xa9, 0x98, 0xef, 0xd8, 0x9b, |
|
1549 |
+ 0x11, 0x8f, 0xb8, 0x52, 0x7a, 0x45, 0xa5, 0x4d, 0xf6, 0x8d, 0x88, 0xf3, 0x28, 0x41, 0x4f, 0x9d, |
|
1550 |
+ 0x86, 0xb3, 0x23, 0x0f, 0x27, 0xa9, 0x5c, 0x94, 0x97, 0xed, 0x8b, 0x97, 0x32, 0x9e, 0xa0, 0x90, |
|
1551 |
+ 0xe1, 0x24, 0xd5, 0x02, 0xf7, 0x07, 0x81, 0x86, 0x5f, 0x4c, 0xa0, 0x5b, 0x60, 0xc4, 0x63, 0x8b, |
|
1552 |
+ 0x74, 0x48, 0xb7, 0xd9, 0x37, 0xf3, 0xe3, 0xb6, 0xf1, 0x7c, 0x10, 0x18, 0xf1, 0x98, 0xee, 0x03, |
|
1553 |
+ 0x8c, 0x32, 0x0c, 0x25, 0x8e, 0x0f, 0x43, 0x69, 0x19, 0x1d, 0xd2, 0x6d, 0xf5, 0x6c, 0xa6, 0xfb, |
|
1554 |
+ 0xb2, 0xaa, 0x2f, 0x7b, 0x55, 0xf5, 0xed, 0x5f, 0x59, 0x1e, 0xb7, 0x6b, 0x1f, 0xbf, 0xb5, 0x49, |
|
1555 |
+ 0xd0, 0x2c, 0x7d, 0x4f, 0x25, 0x7d, 0x06, 0x66, 0x12, 0x0e, 0x31, 0x11, 0x56, 0xbd, 0x53, 0xef, |
|
1556 |
+ 0xb6, 0x7a, 0xf7, 0xd9, 0x1f, 0x57, 0x65, 0x0a, 0x89, 0xf9, 0xca, 0x72, 0x30, 0x95, 0xd9, 0x22, |
|
1557 |
+ 0x28, 0xfd, 0xf6, 0x43, 0x68, 0x9d, 0xf9, 0x4c, 0xaf, 0x43, 0xfd, 0x1d, 0x2e, 0x34, 0x76, 0x50, |
|
1558 |
+ 0x94, 0x74, 0x13, 0x1a, 0xf3, 0x30, 0x99, 0xa1, 0x42, 0x6d, 0x06, 0xfa, 0xb0, 0x67, 0xec, 0x12, |
|
1559 |
+ 0xf7, 0x33, 0x81, 0x8d, 0x7d, 0x85, 0x14, 0xe0, 0xfb, 0x19, 0x0a, 0xf9, 0xdb, 0x9d, 0x5f, 0x5e, |
|
1560 |
+ 0xc0, 0xdd, 0x5d, 0x81, 0x7b, 0xae, 0xeb, 0xff, 0xc6, 0xf6, 0xe1, 0x5a, 0xd5, 0x5f, 0xa4, 0x7c, |
|
1561 |
+ 0x2a, 0x90, 0xee, 0x41, 0x43, 0xcd, 0x56, 0xfe, 0x56, 0xef, 0xd6, 0x3a, 0x61, 0x06, 0xda, 0xe2, |
|
1562 |
+ 0x6e, 0xc3, 0xc6, 0x00, 0x13, 0x5c, 0x99, 0x81, 0xbb, 0x0d, 0x2d, 0x3f, 0x16, 0xb2, 0x92, 0x59, |
|
1563 |
+ 0x70, 0xf9, 0x28, 0x4e, 0x24, 0x66, 0xc2, 0x22, 0x9d, 0x7a, 0xb7, 0x19, 0x54, 0x47, 0xd7, 0x87, |
|
1564 |
+ 0xab, 0x5a, 0x58, 0xd2, 0x3d, 0x06, 0x53, 0xcf, 0x56, 0xc2, 0x75, 0xf1, 0x4a, 0x4f, 0xef, 0x93, |
|
1565 |
+ 0x01, 0xa6, 0xfa, 0x22, 0x28, 0x82, 0xa9, 0x17, 0xa7, 0x77, 0xff, 0x26, 0x7f, 0xfb, 0xde, 0x9a, |
|
1566 |
+ 0xea, 0x92, 0xf7, 0x05, 0x98, 0x3a, 0x91, 0x95, 0x63, 0xce, 0x05, 0x67, 0x6f, 0xfd, 0xf2, 0x08, |
|
1567 |
+ 0x0e, 0x8a, 0x97, 0x47, 0x0f, 0xe1, 0x52, 0x91, 0x07, 0xbd, 0xbd, 0x6a, 0xef, 0xd3, 0x74, 0xed, |
|
1568 |
+ 0x3b, 0x6b, 0x69, 0x35, 0x70, 0xff, 0xf5, 0xf2, 0xc4, 0xa9, 0x7d, 0x3d, 0x71, 0x6a, 0x1f, 0x72, |
|
1569 |
+ 0x87, 0x2c, 0x73, 0x87, 0x7c, 0xc9, 0x1d, 0xf2, 0x3d, 0x77, 0xc8, 0x9b, 0x27, 0xff, 0xf8, 0x1b, |
|
1570 |
+ 0x7a, 0xa4, 0xab, 0xa1, 0xa9, 0x56, 0x79, 0xf0, 0x33, 0x00, 0x00, 0xff, 0xff, 0x1d, 0xb9, 0xa6, |
|
1571 |
+ 0x63, 0xcf, 0x04, 0x00, 0x00, |
|
1572 |
+} |
0 | 1573 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,58 @@ |
0 |
+syntax = "proto3"; |
|
1 |
+ |
|
2 |
+package containerd.services.leases.v1; |
|
3 |
+ |
|
4 |
+import "gogoproto/gogo.proto"; |
|
5 |
+import "google/protobuf/empty.proto"; |
|
6 |
+import "google/protobuf/timestamp.proto"; |
|
7 |
+ |
|
8 |
+option go_package = "github.com/containerd/containerd/api/services/leases/v1;leases"; |
|
9 |
+ |
|
10 |
+// Leases service manages resources leases within the metadata store. |
|
11 |
+service Leases { |
|
12 |
+ // Create creates a new lease for managing changes to metadata. A lease |
|
13 |
+ // can be used to protect objects from being removed. |
|
14 |
+ rpc Create(CreateRequest) returns (CreateResponse); |
|
15 |
+ |
|
16 |
+ // Delete deletes the lease and makes any unreferenced objects created |
|
17 |
+ // during the lease eligible for garbage collection if not referenced |
|
18 |
+ // or retained by other resources during the lease. |
|
19 |
+ rpc Delete(DeleteRequest) returns (google.protobuf.Empty); |
|
20 |
+ |
|
21 |
+ // ListTransactions lists all active leases, returning the full list of |
|
22 |
+ // leases and optionally including the referenced resources. |
|
23 |
+ rpc List(ListRequest) returns (ListResponse); |
|
24 |
+} |
|
25 |
+ |
|
26 |
+// Lease is an object which retains resources while it exists. |
|
27 |
+message Lease { |
|
28 |
+ string id = 1; |
|
29 |
+ |
|
30 |
+ google.protobuf.Timestamp created_at = 2 [(gogoproto.stdtime) = true, (gogoproto.nullable) = false]; |
|
31 |
+ |
|
32 |
+ map<string, string> labels = 3; |
|
33 |
+} |
|
34 |
+ |
|
35 |
+message CreateRequest { |
|
36 |
+ // ID is used to identity the lease, when the id is not set the service |
|
37 |
+ // generates a random identifier for the lease. |
|
38 |
+ string id = 1; |
|
39 |
+ |
|
40 |
+ map<string, string> labels = 3; |
|
41 |
+} |
|
42 |
+ |
|
43 |
+message CreateResponse { |
|
44 |
+ Lease lease = 1; |
|
45 |
+} |
|
46 |
+ |
|
47 |
+message DeleteRequest { |
|
48 |
+ string id = 1; |
|
49 |
+} |
|
50 |
+ |
|
51 |
+message ListRequest { |
|
52 |
+ repeated string filters = 1; |
|
53 |
+} |
|
54 |
+ |
|
55 |
+message ListResponse { |
|
56 |
+ repeated Lease leases = 1; |
|
57 |
+} |
... | ... |
@@ -22,9 +22,11 @@ import ( |
22 | 22 |
versionservice "github.com/containerd/containerd/api/services/version/v1" |
23 | 23 |
"github.com/containerd/containerd/containers" |
24 | 24 |
"github.com/containerd/containerd/content" |
25 |
+ "github.com/containerd/containerd/dialer" |
|
25 | 26 |
"github.com/containerd/containerd/diff" |
26 | 27 |
"github.com/containerd/containerd/errdefs" |
27 | 28 |
"github.com/containerd/containerd/images" |
29 |
+ "github.com/containerd/containerd/namespaces" |
|
28 | 30 |
"github.com/containerd/containerd/platforms" |
29 | 31 |
"github.com/containerd/containerd/plugin" |
30 | 32 |
"github.com/containerd/containerd/reference" |
... | ... |
@@ -34,6 +36,7 @@ import ( |
34 | 34 |
contentservice "github.com/containerd/containerd/services/content" |
35 | 35 |
diffservice "github.com/containerd/containerd/services/diff" |
36 | 36 |
imagesservice "github.com/containerd/containerd/services/images" |
37 |
+ namespacesservice "github.com/containerd/containerd/services/namespaces" |
|
37 | 38 |
snapshotservice "github.com/containerd/containerd/services/snapshot" |
38 | 39 |
"github.com/containerd/containerd/snapshot" |
39 | 40 |
"github.com/containerd/typeurl" |
... | ... |
@@ -70,7 +73,7 @@ func New(address string, opts ...ClientOpt) (*Client, error) { |
70 | 70 |
grpc.WithTimeout(60 * time.Second), |
71 | 71 |
grpc.FailOnNonTempDialError(true), |
72 | 72 |
grpc.WithBackoffMaxDelay(3 * time.Second), |
73 |
- grpc.WithDialer(Dialer), |
|
73 |
+ grpc.WithDialer(dialer.Dialer), |
|
74 | 74 |
} |
75 | 75 |
if len(copts.dialOptions) > 0 { |
76 | 76 |
gopts = copts.dialOptions |
... | ... |
@@ -82,7 +85,7 @@ func New(address string, opts ...ClientOpt) (*Client, error) { |
82 | 82 |
grpc.WithStreamInterceptor(stream), |
83 | 83 |
) |
84 | 84 |
} |
85 |
- conn, err := grpc.Dial(DialAddress(address), gopts...) |
|
85 |
+ conn, err := grpc.Dial(dialer.DialAddress(address), gopts...) |
|
86 | 86 |
if err != nil { |
87 | 87 |
return nil, errors.Wrapf(err, "failed to dial %q", address) |
88 | 88 |
} |
... | ... |
@@ -135,6 +138,12 @@ func (c *Client) Containers(ctx context.Context, filters ...string) ([]Container |
135 | 135 |
// NewContainer will create a new container in container with the provided id |
136 | 136 |
// the id must be unique within the namespace |
137 | 137 |
func (c *Client) NewContainer(ctx context.Context, id string, opts ...NewContainerOpts) (Container, error) { |
138 |
+ ctx, done, err := c.withLease(ctx) |
|
139 |
+ if err != nil { |
|
140 |
+ return nil, err |
|
141 |
+ } |
|
142 |
+ defer done() |
|
143 |
+ |
|
138 | 144 |
container := containers.Container{ |
139 | 145 |
ID: id, |
140 | 146 |
Runtime: containers.RuntimeInfo{ |
... | ... |
@@ -210,6 +219,12 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image |
210 | 210 |
} |
211 | 211 |
store := c.ContentStore() |
212 | 212 |
|
213 |
+ ctx, done, err := c.withLease(ctx) |
|
214 |
+ if err != nil { |
|
215 |
+ return nil, err |
|
216 |
+ } |
|
217 |
+ defer done() |
|
218 |
+ |
|
213 | 219 |
name, desc, err := pullCtx.Resolver.Resolve(ctx, ref) |
214 | 220 |
if err != nil { |
215 | 221 |
return nil, err |
... | ... |
@@ -228,7 +243,7 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image |
228 | 228 |
handler = images.Handlers(append(pullCtx.BaseHandlers, schema1Converter)...) |
229 | 229 |
} else { |
230 | 230 |
handler = images.Handlers(append(pullCtx.BaseHandlers, |
231 |
- remotes.FetchHandler(store, fetcher, desc), |
|
231 |
+ remotes.FetchHandler(store, fetcher), |
|
232 | 232 |
images.ChildrenHandler(store, platforms.Default()))..., |
233 | 233 |
) |
234 | 234 |
} |
... | ... |
@@ -265,11 +280,6 @@ func (c *Client) Pull(ctx context.Context, ref string, opts ...RemoteOpt) (Image |
265 | 265 |
imgrec = created |
266 | 266 |
} |
267 | 267 |
|
268 |
- // Remove root tag from manifest now that image refers to it |
|
269 |
- if _, err := store.Update(ctx, content.Info{Digest: desc.Digest}, "labels.containerd.io/gc.root"); err != nil { |
|
270 |
- return nil, errors.Wrap(err, "failed to remove manifest root tag") |
|
271 |
- } |
|
272 |
- |
|
273 | 268 |
img := &image{ |
274 | 269 |
client: c, |
275 | 270 |
i: imgrec, |
... | ... |
@@ -414,9 +424,9 @@ func (c *Client) Close() error { |
414 | 414 |
return c.conn.Close() |
415 | 415 |
} |
416 | 416 |
|
417 |
-// NamespaceService returns the underlying NamespacesClient |
|
418 |
-func (c *Client) NamespaceService() namespacesapi.NamespacesClient { |
|
419 |
- return namespacesapi.NewNamespacesClient(c.conn) |
|
417 |
+// NamespaceService returns the underlying Namespaces Store |
|
418 |
+func (c *Client) NamespaceService() namespaces.Store { |
|
419 |
+ return namespacesservice.NewStoreFromClient(namespacesapi.NewNamespacesClient(c.conn)) |
|
420 | 420 |
} |
421 | 421 |
|
422 | 422 |
// ContainerService returns the underlying container Store |
... | ... |
@@ -449,6 +459,7 @@ func (c *Client) DiffService() diff.Differ { |
449 | 449 |
return diffservice.NewDiffServiceFromClient(diffapi.NewDiffClient(c.conn)) |
450 | 450 |
} |
451 | 451 |
|
452 |
+// IntrospectionService returns the underlying Introspection Client |
|
452 | 453 |
func (c *Client) IntrospectionService() introspectionapi.IntrospectionClient { |
453 | 454 |
return introspectionapi.NewIntrospectionClient(c.conn) |
454 | 455 |
} |
... | ... |
@@ -580,6 +591,13 @@ func (c *Client) Import(ctx context.Context, ref string, reader io.Reader, opts |
580 | 580 |
if err != nil { |
581 | 581 |
return nil, err |
582 | 582 |
} |
583 |
+ |
|
584 |
+ ctx, done, err := c.withLease(ctx) |
|
585 |
+ if err != nil { |
|
586 |
+ return nil, err |
|
587 |
+ } |
|
588 |
+ defer done() |
|
589 |
+ |
|
583 | 590 |
switch iopts.format { |
584 | 591 |
case ociImageFormat: |
585 | 592 |
return c.importFromOCITar(ctx, ref, reader, iopts) |
... | ... |
@@ -2,12 +2,10 @@ package containerd |
2 | 2 |
|
3 | 3 |
import ( |
4 | 4 |
"context" |
5 |
- "time" |
|
6 | 5 |
|
7 | 6 |
"github.com/containerd/containerd/containers" |
8 | 7 |
"github.com/containerd/containerd/errdefs" |
9 | 8 |
"github.com/containerd/containerd/platforms" |
10 |
- "github.com/containerd/containerd/snapshot" |
|
11 | 9 |
"github.com/containerd/typeurl" |
12 | 10 |
"github.com/gogo/protobuf/types" |
13 | 11 |
"github.com/opencontainers/image-spec/identity" |
... | ... |
@@ -93,11 +91,8 @@ func WithNewSnapshot(id string, i Image) NewContainerOpts { |
93 | 93 |
return err |
94 | 94 |
} |
95 | 95 |
setSnapshotterIfEmpty(c) |
96 |
- labels := map[string]string{ |
|
97 |
- "containerd.io/gc.root": time.Now().String(), |
|
98 |
- } |
|
99 | 96 |
parent := identity.ChainID(diffIDs).String() |
100 |
- if _, err := client.SnapshotService(c.Snapshotter).Prepare(ctx, id, parent, snapshot.WithLabels(labels)); err != nil { |
|
97 |
+ if _, err := client.SnapshotService(c.Snapshotter).Prepare(ctx, id, parent); err != nil { |
|
101 | 98 |
return err |
102 | 99 |
} |
103 | 100 |
c.SnapshotKey = id |
... | ... |
@@ -126,11 +121,8 @@ func WithNewSnapshotView(id string, i Image) NewContainerOpts { |
126 | 126 |
return err |
127 | 127 |
} |
128 | 128 |
setSnapshotterIfEmpty(c) |
129 |
- labels := map[string]string{ |
|
130 |
- "containerd.io/gc.root": time.Now().String(), |
|
131 |
- } |
|
132 | 129 |
parent := identity.ChainID(diffIDs).String() |
133 |
- if _, err := client.SnapshotService(c.Snapshotter).View(ctx, id, parent, snapshot.WithLabels(labels)); err != nil { |
|
130 |
+ if _, err := client.SnapshotService(c.Snapshotter).View(ctx, id, parent); err != nil { |
|
134 | 131 |
return err |
135 | 132 |
} |
136 | 133 |
c.SnapshotKey = id |
... | ... |
@@ -8,6 +8,7 @@ import ( |
8 | 8 |
"os" |
9 | 9 |
"path/filepath" |
10 | 10 |
"strconv" |
11 |
+ "strings" |
|
11 | 12 |
"sync" |
12 | 13 |
"time" |
13 | 14 |
|
... | ... |
@@ -27,6 +28,19 @@ var ( |
27 | 27 |
} |
28 | 28 |
) |
29 | 29 |
|
30 |
+// LabelStore is used to store mutable labels for digests |
|
31 |
+type LabelStore interface { |
|
32 |
+ // Get returns all the labels for the given digest |
|
33 |
+ Get(digest.Digest) (map[string]string, error) |
|
34 |
+ |
|
35 |
+ // Set sets all the labels for a given digest |
|
36 |
+ Set(digest.Digest, map[string]string) error |
|
37 |
+ |
|
38 |
+ // Update replaces the given labels for a digest, |
|
39 |
+ // a key with an empty value removes a label. |
|
40 |
+ Update(digest.Digest, map[string]string) (map[string]string, error) |
|
41 |
+} |
|
42 |
+ |
|
30 | 43 |
// Store is digest-keyed store for content. All data written into the store is |
31 | 44 |
// stored under a verifiable digest. |
32 | 45 |
// |
... | ... |
@@ -34,16 +48,27 @@ var ( |
34 | 34 |
// including resumable ingest. |
35 | 35 |
type store struct { |
36 | 36 |
root string |
37 |
+ ls LabelStore |
|
37 | 38 |
} |
38 | 39 |
|
39 | 40 |
// NewStore returns a local content store |
40 | 41 |
func NewStore(root string) (content.Store, error) { |
42 |
+ return NewLabeledStore(root, nil) |
|
43 |
+} |
|
44 |
+ |
|
45 |
+// NewLabeledStore returns a new content store using the provided label store |
|
46 |
+// |
|
47 |
+// Note: content stores which are used underneath a metadata store may not |
|
48 |
+// require labels and should use `NewStore`. `NewLabeledStore` is primarily |
|
49 |
+// useful for tests or standalone implementations. |
|
50 |
+func NewLabeledStore(root string, ls LabelStore) (content.Store, error) { |
|
41 | 51 |
if err := os.MkdirAll(filepath.Join(root, "ingest"), 0777); err != nil && !os.IsExist(err) { |
42 | 52 |
return nil, err |
43 | 53 |
} |
44 | 54 |
|
45 | 55 |
return &store{ |
46 | 56 |
root: root, |
57 |
+ ls: ls, |
|
47 | 58 |
}, nil |
48 | 59 |
} |
49 | 60 |
|
... | ... |
@@ -57,16 +82,23 @@ func (s *store) Info(ctx context.Context, dgst digest.Digest) (content.Info, err |
57 | 57 |
|
58 | 58 |
return content.Info{}, err |
59 | 59 |
} |
60 |
- |
|
61 |
- return s.info(dgst, fi), nil |
|
60 |
+ var labels map[string]string |
|
61 |
+ if s.ls != nil { |
|
62 |
+ labels, err = s.ls.Get(dgst) |
|
63 |
+ if err != nil { |
|
64 |
+ return content.Info{}, err |
|
65 |
+ } |
|
66 |
+ } |
|
67 |
+ return s.info(dgst, fi, labels), nil |
|
62 | 68 |
} |
63 | 69 |
|
64 |
-func (s *store) info(dgst digest.Digest, fi os.FileInfo) content.Info { |
|
70 |
+func (s *store) info(dgst digest.Digest, fi os.FileInfo, labels map[string]string) content.Info { |
|
65 | 71 |
return content.Info{ |
66 | 72 |
Digest: dgst, |
67 | 73 |
Size: fi.Size(), |
68 | 74 |
CreatedAt: fi.ModTime(), |
69 |
- UpdatedAt: fi.ModTime(), |
|
75 |
+ UpdatedAt: getATime(fi), |
|
76 |
+ Labels: labels, |
|
70 | 77 |
} |
71 | 78 |
} |
72 | 79 |
|
... | ... |
@@ -111,8 +143,66 @@ func (s *store) Delete(ctx context.Context, dgst digest.Digest) error { |
111 | 111 |
} |
112 | 112 |
|
113 | 113 |
func (s *store) Update(ctx context.Context, info content.Info, fieldpaths ...string) (content.Info, error) { |
114 |
- // TODO: Support persisting and updating mutable content data |
|
115 |
- return content.Info{}, errors.Wrapf(errdefs.ErrFailedPrecondition, "update not supported on immutable content store") |
|
114 |
+ if s.ls == nil { |
|
115 |
+ return content.Info{}, errors.Wrapf(errdefs.ErrFailedPrecondition, "update not supported on immutable content store") |
|
116 |
+ } |
|
117 |
+ |
|
118 |
+ p := s.blobPath(info.Digest) |
|
119 |
+ fi, err := os.Stat(p) |
|
120 |
+ if err != nil { |
|
121 |
+ if os.IsNotExist(err) { |
|
122 |
+ err = errors.Wrapf(errdefs.ErrNotFound, "content %v", info.Digest) |
|
123 |
+ } |
|
124 |
+ |
|
125 |
+ return content.Info{}, err |
|
126 |
+ } |
|
127 |
+ |
|
128 |
+ var ( |
|
129 |
+ all bool |
|
130 |
+ labels map[string]string |
|
131 |
+ ) |
|
132 |
+ if len(fieldpaths) > 0 { |
|
133 |
+ for _, path := range fieldpaths { |
|
134 |
+ if strings.HasPrefix(path, "labels.") { |
|
135 |
+ if labels == nil { |
|
136 |
+ labels = map[string]string{} |
|
137 |
+ } |
|
138 |
+ |
|
139 |
+ key := strings.TrimPrefix(path, "labels.") |
|
140 |
+ labels[key] = info.Labels[key] |
|
141 |
+ continue |
|
142 |
+ } |
|
143 |
+ |
|
144 |
+ switch path { |
|
145 |
+ case "labels": |
|
146 |
+ all = true |
|
147 |
+ labels = info.Labels |
|
148 |
+ default: |
|
149 |
+ return content.Info{}, errors.Wrapf(errdefs.ErrInvalidArgument, "cannot update %q field on content info %q", path, info.Digest) |
|
150 |
+ } |
|
151 |
+ } |
|
152 |
+ } else { |
|
153 |
+ all = true |
|
154 |
+ labels = info.Labels |
|
155 |
+ } |
|
156 |
+ |
|
157 |
+ if all { |
|
158 |
+ err = s.ls.Set(info.Digest, labels) |
|
159 |
+ } else { |
|
160 |
+ labels, err = s.ls.Update(info.Digest, labels) |
|
161 |
+ } |
|
162 |
+ if err != nil { |
|
163 |
+ return content.Info{}, err |
|
164 |
+ } |
|
165 |
+ |
|
166 |
+ info = s.info(info.Digest, fi, labels) |
|
167 |
+ info.UpdatedAt = time.Now() |
|
168 |
+ |
|
169 |
+ if err := os.Chtimes(p, info.UpdatedAt, info.CreatedAt); err != nil { |
|
170 |
+ log.G(ctx).WithError(err).Warnf("could not change access time for %s", info.Digest) |
|
171 |
+ } |
|
172 |
+ |
|
173 |
+ return info, nil |
|
116 | 174 |
} |
117 | 175 |
|
118 | 176 |
func (s *store) Walk(ctx context.Context, fn content.WalkFunc, filters ...string) error { |
... | ... |
@@ -154,7 +244,14 @@ func (s *store) Walk(ctx context.Context, fn content.WalkFunc, filters ...string |
154 | 154 |
// store or extra paths not expected previously. |
155 | 155 |
} |
156 | 156 |
|
157 |
- return fn(s.info(dgst, fi)) |
|
157 |
+ var labels map[string]string |
|
158 |
+ if s.ls != nil { |
|
159 |
+ labels, err = s.ls.Get(dgst) |
|
160 |
+ if err != nil { |
|
161 |
+ return err |
|
162 |
+ } |
|
163 |
+ } |
|
164 |
+ return fn(s.info(dgst, fi, labels)) |
|
158 | 165 |
}) |
159 | 166 |
} |
160 | 167 |
|
... | ... |
@@ -18,3 +18,12 @@ func getStartTime(fi os.FileInfo) time.Time { |
18 | 18 |
|
19 | 19 |
return fi.ModTime() |
20 | 20 |
} |
21 |
+ |
|
22 |
+func getATime(fi os.FileInfo) time.Time { |
|
23 |
+ if st, ok := fi.Sys().(*syscall.Stat_t); ok { |
|
24 |
+ return time.Unix(int64(sys.StatAtime(st).Sec), |
|
25 |
+ int64(sys.StatAtime(st).Nsec)) |
|
26 |
+ } |
|
27 |
+ |
|
28 |
+ return fi.ModTime() |
|
29 |
+} |
... | ... |
@@ -56,6 +56,13 @@ func (w *writer) Write(p []byte) (n int, err error) { |
56 | 56 |
} |
57 | 57 |
|
58 | 58 |
func (w *writer) Commit(ctx context.Context, size int64, expected digest.Digest, opts ...content.Opt) error { |
59 |
+ var base content.Info |
|
60 |
+ for _, opt := range opts { |
|
61 |
+ if err := opt(&base); err != nil { |
|
62 |
+ return err |
|
63 |
+ } |
|
64 |
+ } |
|
65 |
+ |
|
59 | 66 |
if w.fp == nil { |
60 | 67 |
return errors.Wrap(errdefs.ErrFailedPrecondition, "cannot commit on closed writer") |
61 | 68 |
} |
... | ... |
@@ -123,6 +130,12 @@ func (w *writer) Commit(ctx context.Context, size int64, expected digest.Digest, |
123 | 123 |
w.fp = nil |
124 | 124 |
unlock(w.ref) |
125 | 125 |
|
126 |
+ if w.s.ls != nil && base.Labels != nil { |
|
127 |
+ if err := w.s.ls.Set(dgst, base.Labels); err != nil { |
|
128 |
+ return err |
|
129 |
+ } |
|
130 |
+ } |
|
131 |
+ |
|
126 | 132 |
return nil |
127 | 133 |
} |
128 | 134 |
|
129 | 135 |
deleted file mode 100644 |
... | ... |
@@ -1,51 +0,0 @@ |
1 |
-package containerd |
|
2 |
- |
|
3 |
-import ( |
|
4 |
- "net" |
|
5 |
- "time" |
|
6 |
- |
|
7 |
- "github.com/pkg/errors" |
|
8 |
-) |
|
9 |
- |
|
10 |
-type dialResult struct { |
|
11 |
- c net.Conn |
|
12 |
- err error |
|
13 |
-} |
|
14 |
- |
|
15 |
-// Dialer returns a GRPC net.Conn connected to the provided address |
|
16 |
-func Dialer(address string, timeout time.Duration) (net.Conn, error) { |
|
17 |
- var ( |
|
18 |
- stopC = make(chan struct{}) |
|
19 |
- synC = make(chan *dialResult) |
|
20 |
- ) |
|
21 |
- go func() { |
|
22 |
- defer close(synC) |
|
23 |
- for { |
|
24 |
- select { |
|
25 |
- case <-stopC: |
|
26 |
- return |
|
27 |
- default: |
|
28 |
- c, err := dialer(address, timeout) |
|
29 |
- if isNoent(err) { |
|
30 |
- <-time.After(10 * time.Millisecond) |
|
31 |
- continue |
|
32 |
- } |
|
33 |
- synC <- &dialResult{c, err} |
|
34 |
- return |
|
35 |
- } |
|
36 |
- } |
|
37 |
- }() |
|
38 |
- select { |
|
39 |
- case dr := <-synC: |
|
40 |
- return dr.c, dr.err |
|
41 |
- case <-time.After(timeout): |
|
42 |
- close(stopC) |
|
43 |
- go func() { |
|
44 |
- dr := <-synC |
|
45 |
- if dr != nil { |
|
46 |
- dr.c.Close() |
|
47 |
- } |
|
48 |
- }() |
|
49 |
- return nil, errors.Errorf("dial %s: timeout", address) |
|
50 |
- } |
|
51 |
-} |
52 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,51 @@ |
0 |
+package dialer |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "net" |
|
4 |
+ "time" |
|
5 |
+ |
|
6 |
+ "github.com/pkg/errors" |
|
7 |
+) |
|
8 |
+ |
|
9 |
+type dialResult struct { |
|
10 |
+ c net.Conn |
|
11 |
+ err error |
|
12 |
+} |
|
13 |
+ |
|
14 |
+// Dialer returns a GRPC net.Conn connected to the provided address |
|
15 |
+func Dialer(address string, timeout time.Duration) (net.Conn, error) { |
|
16 |
+ var ( |
|
17 |
+ stopC = make(chan struct{}) |
|
18 |
+ synC = make(chan *dialResult) |
|
19 |
+ ) |
|
20 |
+ go func() { |
|
21 |
+ defer close(synC) |
|
22 |
+ for { |
|
23 |
+ select { |
|
24 |
+ case <-stopC: |
|
25 |
+ return |
|
26 |
+ default: |
|
27 |
+ c, err := dialer(address, timeout) |
|
28 |
+ if isNoent(err) { |
|
29 |
+ <-time.After(10 * time.Millisecond) |
|
30 |
+ continue |
|
31 |
+ } |
|
32 |
+ synC <- &dialResult{c, err} |
|
33 |
+ return |
|
34 |
+ } |
|
35 |
+ } |
|
36 |
+ }() |
|
37 |
+ select { |
|
38 |
+ case dr := <-synC: |
|
39 |
+ return dr.c, dr.err |
|
40 |
+ case <-time.After(timeout): |
|
41 |
+ close(stopC) |
|
42 |
+ go func() { |
|
43 |
+ dr := <-synC |
|
44 |
+ if dr != nil { |
|
45 |
+ dr.c.Close() |
|
46 |
+ } |
|
47 |
+ }() |
|
48 |
+ return nil, errors.Errorf("dial %s: timeout", address) |
|
49 |
+ } |
|
50 |
+} |
0 | 51 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,36 @@ |
0 |
+// +build !windows |
|
1 |
+ |
|
2 |
+package dialer |
|
3 |
+ |
|
4 |
+import ( |
|
5 |
+ "fmt" |
|
6 |
+ "net" |
|
7 |
+ "os" |
|
8 |
+ "strings" |
|
9 |
+ "syscall" |
|
10 |
+ "time" |
|
11 |
+) |
|
12 |
+ |
|
13 |
+// DialAddress returns the address with unix:// prepended to the |
|
14 |
+// provided address |
|
15 |
+func DialAddress(address string) string { |
|
16 |
+ return fmt.Sprintf("unix://%s", address) |
|
17 |
+} |
|
18 |
+ |
|
19 |
+func isNoent(err error) bool { |
|
20 |
+ if err != nil { |
|
21 |
+ if nerr, ok := err.(*net.OpError); ok { |
|
22 |
+ if serr, ok := nerr.Err.(*os.SyscallError); ok { |
|
23 |
+ if serr.Err == syscall.ENOENT { |
|
24 |
+ return true |
|
25 |
+ } |
|
26 |
+ } |
|
27 |
+ } |
|
28 |
+ } |
|
29 |
+ return false |
|
30 |
+} |
|
31 |
+ |
|
32 |
+func dialer(address string, timeout time.Duration) (net.Conn, error) { |
|
33 |
+ address = strings.TrimPrefix(address, "unix://") |
|
34 |
+ return net.DialTimeout("unix", address, timeout) |
|
35 |
+} |
0 | 36 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,30 @@ |
0 |
+package dialer |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "net" |
|
4 |
+ "os" |
|
5 |
+ "syscall" |
|
6 |
+ "time" |
|
7 |
+ |
|
8 |
+ winio "github.com/Microsoft/go-winio" |
|
9 |
+) |
|
10 |
+ |
|
11 |
+func isNoent(err error) bool { |
|
12 |
+ if err != nil { |
|
13 |
+ if oerr, ok := err.(*os.PathError); ok { |
|
14 |
+ if oerr.Err == syscall.ENOENT { |
|
15 |
+ return true |
|
16 |
+ } |
|
17 |
+ } |
|
18 |
+ } |
|
19 |
+ return false |
|
20 |
+} |
|
21 |
+ |
|
22 |
+func dialer(address string, timeout time.Duration) (net.Conn, error) { |
|
23 |
+ return winio.DialPipe(address, &timeout) |
|
24 |
+} |
|
25 |
+ |
|
26 |
+// DialAddress returns the dial address |
|
27 |
+func DialAddress(address string) string { |
|
28 |
+ return address |
|
29 |
+} |
0 | 30 |
deleted file mode 100644 |
... | ... |
@@ -1,36 +0,0 @@ |
1 |
-// +build !windows |
|
2 |
- |
|
3 |
-package containerd |
|
4 |
- |
|
5 |
-import ( |
|
6 |
- "fmt" |
|
7 |
- "net" |
|
8 |
- "os" |
|
9 |
- "strings" |
|
10 |
- "syscall" |
|
11 |
- "time" |
|
12 |
-) |
|
13 |
- |
|
14 |
-func isNoent(err error) bool { |
|
15 |
- if err != nil { |
|
16 |
- if nerr, ok := err.(*net.OpError); ok { |
|
17 |
- if serr, ok := nerr.Err.(*os.SyscallError); ok { |
|
18 |
- if serr.Err == syscall.ENOENT { |
|
19 |
- return true |
|
20 |
- } |
|
21 |
- } |
|
22 |
- } |
|
23 |
- } |
|
24 |
- return false |
|
25 |
-} |
|
26 |
- |
|
27 |
-func dialer(address string, timeout time.Duration) (net.Conn, error) { |
|
28 |
- address = strings.TrimPrefix(address, "unix://") |
|
29 |
- return net.DialTimeout("unix", address, timeout) |
|
30 |
-} |
|
31 |
- |
|
32 |
-// DialAddress returns the address with unix:// prepended to the |
|
33 |
-// provided address |
|
34 |
-func DialAddress(address string) string { |
|
35 |
- return fmt.Sprintf("unix://%s", address) |
|
36 |
-} |
37 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,29 +0,0 @@ |
1 |
-package containerd |
|
2 |
- |
|
3 |
-import ( |
|
4 |
- "net" |
|
5 |
- "os" |
|
6 |
- "syscall" |
|
7 |
- "time" |
|
8 |
- |
|
9 |
- winio "github.com/Microsoft/go-winio" |
|
10 |
-) |
|
11 |
- |
|
12 |
-func isNoent(err error) bool { |
|
13 |
- if err != nil { |
|
14 |
- if oerr, ok := err.(*os.PathError); ok { |
|
15 |
- if oerr.Err == syscall.ENOENT { |
|
16 |
- return true |
|
17 |
- } |
|
18 |
- } |
|
19 |
- } |
|
20 |
- return false |
|
21 |
-} |
|
22 |
- |
|
23 |
-func dialer(address string, timeout time.Duration) (net.Conn, error) { |
|
24 |
- return winio.DialPipe(address, &timeout) |
|
25 |
-} |
|
26 |
- |
|
27 |
-func DialAddress(address string) string { |
|
28 |
- return address |
|
29 |
-} |
30 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,231 +0,0 @@ |
1 |
-package events |
|
2 |
- |
|
3 |
-import ( |
|
4 |
- "context" |
|
5 |
- "strings" |
|
6 |
- "time" |
|
7 |
- |
|
8 |
- events "github.com/containerd/containerd/api/services/events/v1" |
|
9 |
- "github.com/containerd/containerd/errdefs" |
|
10 |
- "github.com/containerd/containerd/filters" |
|
11 |
- "github.com/containerd/containerd/identifiers" |
|
12 |
- "github.com/containerd/containerd/log" |
|
13 |
- "github.com/containerd/containerd/namespaces" |
|
14 |
- "github.com/containerd/typeurl" |
|
15 |
- goevents "github.com/docker/go-events" |
|
16 |
- "github.com/gogo/protobuf/types" |
|
17 |
- "github.com/pkg/errors" |
|
18 |
- "github.com/sirupsen/logrus" |
|
19 |
-) |
|
20 |
- |
|
21 |
-// Exchange broadcasts events |
|
22 |
-type Exchange struct { |
|
23 |
- broadcaster *goevents.Broadcaster |
|
24 |
-} |
|
25 |
- |
|
26 |
-// NewExchange returns a new event Exchange |
|
27 |
-func NewExchange() *Exchange { |
|
28 |
- return &Exchange{ |
|
29 |
- broadcaster: goevents.NewBroadcaster(), |
|
30 |
- } |
|
31 |
-} |
|
32 |
- |
|
33 |
-// Forward accepts an envelope to be direcly distributed on the exchange. |
|
34 |
-// |
|
35 |
-// This is useful when an event is forwaded on behalf of another namespace or |
|
36 |
-// when the event is propagated on behalf of another publisher. |
|
37 |
-func (e *Exchange) Forward(ctx context.Context, envelope *events.Envelope) (err error) { |
|
38 |
- if err := validateEnvelope(envelope); err != nil { |
|
39 |
- return err |
|
40 |
- } |
|
41 |
- |
|
42 |
- defer func() { |
|
43 |
- logger := log.G(ctx).WithFields(logrus.Fields{ |
|
44 |
- "topic": envelope.Topic, |
|
45 |
- "ns": envelope.Namespace, |
|
46 |
- "type": envelope.Event.TypeUrl, |
|
47 |
- }) |
|
48 |
- |
|
49 |
- if err != nil { |
|
50 |
- logger.WithError(err).Error("error forwarding event") |
|
51 |
- } else { |
|
52 |
- logger.Debug("event forwarded") |
|
53 |
- } |
|
54 |
- }() |
|
55 |
- |
|
56 |
- return e.broadcaster.Write(envelope) |
|
57 |
-} |
|
58 |
- |
|
59 |
-// Publish packages and sends an event. The caller will be considered the |
|
60 |
-// initial publisher of the event. This means the timestamp will be calculated |
|
61 |
-// at this point and this method may read from the calling context. |
|
62 |
-func (e *Exchange) Publish(ctx context.Context, topic string, event Event) (err error) { |
|
63 |
- var ( |
|
64 |
- namespace string |
|
65 |
- encoded *types.Any |
|
66 |
- envelope events.Envelope |
|
67 |
- ) |
|
68 |
- |
|
69 |
- namespace, err = namespaces.NamespaceRequired(ctx) |
|
70 |
- if err != nil { |
|
71 |
- return errors.Wrapf(err, "failed publishing event") |
|
72 |
- } |
|
73 |
- if err := validateTopic(topic); err != nil { |
|
74 |
- return errors.Wrapf(err, "envelope topic %q", topic) |
|
75 |
- } |
|
76 |
- |
|
77 |
- encoded, err = typeurl.MarshalAny(event) |
|
78 |
- if err != nil { |
|
79 |
- return err |
|
80 |
- } |
|
81 |
- |
|
82 |
- envelope.Timestamp = time.Now().UTC() |
|
83 |
- envelope.Namespace = namespace |
|
84 |
- envelope.Topic = topic |
|
85 |
- envelope.Event = encoded |
|
86 |
- |
|
87 |
- defer func() { |
|
88 |
- logger := log.G(ctx).WithFields(logrus.Fields{ |
|
89 |
- "topic": envelope.Topic, |
|
90 |
- "ns": envelope.Namespace, |
|
91 |
- "type": envelope.Event.TypeUrl, |
|
92 |
- }) |
|
93 |
- |
|
94 |
- if err != nil { |
|
95 |
- logger.WithError(err).Error("error publishing event") |
|
96 |
- } else { |
|
97 |
- logger.Debug("event published") |
|
98 |
- } |
|
99 |
- }() |
|
100 |
- |
|
101 |
- return e.broadcaster.Write(&envelope) |
|
102 |
-} |
|
103 |
- |
|
104 |
-// Subscribe to events on the exchange. Events are sent through the returned |
|
105 |
-// channel ch. If an error is encountered, it will be sent on channel errs and |
|
106 |
-// errs will be closed. To end the subscription, cancel the provided context. |
|
107 |
-// |
|
108 |
-// Zero or more filters may be provided as strings. Only events that match |
|
109 |
-// *any* of the provided filters will be sent on the channel. The filters use |
|
110 |
-// the standard containerd filters package syntax. |
|
111 |
-func (e *Exchange) Subscribe(ctx context.Context, fs ...string) (ch <-chan *events.Envelope, errs <-chan error) { |
|
112 |
- var ( |
|
113 |
- evch = make(chan *events.Envelope) |
|
114 |
- errq = make(chan error, 1) |
|
115 |
- channel = goevents.NewChannel(0) |
|
116 |
- queue = goevents.NewQueue(channel) |
|
117 |
- dst goevents.Sink = queue |
|
118 |
- ) |
|
119 |
- |
|
120 |
- closeAll := func() { |
|
121 |
- defer close(errq) |
|
122 |
- defer e.broadcaster.Remove(dst) |
|
123 |
- defer queue.Close() |
|
124 |
- defer channel.Close() |
|
125 |
- } |
|
126 |
- |
|
127 |
- ch = evch |
|
128 |
- errs = errq |
|
129 |
- |
|
130 |
- if len(fs) > 0 { |
|
131 |
- filter, err := filters.ParseAll(fs...) |
|
132 |
- if err != nil { |
|
133 |
- errq <- errors.Wrapf(err, "failed parsing subscription filters") |
|
134 |
- closeAll() |
|
135 |
- return |
|
136 |
- } |
|
137 |
- |
|
138 |
- dst = goevents.NewFilter(queue, goevents.MatcherFunc(func(gev goevents.Event) bool { |
|
139 |
- return filter.Match(adapt(gev)) |
|
140 |
- })) |
|
141 |
- } |
|
142 |
- |
|
143 |
- e.broadcaster.Add(dst) |
|
144 |
- |
|
145 |
- go func() { |
|
146 |
- defer closeAll() |
|
147 |
- |
|
148 |
- var err error |
|
149 |
- loop: |
|
150 |
- for { |
|
151 |
- select { |
|
152 |
- case ev := <-channel.C: |
|
153 |
- env, ok := ev.(*events.Envelope) |
|
154 |
- if !ok { |
|
155 |
- // TODO(stevvooe): For the most part, we are well protected |
|
156 |
- // from this condition. Both Forward and Publish protect |
|
157 |
- // from this. |
|
158 |
- err = errors.Errorf("invalid envelope encountered %#v; please file a bug", ev) |
|
159 |
- break |
|
160 |
- } |
|
161 |
- |
|
162 |
- select { |
|
163 |
- case evch <- env: |
|
164 |
- case <-ctx.Done(): |
|
165 |
- break loop |
|
166 |
- } |
|
167 |
- case <-ctx.Done(): |
|
168 |
- break loop |
|
169 |
- } |
|
170 |
- } |
|
171 |
- |
|
172 |
- if err == nil { |
|
173 |
- if cerr := ctx.Err(); cerr != context.Canceled { |
|
174 |
- err = cerr |
|
175 |
- } |
|
176 |
- } |
|
177 |
- |
|
178 |
- errq <- err |
|
179 |
- }() |
|
180 |
- |
|
181 |
- return |
|
182 |
-} |
|
183 |
- |
|
184 |
-func validateTopic(topic string) error { |
|
185 |
- if topic == "" { |
|
186 |
- return errors.Wrap(errdefs.ErrInvalidArgument, "must not be empty") |
|
187 |
- } |
|
188 |
- |
|
189 |
- if topic[0] != '/' { |
|
190 |
- return errors.Wrapf(errdefs.ErrInvalidArgument, "must start with '/'") |
|
191 |
- } |
|
192 |
- |
|
193 |
- if len(topic) == 1 { |
|
194 |
- return errors.Wrapf(errdefs.ErrInvalidArgument, "must have at least one component") |
|
195 |
- } |
|
196 |
- |
|
197 |
- components := strings.Split(topic[1:], "/") |
|
198 |
- for _, component := range components { |
|
199 |
- if err := identifiers.Validate(component); err != nil { |
|
200 |
- return errors.Wrapf(err, "failed validation on component %q", component) |
|
201 |
- } |
|
202 |
- } |
|
203 |
- |
|
204 |
- return nil |
|
205 |
-} |
|
206 |
- |
|
207 |
-func validateEnvelope(envelope *events.Envelope) error { |
|
208 |
- if err := namespaces.Validate(envelope.Namespace); err != nil { |
|
209 |
- return errors.Wrapf(err, "event envelope has invalid namespace") |
|
210 |
- } |
|
211 |
- |
|
212 |
- if err := validateTopic(envelope.Topic); err != nil { |
|
213 |
- return errors.Wrapf(err, "envelope topic %q", envelope.Topic) |
|
214 |
- } |
|
215 |
- |
|
216 |
- if envelope.Timestamp.IsZero() { |
|
217 |
- return errors.Wrapf(errdefs.ErrInvalidArgument, "timestamp must be set on forwarded event") |
|
218 |
- } |
|
219 |
- |
|
220 |
- return nil |
|
221 |
-} |
|
222 |
- |
|
223 |
-func adapt(ev interface{}) filters.Adaptor { |
|
224 |
- if adaptor, ok := ev.(filters.Adaptor); ok { |
|
225 |
- return adaptor |
|
226 |
- } |
|
227 |
- |
|
228 |
- return filters.AdapterFunc(func(fieldpath []string) (string, bool) { |
|
229 |
- return "", false |
|
230 |
- }) |
|
231 |
-} |
232 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,232 @@ |
0 |
+package exchange |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "context" |
|
4 |
+ "strings" |
|
5 |
+ "time" |
|
6 |
+ |
|
7 |
+ v1 "github.com/containerd/containerd/api/services/events/v1" |
|
8 |
+ "github.com/containerd/containerd/errdefs" |
|
9 |
+ "github.com/containerd/containerd/events" |
|
10 |
+ "github.com/containerd/containerd/filters" |
|
11 |
+ "github.com/containerd/containerd/identifiers" |
|
12 |
+ "github.com/containerd/containerd/log" |
|
13 |
+ "github.com/containerd/containerd/namespaces" |
|
14 |
+ "github.com/containerd/typeurl" |
|
15 |
+ goevents "github.com/docker/go-events" |
|
16 |
+ "github.com/gogo/protobuf/types" |
|
17 |
+ "github.com/pkg/errors" |
|
18 |
+ "github.com/sirupsen/logrus" |
|
19 |
+) |
|
20 |
+ |
|
21 |
+// Exchange broadcasts events |
|
22 |
+type Exchange struct { |
|
23 |
+ broadcaster *goevents.Broadcaster |
|
24 |
+} |
|
25 |
+ |
|
26 |
+// NewExchange returns a new event Exchange |
|
27 |
+func NewExchange() *Exchange { |
|
28 |
+ return &Exchange{ |
|
29 |
+ broadcaster: goevents.NewBroadcaster(), |
|
30 |
+ } |
|
31 |
+} |
|
32 |
+ |
|
33 |
+// Forward accepts an envelope to be direcly distributed on the exchange. |
|
34 |
+// |
|
35 |
+// This is useful when an event is forwaded on behalf of another namespace or |
|
36 |
+// when the event is propagated on behalf of another publisher. |
|
37 |
+func (e *Exchange) Forward(ctx context.Context, envelope *v1.Envelope) (err error) { |
|
38 |
+ if err := validateEnvelope(envelope); err != nil { |
|
39 |
+ return err |
|
40 |
+ } |
|
41 |
+ |
|
42 |
+ defer func() { |
|
43 |
+ logger := log.G(ctx).WithFields(logrus.Fields{ |
|
44 |
+ "topic": envelope.Topic, |
|
45 |
+ "ns": envelope.Namespace, |
|
46 |
+ "type": envelope.Event.TypeUrl, |
|
47 |
+ }) |
|
48 |
+ |
|
49 |
+ if err != nil { |
|
50 |
+ logger.WithError(err).Error("error forwarding event") |
|
51 |
+ } else { |
|
52 |
+ logger.Debug("event forwarded") |
|
53 |
+ } |
|
54 |
+ }() |
|
55 |
+ |
|
56 |
+ return e.broadcaster.Write(envelope) |
|
57 |
+} |
|
58 |
+ |
|
59 |
+// Publish packages and sends an event. The caller will be considered the |
|
60 |
+// initial publisher of the event. This means the timestamp will be calculated |
|
61 |
+// at this point and this method may read from the calling context. |
|
62 |
+func (e *Exchange) Publish(ctx context.Context, topic string, event events.Event) (err error) { |
|
63 |
+ var ( |
|
64 |
+ namespace string |
|
65 |
+ encoded *types.Any |
|
66 |
+ envelope v1.Envelope |
|
67 |
+ ) |
|
68 |
+ |
|
69 |
+ namespace, err = namespaces.NamespaceRequired(ctx) |
|
70 |
+ if err != nil { |
|
71 |
+ return errors.Wrapf(err, "failed publishing event") |
|
72 |
+ } |
|
73 |
+ if err := validateTopic(topic); err != nil { |
|
74 |
+ return errors.Wrapf(err, "envelope topic %q", topic) |
|
75 |
+ } |
|
76 |
+ |
|
77 |
+ encoded, err = typeurl.MarshalAny(event) |
|
78 |
+ if err != nil { |
|
79 |
+ return err |
|
80 |
+ } |
|
81 |
+ |
|
82 |
+ envelope.Timestamp = time.Now().UTC() |
|
83 |
+ envelope.Namespace = namespace |
|
84 |
+ envelope.Topic = topic |
|
85 |
+ envelope.Event = encoded |
|
86 |
+ |
|
87 |
+ defer func() { |
|
88 |
+ logger := log.G(ctx).WithFields(logrus.Fields{ |
|
89 |
+ "topic": envelope.Topic, |
|
90 |
+ "ns": envelope.Namespace, |
|
91 |
+ "type": envelope.Event.TypeUrl, |
|
92 |
+ }) |
|
93 |
+ |
|
94 |
+ if err != nil { |
|
95 |
+ logger.WithError(err).Error("error publishing event") |
|
96 |
+ } else { |
|
97 |
+ logger.Debug("event published") |
|
98 |
+ } |
|
99 |
+ }() |
|
100 |
+ |
|
101 |
+ return e.broadcaster.Write(&envelope) |
|
102 |
+} |
|
103 |
+ |
|
104 |
+// Subscribe to events on the exchange. Events are sent through the returned |
|
105 |
+// channel ch. If an error is encountered, it will be sent on channel errs and |
|
106 |
+// errs will be closed. To end the subscription, cancel the provided context. |
|
107 |
+// |
|
108 |
+// Zero or more filters may be provided as strings. Only events that match |
|
109 |
+// *any* of the provided filters will be sent on the channel. The filters use |
|
110 |
+// the standard containerd filters package syntax. |
|
111 |
+func (e *Exchange) Subscribe(ctx context.Context, fs ...string) (ch <-chan *v1.Envelope, errs <-chan error) { |
|
112 |
+ var ( |
|
113 |
+ evch = make(chan *v1.Envelope) |
|
114 |
+ errq = make(chan error, 1) |
|
115 |
+ channel = goevents.NewChannel(0) |
|
116 |
+ queue = goevents.NewQueue(channel) |
|
117 |
+ dst goevents.Sink = queue |
|
118 |
+ ) |
|
119 |
+ |
|
120 |
+ closeAll := func() { |
|
121 |
+ defer close(errq) |
|
122 |
+ defer e.broadcaster.Remove(dst) |
|
123 |
+ defer queue.Close() |
|
124 |
+ defer channel.Close() |
|
125 |
+ } |
|
126 |
+ |
|
127 |
+ ch = evch |
|
128 |
+ errs = errq |
|
129 |
+ |
|
130 |
+ if len(fs) > 0 { |
|
131 |
+ filter, err := filters.ParseAll(fs...) |
|
132 |
+ if err != nil { |
|
133 |
+ errq <- errors.Wrapf(err, "failed parsing subscription filters") |
|
134 |
+ closeAll() |
|
135 |
+ return |
|
136 |
+ } |
|
137 |
+ |
|
138 |
+ dst = goevents.NewFilter(queue, goevents.MatcherFunc(func(gev goevents.Event) bool { |
|
139 |
+ return filter.Match(adapt(gev)) |
|
140 |
+ })) |
|
141 |
+ } |
|
142 |
+ |
|
143 |
+ e.broadcaster.Add(dst) |
|
144 |
+ |
|
145 |
+ go func() { |
|
146 |
+ defer closeAll() |
|
147 |
+ |
|
148 |
+ var err error |
|
149 |
+ loop: |
|
150 |
+ for { |
|
151 |
+ select { |
|
152 |
+ case ev := <-channel.C: |
|
153 |
+ env, ok := ev.(*v1.Envelope) |
|
154 |
+ if !ok { |
|
155 |
+ // TODO(stevvooe): For the most part, we are well protected |
|
156 |
+ // from this condition. Both Forward and Publish protect |
|
157 |
+ // from this. |
|
158 |
+ err = errors.Errorf("invalid envelope encountered %#v; please file a bug", ev) |
|
159 |
+ break |
|
160 |
+ } |
|
161 |
+ |
|
162 |
+ select { |
|
163 |
+ case evch <- env: |
|
164 |
+ case <-ctx.Done(): |
|
165 |
+ break loop |
|
166 |
+ } |
|
167 |
+ case <-ctx.Done(): |
|
168 |
+ break loop |
|
169 |
+ } |
|
170 |
+ } |
|
171 |
+ |
|
172 |
+ if err == nil { |
|
173 |
+ if cerr := ctx.Err(); cerr != context.Canceled { |
|
174 |
+ err = cerr |
|
175 |
+ } |
|
176 |
+ } |
|
177 |
+ |
|
178 |
+ errq <- err |
|
179 |
+ }() |
|
180 |
+ |
|
181 |
+ return |
|
182 |
+} |
|
183 |
+ |
|
184 |
+func validateTopic(topic string) error { |
|
185 |
+ if topic == "" { |
|
186 |
+ return errors.Wrap(errdefs.ErrInvalidArgument, "must not be empty") |
|
187 |
+ } |
|
188 |
+ |
|
189 |
+ if topic[0] != '/' { |
|
190 |
+ return errors.Wrapf(errdefs.ErrInvalidArgument, "must start with '/'") |
|
191 |
+ } |
|
192 |
+ |
|
193 |
+ if len(topic) == 1 { |
|
194 |
+ return errors.Wrapf(errdefs.ErrInvalidArgument, "must have at least one component") |
|
195 |
+ } |
|
196 |
+ |
|
197 |
+ components := strings.Split(topic[1:], "/") |
|
198 |
+ for _, component := range components { |
|
199 |
+ if err := identifiers.Validate(component); err != nil { |
|
200 |
+ return errors.Wrapf(err, "failed validation on component %q", component) |
|
201 |
+ } |
|
202 |
+ } |
|
203 |
+ |
|
204 |
+ return nil |
|
205 |
+} |
|
206 |
+ |
|
207 |
+func validateEnvelope(envelope *v1.Envelope) error { |
|
208 |
+ if err := namespaces.Validate(envelope.Namespace); err != nil { |
|
209 |
+ return errors.Wrapf(err, "event envelope has invalid namespace") |
|
210 |
+ } |
|
211 |
+ |
|
212 |
+ if err := validateTopic(envelope.Topic); err != nil { |
|
213 |
+ return errors.Wrapf(err, "envelope topic %q", envelope.Topic) |
|
214 |
+ } |
|
215 |
+ |
|
216 |
+ if envelope.Timestamp.IsZero() { |
|
217 |
+ return errors.Wrapf(errdefs.ErrInvalidArgument, "timestamp must be set on forwarded event") |
|
218 |
+ } |
|
219 |
+ |
|
220 |
+ return nil |
|
221 |
+} |
|
222 |
+ |
|
223 |
+func adapt(ev interface{}) filters.Adaptor { |
|
224 |
+ if adaptor, ok := ev.(filters.Adaptor); ok { |
|
225 |
+ return adaptor |
|
226 |
+ } |
|
227 |
+ |
|
228 |
+ return filters.AdapterFunc(func(fieldpath []string) (string, bool) { |
|
229 |
+ return "", false |
|
230 |
+ }) |
|
231 |
+} |
... | ... |
@@ -10,7 +10,7 @@ import ( |
10 | 10 |
"sync" |
11 | 11 |
) |
12 | 12 |
|
13 |
-// Resourcetype represents type of resource at a node |
|
13 |
+// ResourceType represents type of resource at a node |
|
14 | 14 |
type ResourceType uint8 |
15 | 15 |
|
16 | 16 |
// Node presents a resource which has a type and key, |
... | ... |
@@ -145,10 +145,10 @@ func ConcurrentMark(ctx context.Context, root <-chan Node, refs func(context.Con |
145 | 145 |
|
146 | 146 |
// Sweep removes all nodes returned through the channel which are not in |
147 | 147 |
// the reachable set by calling the provided remove function. |
148 |
-func Sweep(reachable map[Node]struct{}, all <-chan Node, remove func(Node) error) error { |
|
148 |
+func Sweep(reachable map[Node]struct{}, all []Node, remove func(Node) error) error { |
|
149 | 149 |
// All black objects are now reachable, and all white objects are |
150 | 150 |
// unreachable. Free those that are white! |
151 |
- for node := range all { |
|
151 |
+ for _, node := range all { |
|
152 | 152 |
if _, ok := reachable[node]; !ok { |
153 | 153 |
if err := remove(node); err != nil { |
154 | 154 |
return err |
... | ... |
@@ -3,9 +3,9 @@ package containerd |
3 | 3 |
import ( |
4 | 4 |
"context" |
5 | 5 |
"fmt" |
6 |
- "time" |
|
7 | 6 |
|
8 | 7 |
"github.com/containerd/containerd/content" |
8 |
+ "github.com/containerd/containerd/errdefs" |
|
9 | 9 |
"github.com/containerd/containerd/images" |
10 | 10 |
"github.com/containerd/containerd/platforms" |
11 | 11 |
"github.com/containerd/containerd/rootfs" |
... | ... |
@@ -30,6 +30,8 @@ type Image interface { |
30 | 30 |
Size(ctx context.Context) (int64, error) |
31 | 31 |
// Config descriptor for the image. |
32 | 32 |
Config(ctx context.Context) (ocispec.Descriptor, error) |
33 |
+ // IsUnpacked returns whether or not an image is unpacked. |
|
34 |
+ IsUnpacked(context.Context, string) (bool, error) |
|
33 | 35 |
} |
34 | 36 |
|
35 | 37 |
var _ = (Image)(&image{}) |
... | ... |
@@ -63,6 +65,26 @@ func (i *image) Config(ctx context.Context) (ocispec.Descriptor, error) { |
63 | 63 |
return i.i.Config(ctx, provider, platforms.Default()) |
64 | 64 |
} |
65 | 65 |
|
66 |
+func (i *image) IsUnpacked(ctx context.Context, snapshotterName string) (bool, error) { |
|
67 |
+ sn := i.client.SnapshotService(snapshotterName) |
|
68 |
+ cs := i.client.ContentStore() |
|
69 |
+ |
|
70 |
+ diffs, err := i.i.RootFS(ctx, cs, platforms.Default()) |
|
71 |
+ if err != nil { |
|
72 |
+ return false, err |
|
73 |
+ } |
|
74 |
+ |
|
75 |
+ chainID := identity.ChainID(diffs) |
|
76 |
+ _, err = sn.Stat(ctx, chainID.String()) |
|
77 |
+ if err == nil { |
|
78 |
+ return true, nil |
|
79 |
+ } else if !errdefs.IsNotFound(err) { |
|
80 |
+ return false, err |
|
81 |
+ } |
|
82 |
+ |
|
83 |
+ return false, nil |
|
84 |
+} |
|
85 |
+ |
|
66 | 86 |
func (i *image) Unpack(ctx context.Context, snapshotterName string) error { |
67 | 87 |
layers, err := i.getLayers(ctx, platforms.Default()) |
68 | 88 |
if err != nil { |
... | ... |
@@ -79,27 +101,14 @@ func (i *image) Unpack(ctx context.Context, snapshotterName string) error { |
79 | 79 |
) |
80 | 80 |
for _, layer := range layers { |
81 | 81 |
labels := map[string]string{ |
82 |
- "containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339), |
|
83 | 82 |
"containerd.io/uncompressed": layer.Diff.Digest.String(), |
84 | 83 |
} |
85 |
- lastUnpacked := unpacked |
|
86 | 84 |
|
87 | 85 |
unpacked, err = rootfs.ApplyLayer(ctx, layer, chain, sn, a, snapshot.WithLabels(labels)) |
88 | 86 |
if err != nil { |
89 | 87 |
return err |
90 | 88 |
} |
91 | 89 |
|
92 |
- if lastUnpacked { |
|
93 |
- info := snapshot.Info{ |
|
94 |
- Name: identity.ChainID(chain).String(), |
|
95 |
- } |
|
96 |
- |
|
97 |
- // Remove previously created gc.root label |
|
98 |
- if _, err := sn.Update(ctx, info, "labels.containerd.io/gc.root"); err != nil { |
|
99 |
- return err |
|
100 |
- } |
|
101 |
- } |
|
102 |
- |
|
103 | 90 |
chain = append(chain, layer.Diff.Digest) |
104 | 91 |
} |
105 | 92 |
|
... | ... |
@@ -120,15 +129,6 @@ func (i *image) Unpack(ctx context.Context, snapshotterName string) error { |
120 | 120 |
if _, err := cs.Update(ctx, cinfo, fmt.Sprintf("labels.containerd.io/gc.ref.snapshot.%s", snapshotterName)); err != nil { |
121 | 121 |
return err |
122 | 122 |
} |
123 |
- |
|
124 |
- sinfo := snapshot.Info{ |
|
125 |
- Name: rootfs, |
|
126 |
- } |
|
127 |
- |
|
128 |
- // Config now referenced snapshot, release root reference |
|
129 |
- if _, err := sn.Update(ctx, sinfo, "labels.containerd.io/gc.root"); err != nil { |
|
130 |
- return err |
|
131 |
- } |
|
132 | 123 |
} |
133 | 124 |
|
134 | 125 |
return nil |
... | ... |
@@ -16,7 +16,7 @@ import ( |
16 | 16 |
|
17 | 17 |
// NewFifos returns a new set of fifos for the task |
18 | 18 |
func NewFifos(id string) (*FIFOSet, error) { |
19 |
- root := filepath.Join(os.TempDir(), "containerd") |
|
19 |
+ root := "/run/containerd/fifo" |
|
20 | 20 |
if err := os.MkdirAll(root, 0700); err != nil { |
21 | 21 |
return nil, err |
22 | 22 |
} |
23 | 23 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,91 @@ |
0 |
+package containerd |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "context" |
|
4 |
+ "time" |
|
5 |
+ |
|
6 |
+ leasesapi "github.com/containerd/containerd/api/services/leases/v1" |
|
7 |
+ "github.com/containerd/containerd/leases" |
|
8 |
+) |
|
9 |
+ |
|
10 |
+// Lease is used to hold a reference to active resources which have not been |
|
11 |
+// referenced by a root resource. This is useful for preventing garbage |
|
12 |
+// collection of resources while they are actively being updated. |
|
13 |
+type Lease struct { |
|
14 |
+ id string |
|
15 |
+ createdAt time.Time |
|
16 |
+ |
|
17 |
+ client *Client |
|
18 |
+} |
|
19 |
+ |
|
20 |
+// CreateLease creates a new lease |
|
21 |
+func (c *Client) CreateLease(ctx context.Context) (Lease, error) { |
|
22 |
+ lapi := leasesapi.NewLeasesClient(c.conn) |
|
23 |
+ resp, err := lapi.Create(ctx, &leasesapi.CreateRequest{}) |
|
24 |
+ if err != nil { |
|
25 |
+ return Lease{}, err |
|
26 |
+ } |
|
27 |
+ |
|
28 |
+ return Lease{ |
|
29 |
+ id: resp.Lease.ID, |
|
30 |
+ client: c, |
|
31 |
+ }, nil |
|
32 |
+} |
|
33 |
+ |
|
34 |
+// ListLeases lists active leases |
|
35 |
+func (c *Client) ListLeases(ctx context.Context) ([]Lease, error) { |
|
36 |
+ lapi := leasesapi.NewLeasesClient(c.conn) |
|
37 |
+ resp, err := lapi.List(ctx, &leasesapi.ListRequest{}) |
|
38 |
+ if err != nil { |
|
39 |
+ return nil, err |
|
40 |
+ } |
|
41 |
+ leases := make([]Lease, len(resp.Leases)) |
|
42 |
+ for i := range resp.Leases { |
|
43 |
+ leases[i] = Lease{ |
|
44 |
+ id: resp.Leases[i].ID, |
|
45 |
+ createdAt: resp.Leases[i].CreatedAt, |
|
46 |
+ client: c, |
|
47 |
+ } |
|
48 |
+ } |
|
49 |
+ |
|
50 |
+ return leases, nil |
|
51 |
+} |
|
52 |
+ |
|
53 |
+func (c *Client) withLease(ctx context.Context) (context.Context, func() error, error) { |
|
54 |
+ _, ok := leases.Lease(ctx) |
|
55 |
+ if ok { |
|
56 |
+ return ctx, func() error { |
|
57 |
+ return nil |
|
58 |
+ }, nil |
|
59 |
+ } |
|
60 |
+ |
|
61 |
+ l, err := c.CreateLease(ctx) |
|
62 |
+ if err != nil { |
|
63 |
+ return nil, nil, err |
|
64 |
+ } |
|
65 |
+ |
|
66 |
+ ctx = leases.WithLease(ctx, l.ID()) |
|
67 |
+ return ctx, func() error { |
|
68 |
+ return l.Delete(ctx) |
|
69 |
+ }, nil |
|
70 |
+} |
|
71 |
+ |
|
72 |
+// ID returns the lease ID |
|
73 |
+func (l Lease) ID() string { |
|
74 |
+ return l.id |
|
75 |
+} |
|
76 |
+ |
|
77 |
+// CreatedAt returns the time at which the lease was created |
|
78 |
+func (l Lease) CreatedAt() time.Time { |
|
79 |
+ return l.createdAt |
|
80 |
+} |
|
81 |
+ |
|
82 |
+// Delete deletes the lease, removing the reference to all resources created |
|
83 |
+// during the lease. |
|
84 |
+func (l Lease) Delete(ctx context.Context) error { |
|
85 |
+ lapi := leasesapi.NewLeasesClient(l.client.conn) |
|
86 |
+ _, err := lapi.Delete(ctx, &leasesapi.DeleteRequest{ |
|
87 |
+ ID: l.id, |
|
88 |
+ }) |
|
89 |
+ return err |
|
90 |
+} |
0 | 91 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,24 @@ |
0 |
+package leases |
|
1 |
+ |
|
2 |
+import "context" |
|
3 |
+ |
|
4 |
+type leaseKey struct{} |
|
5 |
+ |
|
6 |
+// WithLease sets a given lease on the context |
|
7 |
+func WithLease(ctx context.Context, lid string) context.Context { |
|
8 |
+ ctx = context.WithValue(ctx, leaseKey{}, lid) |
|
9 |
+ |
|
10 |
+ // also store on the grpc headers so it gets picked up by any clients that |
|
11 |
+ // are using this. |
|
12 |
+ return withGRPCLeaseHeader(ctx, lid) |
|
13 |
+} |
|
14 |
+ |
|
15 |
+// Lease returns the lease from the context. |
|
16 |
+func Lease(ctx context.Context) (string, bool) { |
|
17 |
+ lid, ok := ctx.Value(leaseKey{}).(string) |
|
18 |
+ if !ok { |
|
19 |
+ return fromGRPCHeader(ctx) |
|
20 |
+ } |
|
21 |
+ |
|
22 |
+ return lid, ok |
|
23 |
+} |
0 | 24 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,41 @@ |
0 |
+package leases |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "golang.org/x/net/context" |
|
4 |
+ "google.golang.org/grpc/metadata" |
|
5 |
+) |
|
6 |
+ |
|
7 |
+const ( |
|
8 |
+ // GRPCHeader defines the header name for specifying a containerd lease. |
|
9 |
+ GRPCHeader = "containerd-lease" |
|
10 |
+) |
|
11 |
+ |
|
12 |
+func withGRPCLeaseHeader(ctx context.Context, lid string) context.Context { |
|
13 |
+ // also store on the grpc headers so it gets picked up by any clients |
|
14 |
+ // that are using this. |
|
15 |
+ txheader := metadata.Pairs(GRPCHeader, lid) |
|
16 |
+ md, ok := metadata.FromOutgoingContext(ctx) // merge with outgoing context. |
|
17 |
+ if !ok { |
|
18 |
+ md = txheader |
|
19 |
+ } else { |
|
20 |
+ // order ensures the latest is first in this list. |
|
21 |
+ md = metadata.Join(txheader, md) |
|
22 |
+ } |
|
23 |
+ |
|
24 |
+ return metadata.NewOutgoingContext(ctx, md) |
|
25 |
+} |
|
26 |
+ |
|
27 |
+func fromGRPCHeader(ctx context.Context) (string, bool) { |
|
28 |
+ // try to extract for use in grpc servers. |
|
29 |
+ md, ok := metadata.FromIncomingContext(ctx) |
|
30 |
+ if !ok { |
|
31 |
+ return "", false |
|
32 |
+ } |
|
33 |
+ |
|
34 |
+ values := md[GRPCHeader] |
|
35 |
+ if len(values) == 0 { |
|
36 |
+ return "", false |
|
37 |
+ } |
|
38 |
+ |
|
39 |
+ return values[0], true |
|
40 |
+} |
... | ... |
@@ -9,9 +9,10 @@ import ( |
9 | 9 |
"os" |
10 | 10 |
"path/filepath" |
11 | 11 |
|
12 |
- "github.com/containerd/containerd/events" |
|
12 |
+ "github.com/containerd/containerd/events/exchange" |
|
13 | 13 |
"github.com/containerd/containerd/linux/runcopts" |
14 |
- client "github.com/containerd/containerd/linux/shim" |
|
14 |
+ "github.com/containerd/containerd/linux/shim" |
|
15 |
+ "github.com/containerd/containerd/linux/shim/client" |
|
15 | 16 |
"github.com/pkg/errors" |
16 | 17 |
) |
17 | 18 |
|
... | ... |
@@ -70,32 +71,33 @@ type bundle struct { |
70 | 70 |
workDir string |
71 | 71 |
} |
72 | 72 |
|
73 |
-type shimOpt func(*bundle, string, *runcopts.RuncOptions) (client.Config, client.ClientOpt) |
|
73 |
+// ShimOpt specifies shim options for initialization and connection |
|
74 |
+type ShimOpt func(*bundle, string, *runcopts.RuncOptions) (shim.Config, client.Opt) |
|
74 | 75 |
|
75 |
-// ShimRemote is a shimOpt for connecting and starting a remote shim |
|
76 |
-func ShimRemote(shim, daemonAddress, cgroup string, nonewns, debug bool, exitHandler func()) shimOpt { |
|
77 |
- return func(b *bundle, ns string, ropts *runcopts.RuncOptions) (client.Config, client.ClientOpt) { |
|
76 |
+// ShimRemote is a ShimOpt for connecting and starting a remote shim |
|
77 |
+func ShimRemote(shimBinary, daemonAddress, cgroup string, nonewns, debug bool, exitHandler func()) ShimOpt { |
|
78 |
+ return func(b *bundle, ns string, ropts *runcopts.RuncOptions) (shim.Config, client.Opt) { |
|
78 | 79 |
return b.shimConfig(ns, ropts), |
79 |
- client.WithStart(shim, b.shimAddress(ns), daemonAddress, cgroup, nonewns, debug, exitHandler) |
|
80 |
+ client.WithStart(shimBinary, b.shimAddress(ns), daemonAddress, cgroup, nonewns, debug, exitHandler) |
|
80 | 81 |
} |
81 | 82 |
} |
82 | 83 |
|
83 |
-// ShimLocal is a shimOpt for using an in process shim implementation |
|
84 |
-func ShimLocal(exchange *events.Exchange) shimOpt { |
|
85 |
- return func(b *bundle, ns string, ropts *runcopts.RuncOptions) (client.Config, client.ClientOpt) { |
|
84 |
+// ShimLocal is a ShimOpt for using an in process shim implementation |
|
85 |
+func ShimLocal(exchange *exchange.Exchange) ShimOpt { |
|
86 |
+ return func(b *bundle, ns string, ropts *runcopts.RuncOptions) (shim.Config, client.Opt) { |
|
86 | 87 |
return b.shimConfig(ns, ropts), client.WithLocal(exchange) |
87 | 88 |
} |
88 | 89 |
} |
89 | 90 |
|
90 |
-// ShimConnect is a shimOpt for connecting to an existing remote shim |
|
91 |
-func ShimConnect() shimOpt { |
|
92 |
- return func(b *bundle, ns string, ropts *runcopts.RuncOptions) (client.Config, client.ClientOpt) { |
|
91 |
+// ShimConnect is a ShimOpt for connecting to an existing remote shim |
|
92 |
+func ShimConnect() ShimOpt { |
|
93 |
+ return func(b *bundle, ns string, ropts *runcopts.RuncOptions) (shim.Config, client.Opt) { |
|
93 | 94 |
return b.shimConfig(ns, ropts), client.WithConnect(b.shimAddress(ns)) |
94 | 95 |
} |
95 | 96 |
} |
96 | 97 |
|
97 | 98 |
// NewShimClient connects to the shim managing the bundle and tasks creating it if needed |
98 |
-func (b *bundle) NewShimClient(ctx context.Context, namespace string, getClientOpts shimOpt, runcOpts *runcopts.RuncOptions) (*client.Client, error) { |
|
99 |
+func (b *bundle) NewShimClient(ctx context.Context, namespace string, getClientOpts ShimOpt, runcOpts *runcopts.RuncOptions) (*client.Client, error) { |
|
99 | 100 |
cfg, opt := getClientOpts(b, namespace, runcOpts) |
100 | 101 |
return client.New(ctx, cfg, opt) |
101 | 102 |
} |
... | ... |
@@ -118,7 +120,7 @@ func (b *bundle) shimAddress(namespace string) string { |
118 | 118 |
return filepath.Join(string(filepath.Separator), "containerd-shim", namespace, b.id, "shim.sock") |
119 | 119 |
} |
120 | 120 |
|
121 |
-func (b *bundle) shimConfig(namespace string, runcOptions *runcopts.RuncOptions) client.Config { |
|
121 |
+func (b *bundle) shimConfig(namespace string, runcOptions *runcopts.RuncOptions) shim.Config { |
|
122 | 122 |
var ( |
123 | 123 |
criuPath string |
124 | 124 |
runtimeRoot string |
... | ... |
@@ -129,7 +131,7 @@ func (b *bundle) shimConfig(namespace string, runcOptions *runcopts.RuncOptions) |
129 | 129 |
systemdCgroup = runcOptions.SystemdCgroup |
130 | 130 |
runtimeRoot = runcOptions.RuntimeRoot |
131 | 131 |
} |
132 |
- return client.Config{ |
|
132 |
+ return shim.Config{ |
|
133 | 133 |
Path: b.path, |
134 | 134 |
WorkDir: b.workDir, |
135 | 135 |
Namespace: namespace, |
... | ... |
@@ -15,7 +15,7 @@ import ( |
15 | 15 |
"github.com/containerd/containerd/api/types" |
16 | 16 |
"github.com/containerd/containerd/containers" |
17 | 17 |
"github.com/containerd/containerd/errdefs" |
18 |
- "github.com/containerd/containerd/events" |
|
18 |
+ "github.com/containerd/containerd/events/exchange" |
|
19 | 19 |
"github.com/containerd/containerd/identifiers" |
20 | 20 |
"github.com/containerd/containerd/linux/runcopts" |
21 | 21 |
client "github.com/containerd/containerd/linux/shim" |
... | ... |
@@ -143,7 +143,7 @@ type Runtime struct { |
143 | 143 |
monitor runtime.TaskMonitor |
144 | 144 |
tasks *runtime.TaskList |
145 | 145 |
db *metadata.DB |
146 |
- events *events.Exchange |
|
146 |
+ events *exchange.Exchange |
|
147 | 147 |
|
148 | 148 |
config *Config |
149 | 149 |
} |
150 | 150 |
deleted file mode 100644 |
... | ... |
@@ -1,282 +0,0 @@ |
1 |
-// +build !windows |
|
2 |
- |
|
3 |
-package shim |
|
4 |
- |
|
5 |
-import ( |
|
6 |
- "context" |
|
7 |
- "fmt" |
|
8 |
- "io" |
|
9 |
- "net" |
|
10 |
- "os" |
|
11 |
- "os/exec" |
|
12 |
- "strings" |
|
13 |
- "sync" |
|
14 |
- "syscall" |
|
15 |
- "time" |
|
16 |
- |
|
17 |
- "golang.org/x/sys/unix" |
|
18 |
- |
|
19 |
- "github.com/pkg/errors" |
|
20 |
- "github.com/sirupsen/logrus" |
|
21 |
- |
|
22 |
- "github.com/containerd/containerd/events" |
|
23 |
- shim "github.com/containerd/containerd/linux/shim/v1" |
|
24 |
- "github.com/containerd/containerd/log" |
|
25 |
- "github.com/containerd/containerd/reaper" |
|
26 |
- "github.com/containerd/containerd/sys" |
|
27 |
- "google.golang.org/grpc" |
|
28 |
-) |
|
29 |
- |
|
30 |
-// ClientOpt is an option for a shim client configuration |
|
31 |
-type ClientOpt func(context.Context, Config) (shim.ShimClient, io.Closer, error) |
|
32 |
- |
|
33 |
-// WithStart executes a new shim process |
|
34 |
-func WithStart(binary, address, daemonAddress, cgroup string, nonewns, debug bool, exitHandler func()) ClientOpt { |
|
35 |
- return func(ctx context.Context, config Config) (_ shim.ShimClient, _ io.Closer, err error) { |
|
36 |
- socket, err := newSocket(address) |
|
37 |
- if err != nil { |
|
38 |
- return nil, nil, err |
|
39 |
- } |
|
40 |
- defer socket.Close() |
|
41 |
- f, err := socket.File() |
|
42 |
- if err != nil { |
|
43 |
- return nil, nil, errors.Wrapf(err, "failed to get fd for socket %s", address) |
|
44 |
- } |
|
45 |
- defer f.Close() |
|
46 |
- |
|
47 |
- cmd := newCommand(binary, daemonAddress, nonewns, debug, config, f) |
|
48 |
- ec, err := reaper.Default.Start(cmd) |
|
49 |
- if err != nil { |
|
50 |
- return nil, nil, errors.Wrapf(err, "failed to start shim") |
|
51 |
- } |
|
52 |
- defer func() { |
|
53 |
- if err != nil { |
|
54 |
- cmd.Process.Kill() |
|
55 |
- } |
|
56 |
- }() |
|
57 |
- go func() { |
|
58 |
- reaper.Default.Wait(cmd, ec) |
|
59 |
- exitHandler() |
|
60 |
- }() |
|
61 |
- log.G(ctx).WithFields(logrus.Fields{ |
|
62 |
- "pid": cmd.Process.Pid, |
|
63 |
- "address": address, |
|
64 |
- "debug": debug, |
|
65 |
- }).Infof("shim %s started", binary) |
|
66 |
- // set shim in cgroup if it is provided |
|
67 |
- if cgroup != "" { |
|
68 |
- if err := setCgroup(cgroup, cmd); err != nil { |
|
69 |
- return nil, nil, err |
|
70 |
- } |
|
71 |
- log.G(ctx).WithFields(logrus.Fields{ |
|
72 |
- "pid": cmd.Process.Pid, |
|
73 |
- "address": address, |
|
74 |
- }).Infof("shim placed in cgroup %s", cgroup) |
|
75 |
- } |
|
76 |
- if err = sys.SetOOMScore(cmd.Process.Pid, sys.OOMScoreMaxKillable); err != nil { |
|
77 |
- return nil, nil, errors.Wrap(err, "failed to set OOM Score on shim") |
|
78 |
- } |
|
79 |
- c, clo, err := WithConnect(address)(ctx, config) |
|
80 |
- if err != nil { |
|
81 |
- return nil, nil, errors.Wrap(err, "failed to connect") |
|
82 |
- } |
|
83 |
- return c, clo, nil |
|
84 |
- } |
|
85 |
-} |
|
86 |
- |
|
87 |
-func newCommand(binary, daemonAddress string, nonewns, debug bool, config Config, socket *os.File) *exec.Cmd { |
|
88 |
- args := []string{ |
|
89 |
- "--namespace", config.Namespace, |
|
90 |
- "--workdir", config.WorkDir, |
|
91 |
- "--address", daemonAddress, |
|
92 |
- } |
|
93 |
- |
|
94 |
- if config.Criu != "" { |
|
95 |
- args = append(args, "--criu-path", config.Criu) |
|
96 |
- } |
|
97 |
- if config.RuntimeRoot != "" { |
|
98 |
- args = append(args, "--runtime-root", config.RuntimeRoot) |
|
99 |
- } |
|
100 |
- if config.SystemdCgroup { |
|
101 |
- args = append(args, "--systemd-cgroup") |
|
102 |
- } |
|
103 |
- if debug { |
|
104 |
- args = append(args, "--debug") |
|
105 |
- } |
|
106 |
- |
|
107 |
- cmd := exec.Command(binary, args...) |
|
108 |
- cmd.Dir = config.Path |
|
109 |
- // make sure the shim can be re-parented to system init |
|
110 |
- // and is cloned in a new mount namespace because the overlay/filesystems |
|
111 |
- // will be mounted by the shim |
|
112 |
- cmd.SysProcAttr = getSysProcAttr(nonewns) |
|
113 |
- cmd.ExtraFiles = append(cmd.ExtraFiles, socket) |
|
114 |
- if debug { |
|
115 |
- cmd.Stdout = os.Stdout |
|
116 |
- cmd.Stderr = os.Stderr |
|
117 |
- } |
|
118 |
- return cmd |
|
119 |
-} |
|
120 |
- |
|
121 |
-func newSocket(address string) (*net.UnixListener, error) { |
|
122 |
- if len(address) > 106 { |
|
123 |
- return nil, errors.Errorf("%q: unix socket path too long (limit 106)", address) |
|
124 |
- } |
|
125 |
- l, err := net.Listen("unix", "\x00"+address) |
|
126 |
- if err != nil { |
|
127 |
- return nil, errors.Wrapf(err, "failed to listen to abstract unix socket %q", address) |
|
128 |
- } |
|
129 |
- |
|
130 |
- return l.(*net.UnixListener), nil |
|
131 |
-} |
|
132 |
- |
|
133 |
-func connect(address string, d func(string, time.Duration) (net.Conn, error)) (*grpc.ClientConn, error) { |
|
134 |
- gopts := []grpc.DialOption{ |
|
135 |
- grpc.WithBlock(), |
|
136 |
- grpc.WithInsecure(), |
|
137 |
- grpc.WithTimeout(100 * time.Second), |
|
138 |
- grpc.WithDialer(d), |
|
139 |
- grpc.FailOnNonTempDialError(true), |
|
140 |
- } |
|
141 |
- conn, err := grpc.Dial(dialAddress(address), gopts...) |
|
142 |
- if err != nil { |
|
143 |
- return nil, errors.Wrapf(err, "failed to dial %q", address) |
|
144 |
- } |
|
145 |
- return conn, nil |
|
146 |
-} |
|
147 |
- |
|
148 |
-func dialer(address string, timeout time.Duration) (net.Conn, error) { |
|
149 |
- address = strings.TrimPrefix(address, "unix://") |
|
150 |
- return net.DialTimeout("unix", address, timeout) |
|
151 |
-} |
|
152 |
- |
|
153 |
-func annonDialer(address string, timeout time.Duration) (net.Conn, error) { |
|
154 |
- address = strings.TrimPrefix(address, "unix://") |
|
155 |
- return net.DialTimeout("unix", "\x00"+address, timeout) |
|
156 |
-} |
|
157 |
- |
|
158 |
-func dialAddress(address string) string { |
|
159 |
- return fmt.Sprintf("unix://%s", address) |
|
160 |
-} |
|
161 |
- |
|
162 |
-// WithConnect connects to an existing shim |
|
163 |
-func WithConnect(address string) ClientOpt { |
|
164 |
- return func(ctx context.Context, config Config) (shim.ShimClient, io.Closer, error) { |
|
165 |
- conn, err := connect(address, annonDialer) |
|
166 |
- if err != nil { |
|
167 |
- return nil, nil, err |
|
168 |
- } |
|
169 |
- return shim.NewShimClient(conn), conn, nil |
|
170 |
- } |
|
171 |
-} |
|
172 |
- |
|
173 |
-// WithLocal uses an in process shim |
|
174 |
-func WithLocal(publisher events.Publisher) func(context.Context, Config) (shim.ShimClient, io.Closer, error) { |
|
175 |
- return func(ctx context.Context, config Config) (shim.ShimClient, io.Closer, error) { |
|
176 |
- service, err := NewService(config, publisher) |
|
177 |
- if err != nil { |
|
178 |
- return nil, nil, err |
|
179 |
- } |
|
180 |
- return NewLocal(service), nil, nil |
|
181 |
- } |
|
182 |
-} |
|
183 |
- |
|
184 |
-// Config contains shim specific configuration |
|
185 |
-type Config struct { |
|
186 |
- Path string |
|
187 |
- Namespace string |
|
188 |
- WorkDir string |
|
189 |
- Criu string |
|
190 |
- RuntimeRoot string |
|
191 |
- SystemdCgroup bool |
|
192 |
-} |
|
193 |
- |
|
194 |
-// New returns a new shim client |
|
195 |
-func New(ctx context.Context, config Config, opt ClientOpt) (*Client, error) { |
|
196 |
- s, c, err := opt(ctx, config) |
|
197 |
- if err != nil { |
|
198 |
- return nil, err |
|
199 |
- } |
|
200 |
- return &Client{ |
|
201 |
- ShimClient: s, |
|
202 |
- c: c, |
|
203 |
- exitCh: make(chan struct{}), |
|
204 |
- }, nil |
|
205 |
-} |
|
206 |
- |
|
207 |
-// Client is a shim client containing the connection to a shim |
|
208 |
-type Client struct { |
|
209 |
- shim.ShimClient |
|
210 |
- |
|
211 |
- c io.Closer |
|
212 |
- exitCh chan struct{} |
|
213 |
- exitOnce sync.Once |
|
214 |
-} |
|
215 |
- |
|
216 |
-// IsAlive returns true if the shim can be contacted. |
|
217 |
-// NOTE: a negative answer doesn't mean that the process is gone. |
|
218 |
-func (c *Client) IsAlive(ctx context.Context) (bool, error) { |
|
219 |
- _, err := c.ShimInfo(ctx, empty) |
|
220 |
- if err != nil { |
|
221 |
- if err != grpc.ErrServerStopped { |
|
222 |
- return false, err |
|
223 |
- } |
|
224 |
- return false, nil |
|
225 |
- } |
|
226 |
- return true, nil |
|
227 |
-} |
|
228 |
- |
|
229 |
-// StopShim signals the shim to exit and wait for the process to disappear |
|
230 |
-func (c *Client) StopShim(ctx context.Context) error { |
|
231 |
- return c.signalShim(ctx, unix.SIGTERM) |
|
232 |
-} |
|
233 |
- |
|
234 |
-// KillShim kills the shim forcefully and wait for the process to disappear |
|
235 |
-func (c *Client) KillShim(ctx context.Context) error { |
|
236 |
- return c.signalShim(ctx, unix.SIGKILL) |
|
237 |
-} |
|
238 |
- |
|
239 |
-// Close the cient connection |
|
240 |
-func (c *Client) Close() error { |
|
241 |
- if c.c == nil { |
|
242 |
- return nil |
|
243 |
- } |
|
244 |
- return c.c.Close() |
|
245 |
-} |
|
246 |
- |
|
247 |
-func (c *Client) signalShim(ctx context.Context, sig syscall.Signal) error { |
|
248 |
- info, err := c.ShimInfo(ctx, empty) |
|
249 |
- if err != nil { |
|
250 |
- return err |
|
251 |
- } |
|
252 |
- pid := int(info.ShimPid) |
|
253 |
- // make sure we don't kill ourselves if we are running a local shim |
|
254 |
- if os.Getpid() == pid { |
|
255 |
- return nil |
|
256 |
- } |
|
257 |
- if err := unix.Kill(pid, sig); err != nil && err != unix.ESRCH { |
|
258 |
- return err |
|
259 |
- } |
|
260 |
- // wait for shim to die after being signaled |
|
261 |
- select { |
|
262 |
- case <-ctx.Done(): |
|
263 |
- return ctx.Err() |
|
264 |
- case <-c.waitForExit(pid): |
|
265 |
- return nil |
|
266 |
- } |
|
267 |
-} |
|
268 |
- |
|
269 |
-func (c *Client) waitForExit(pid int) <-chan struct{} { |
|
270 |
- c.exitOnce.Do(func() { |
|
271 |
- for { |
|
272 |
- // use kill(pid, 0) here because the shim could have been reparented |
|
273 |
- // and we are no longer able to waitpid(pid, ...) on the shim |
|
274 |
- if err := unix.Kill(pid, 0); err == unix.ESRCH { |
|
275 |
- close(c.exitCh) |
|
276 |
- return |
|
277 |
- } |
|
278 |
- time.Sleep(10 * time.Millisecond) |
|
279 |
- } |
|
280 |
- }) |
|
281 |
- return c.exitCh |
|
282 |
-} |
283 | 1 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,276 @@ |
0 |
+// +build !windows |
|
1 |
+ |
|
2 |
+package client |
|
3 |
+ |
|
4 |
+import ( |
|
5 |
+ "context" |
|
6 |
+ "fmt" |
|
7 |
+ "io" |
|
8 |
+ "net" |
|
9 |
+ "os" |
|
10 |
+ "os/exec" |
|
11 |
+ "strings" |
|
12 |
+ "sync" |
|
13 |
+ "syscall" |
|
14 |
+ "time" |
|
15 |
+ |
|
16 |
+ "golang.org/x/sys/unix" |
|
17 |
+ |
|
18 |
+ "github.com/pkg/errors" |
|
19 |
+ "github.com/sirupsen/logrus" |
|
20 |
+ |
|
21 |
+ "github.com/containerd/containerd/events" |
|
22 |
+ "github.com/containerd/containerd/linux/shim" |
|
23 |
+ shimapi "github.com/containerd/containerd/linux/shim/v1" |
|
24 |
+ "github.com/containerd/containerd/log" |
|
25 |
+ "github.com/containerd/containerd/reaper" |
|
26 |
+ "github.com/containerd/containerd/sys" |
|
27 |
+ google_protobuf "github.com/golang/protobuf/ptypes/empty" |
|
28 |
+ "google.golang.org/grpc" |
|
29 |
+) |
|
30 |
+ |
|
31 |
+var empty = &google_protobuf.Empty{} |
|
32 |
+ |
|
33 |
+// Opt is an option for a shim client configuration |
|
34 |
+type Opt func(context.Context, shim.Config) (shimapi.ShimClient, io.Closer, error) |
|
35 |
+ |
|
36 |
+// WithStart executes a new shim process |
|
37 |
+func WithStart(binary, address, daemonAddress, cgroup string, nonewns, debug bool, exitHandler func()) Opt { |
|
38 |
+ return func(ctx context.Context, config shim.Config) (_ shimapi.ShimClient, _ io.Closer, err error) { |
|
39 |
+ socket, err := newSocket(address) |
|
40 |
+ if err != nil { |
|
41 |
+ return nil, nil, err |
|
42 |
+ } |
|
43 |
+ defer socket.Close() |
|
44 |
+ f, err := socket.File() |
|
45 |
+ if err != nil { |
|
46 |
+ return nil, nil, errors.Wrapf(err, "failed to get fd for socket %s", address) |
|
47 |
+ } |
|
48 |
+ defer f.Close() |
|
49 |
+ |
|
50 |
+ cmd := newCommand(binary, daemonAddress, nonewns, debug, config, f) |
|
51 |
+ ec, err := reaper.Default.Start(cmd) |
|
52 |
+ if err != nil { |
|
53 |
+ return nil, nil, errors.Wrapf(err, "failed to start shim") |
|
54 |
+ } |
|
55 |
+ defer func() { |
|
56 |
+ if err != nil { |
|
57 |
+ cmd.Process.Kill() |
|
58 |
+ } |
|
59 |
+ }() |
|
60 |
+ go func() { |
|
61 |
+ reaper.Default.Wait(cmd, ec) |
|
62 |
+ exitHandler() |
|
63 |
+ }() |
|
64 |
+ log.G(ctx).WithFields(logrus.Fields{ |
|
65 |
+ "pid": cmd.Process.Pid, |
|
66 |
+ "address": address, |
|
67 |
+ "debug": debug, |
|
68 |
+ }).Infof("shim %s started", binary) |
|
69 |
+ // set shim in cgroup if it is provided |
|
70 |
+ if cgroup != "" { |
|
71 |
+ if err := setCgroup(cgroup, cmd); err != nil { |
|
72 |
+ return nil, nil, err |
|
73 |
+ } |
|
74 |
+ log.G(ctx).WithFields(logrus.Fields{ |
|
75 |
+ "pid": cmd.Process.Pid, |
|
76 |
+ "address": address, |
|
77 |
+ }).Infof("shim placed in cgroup %s", cgroup) |
|
78 |
+ } |
|
79 |
+ if err = sys.SetOOMScore(cmd.Process.Pid, sys.OOMScoreMaxKillable); err != nil { |
|
80 |
+ return nil, nil, errors.Wrap(err, "failed to set OOM Score on shim") |
|
81 |
+ } |
|
82 |
+ c, clo, err := WithConnect(address)(ctx, config) |
|
83 |
+ if err != nil { |
|
84 |
+ return nil, nil, errors.Wrap(err, "failed to connect") |
|
85 |
+ } |
|
86 |
+ return c, clo, nil |
|
87 |
+ } |
|
88 |
+} |
|
89 |
+ |
|
90 |
+func newCommand(binary, daemonAddress string, nonewns, debug bool, config shim.Config, socket *os.File) *exec.Cmd { |
|
91 |
+ args := []string{ |
|
92 |
+ "-namespace", config.Namespace, |
|
93 |
+ "-workdir", config.WorkDir, |
|
94 |
+ "-address", daemonAddress, |
|
95 |
+ } |
|
96 |
+ |
|
97 |
+ if config.Criu != "" { |
|
98 |
+ args = append(args, "-criu-path", config.Criu) |
|
99 |
+ } |
|
100 |
+ if config.RuntimeRoot != "" { |
|
101 |
+ args = append(args, "-runtime-root", config.RuntimeRoot) |
|
102 |
+ } |
|
103 |
+ if config.SystemdCgroup { |
|
104 |
+ args = append(args, "-systemd-cgroup") |
|
105 |
+ } |
|
106 |
+ if debug { |
|
107 |
+ args = append(args, "-debug") |
|
108 |
+ } |
|
109 |
+ |
|
110 |
+ cmd := exec.Command(binary, args...) |
|
111 |
+ cmd.Dir = config.Path |
|
112 |
+ // make sure the shim can be re-parented to system init |
|
113 |
+ // and is cloned in a new mount namespace because the overlay/filesystems |
|
114 |
+ // will be mounted by the shim |
|
115 |
+ cmd.SysProcAttr = getSysProcAttr(nonewns) |
|
116 |
+ cmd.ExtraFiles = append(cmd.ExtraFiles, socket) |
|
117 |
+ if debug { |
|
118 |
+ cmd.Stdout = os.Stdout |
|
119 |
+ cmd.Stderr = os.Stderr |
|
120 |
+ } |
|
121 |
+ return cmd |
|
122 |
+} |
|
123 |
+ |
|
124 |
+func newSocket(address string) (*net.UnixListener, error) { |
|
125 |
+ if len(address) > 106 { |
|
126 |
+ return nil, errors.Errorf("%q: unix socket path too long (limit 106)", address) |
|
127 |
+ } |
|
128 |
+ l, err := net.Listen("unix", "\x00"+address) |
|
129 |
+ if err != nil { |
|
130 |
+ return nil, errors.Wrapf(err, "failed to listen to abstract unix socket %q", address) |
|
131 |
+ } |
|
132 |
+ |
|
133 |
+ return l.(*net.UnixListener), nil |
|
134 |
+} |
|
135 |
+ |
|
136 |
+func connect(address string, d func(string, time.Duration) (net.Conn, error)) (*grpc.ClientConn, error) { |
|
137 |
+ gopts := []grpc.DialOption{ |
|
138 |
+ grpc.WithBlock(), |
|
139 |
+ grpc.WithInsecure(), |
|
140 |
+ grpc.WithTimeout(100 * time.Second), |
|
141 |
+ grpc.WithDialer(d), |
|
142 |
+ grpc.FailOnNonTempDialError(true), |
|
143 |
+ } |
|
144 |
+ conn, err := grpc.Dial(dialAddress(address), gopts...) |
|
145 |
+ if err != nil { |
|
146 |
+ return nil, errors.Wrapf(err, "failed to dial %q", address) |
|
147 |
+ } |
|
148 |
+ return conn, nil |
|
149 |
+} |
|
150 |
+ |
|
151 |
+func dialer(address string, timeout time.Duration) (net.Conn, error) { |
|
152 |
+ address = strings.TrimPrefix(address, "unix://") |
|
153 |
+ return net.DialTimeout("unix", address, timeout) |
|
154 |
+} |
|
155 |
+ |
|
156 |
+func annonDialer(address string, timeout time.Duration) (net.Conn, error) { |
|
157 |
+ address = strings.TrimPrefix(address, "unix://") |
|
158 |
+ return net.DialTimeout("unix", "\x00"+address, timeout) |
|
159 |
+} |
|
160 |
+ |
|
161 |
+func dialAddress(address string) string { |
|
162 |
+ return fmt.Sprintf("unix://%s", address) |
|
163 |
+} |
|
164 |
+ |
|
165 |
+// WithConnect connects to an existing shim |
|
166 |
+func WithConnect(address string) Opt { |
|
167 |
+ return func(ctx context.Context, config shim.Config) (shimapi.ShimClient, io.Closer, error) { |
|
168 |
+ conn, err := connect(address, annonDialer) |
|
169 |
+ if err != nil { |
|
170 |
+ return nil, nil, err |
|
171 |
+ } |
|
172 |
+ return shimapi.NewShimClient(conn), conn, nil |
|
173 |
+ } |
|
174 |
+} |
|
175 |
+ |
|
176 |
+// WithLocal uses an in process shim |
|
177 |
+func WithLocal(publisher events.Publisher) func(context.Context, shim.Config) (shimapi.ShimClient, io.Closer, error) { |
|
178 |
+ return func(ctx context.Context, config shim.Config) (shimapi.ShimClient, io.Closer, error) { |
|
179 |
+ service, err := shim.NewService(config, publisher) |
|
180 |
+ if err != nil { |
|
181 |
+ return nil, nil, err |
|
182 |
+ } |
|
183 |
+ return shim.NewLocal(service), nil, nil |
|
184 |
+ } |
|
185 |
+} |
|
186 |
+ |
|
187 |
+// New returns a new shim client |
|
188 |
+func New(ctx context.Context, config shim.Config, opt Opt) (*Client, error) { |
|
189 |
+ s, c, err := opt(ctx, config) |
|
190 |
+ if err != nil { |
|
191 |
+ return nil, err |
|
192 |
+ } |
|
193 |
+ return &Client{ |
|
194 |
+ ShimClient: s, |
|
195 |
+ c: c, |
|
196 |
+ exitCh: make(chan struct{}), |
|
197 |
+ }, nil |
|
198 |
+} |
|
199 |
+ |
|
200 |
+// Client is a shim client containing the connection to a shim |
|
201 |
+type Client struct { |
|
202 |
+ shimapi.ShimClient |
|
203 |
+ |
|
204 |
+ c io.Closer |
|
205 |
+ exitCh chan struct{} |
|
206 |
+ exitOnce sync.Once |
|
207 |
+} |
|
208 |
+ |
|
209 |
+// IsAlive returns true if the shim can be contacted. |
|
210 |
+// NOTE: a negative answer doesn't mean that the process is gone. |
|
211 |
+func (c *Client) IsAlive(ctx context.Context) (bool, error) { |
|
212 |
+ _, err := c.ShimInfo(ctx, empty) |
|
213 |
+ if err != nil { |
|
214 |
+ if err != grpc.ErrServerStopped { |
|
215 |
+ return false, err |
|
216 |
+ } |
|
217 |
+ return false, nil |
|
218 |
+ } |
|
219 |
+ return true, nil |
|
220 |
+} |
|
221 |
+ |
|
222 |
+// StopShim signals the shim to exit and wait for the process to disappear |
|
223 |
+func (c *Client) StopShim(ctx context.Context) error { |
|
224 |
+ return c.signalShim(ctx, unix.SIGTERM) |
|
225 |
+} |
|
226 |
+ |
|
227 |
+// KillShim kills the shim forcefully and wait for the process to disappear |
|
228 |
+func (c *Client) KillShim(ctx context.Context) error { |
|
229 |
+ return c.signalShim(ctx, unix.SIGKILL) |
|
230 |
+} |
|
231 |
+ |
|
232 |
+// Close the cient connection |
|
233 |
+func (c *Client) Close() error { |
|
234 |
+ if c.c == nil { |
|
235 |
+ return nil |
|
236 |
+ } |
|
237 |
+ return c.c.Close() |
|
238 |
+} |
|
239 |
+ |
|
240 |
+func (c *Client) signalShim(ctx context.Context, sig syscall.Signal) error { |
|
241 |
+ info, err := c.ShimInfo(ctx, empty) |
|
242 |
+ if err != nil { |
|
243 |
+ return err |
|
244 |
+ } |
|
245 |
+ pid := int(info.ShimPid) |
|
246 |
+ // make sure we don't kill ourselves if we are running a local shim |
|
247 |
+ if os.Getpid() == pid { |
|
248 |
+ return nil |
|
249 |
+ } |
|
250 |
+ if err := unix.Kill(pid, sig); err != nil && err != unix.ESRCH { |
|
251 |
+ return err |
|
252 |
+ } |
|
253 |
+ // wait for shim to die after being signaled |
|
254 |
+ select { |
|
255 |
+ case <-ctx.Done(): |
|
256 |
+ return ctx.Err() |
|
257 |
+ case <-c.waitForExit(pid): |
|
258 |
+ return nil |
|
259 |
+ } |
|
260 |
+} |
|
261 |
+ |
|
262 |
+func (c *Client) waitForExit(pid int) <-chan struct{} { |
|
263 |
+ c.exitOnce.Do(func() { |
|
264 |
+ for { |
|
265 |
+ // use kill(pid, 0) here because the shim could have been reparented |
|
266 |
+ // and we are no longer able to waitpid(pid, ...) on the shim |
|
267 |
+ if err := unix.Kill(pid, 0); err == unix.ESRCH { |
|
268 |
+ close(c.exitCh) |
|
269 |
+ return |
|
270 |
+ } |
|
271 |
+ time.Sleep(10 * time.Millisecond) |
|
272 |
+ } |
|
273 |
+ }) |
|
274 |
+ return c.exitCh |
|
275 |
+} |
0 | 276 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,34 @@ |
0 |
+// +build linux |
|
1 |
+ |
|
2 |
+package client |
|
3 |
+ |
|
4 |
+import ( |
|
5 |
+ "os/exec" |
|
6 |
+ "syscall" |
|
7 |
+ |
|
8 |
+ "github.com/containerd/cgroups" |
|
9 |
+ "github.com/pkg/errors" |
|
10 |
+) |
|
11 |
+ |
|
12 |
+func getSysProcAttr(nonewns bool) *syscall.SysProcAttr { |
|
13 |
+ attr := syscall.SysProcAttr{ |
|
14 |
+ Setpgid: true, |
|
15 |
+ } |
|
16 |
+ if !nonewns { |
|
17 |
+ attr.Cloneflags = syscall.CLONE_NEWNS |
|
18 |
+ } |
|
19 |
+ return &attr |
|
20 |
+} |
|
21 |
+ |
|
22 |
+func setCgroup(cgroupPath string, cmd *exec.Cmd) error { |
|
23 |
+ cg, err := cgroups.Load(cgroups.V1, cgroups.StaticPath(cgroupPath)) |
|
24 |
+ if err != nil { |
|
25 |
+ return errors.Wrapf(err, "failed to load cgroup %s", cgroupPath) |
|
26 |
+ } |
|
27 |
+ if err := cg.Add(cgroups.Process{ |
|
28 |
+ Pid: cmd.Process.Pid, |
|
29 |
+ }); err != nil { |
|
30 |
+ return errors.Wrapf(err, "failed to join cgroup %s", cgroupPath) |
|
31 |
+ } |
|
32 |
+ return nil |
|
33 |
+} |
0 | 34 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,18 @@ |
0 |
+// +build !linux,!windows |
|
1 |
+ |
|
2 |
+package client |
|
3 |
+ |
|
4 |
+import ( |
|
5 |
+ "os/exec" |
|
6 |
+ "syscall" |
|
7 |
+) |
|
8 |
+ |
|
9 |
+func getSysProcAttr(nonewns bool) *syscall.SysProcAttr { |
|
10 |
+ return &syscall.SysProcAttr{ |
|
11 |
+ Setpgid: true, |
|
12 |
+ } |
|
13 |
+} |
|
14 |
+ |
|
15 |
+func setCgroup(cgroupPath string, cmd *exec.Cmd) error { |
|
16 |
+ return nil |
|
17 |
+} |
0 | 18 |
deleted file mode 100644 |
... | ... |
@@ -1,34 +0,0 @@ |
1 |
-// +build linux |
|
2 |
- |
|
3 |
-package shim |
|
4 |
- |
|
5 |
-import ( |
|
6 |
- "os/exec" |
|
7 |
- "syscall" |
|
8 |
- |
|
9 |
- "github.com/containerd/cgroups" |
|
10 |
- "github.com/pkg/errors" |
|
11 |
-) |
|
12 |
- |
|
13 |
-func getSysProcAttr(nonewns bool) *syscall.SysProcAttr { |
|
14 |
- attr := syscall.SysProcAttr{ |
|
15 |
- Setpgid: true, |
|
16 |
- } |
|
17 |
- if !nonewns { |
|
18 |
- attr.Cloneflags = syscall.CLONE_NEWNS |
|
19 |
- } |
|
20 |
- return &attr |
|
21 |
-} |
|
22 |
- |
|
23 |
-func setCgroup(cgroupPath string, cmd *exec.Cmd) error { |
|
24 |
- cg, err := cgroups.Load(cgroups.V1, cgroups.StaticPath(cgroupPath)) |
|
25 |
- if err != nil { |
|
26 |
- return errors.Wrapf(err, "failed to load cgroup %s", cgroupPath) |
|
27 |
- } |
|
28 |
- if err := cg.Add(cgroups.Process{ |
|
29 |
- Pid: cmd.Process.Pid, |
|
30 |
- }); err != nil { |
|
31 |
- return errors.Wrapf(err, "failed to join cgroup %s", cgroupPath) |
|
32 |
- } |
|
33 |
- return nil |
|
34 |
-} |
35 | 1 |
deleted file mode 100644 |
... | ... |
@@ -1,18 +0,0 @@ |
1 |
-// +build !linux,!windows |
|
2 |
- |
|
3 |
-package shim |
|
4 |
- |
|
5 |
-import ( |
|
6 |
- "os/exec" |
|
7 |
- "syscall" |
|
8 |
-) |
|
9 |
- |
|
10 |
-func getSysProcAttr(nonewns bool) *syscall.SysProcAttr { |
|
11 |
- return &syscall.SysProcAttr{ |
|
12 |
- Setpgid: true, |
|
13 |
- } |
|
14 |
-} |
|
15 |
- |
|
16 |
-func setCgroup(cgroupPath string, cmd *exec.Cmd) error { |
|
17 |
- return nil |
|
18 |
-} |
... | ... |
@@ -98,12 +98,16 @@ func (s *Service) newInitProcess(context context.Context, r *shimapi.CreateTaskR |
98 | 98 |
return nil, errors.Wrapf(err, "failed to mount rootfs component %v", m) |
99 | 99 |
} |
100 | 100 |
} |
101 |
+ root := s.config.RuntimeRoot |
|
102 |
+ if root == "" { |
|
103 |
+ root = RuncRoot |
|
104 |
+ } |
|
101 | 105 |
runtime := &runc.Runc{ |
102 | 106 |
Command: r.Runtime, |
103 | 107 |
Log: filepath.Join(s.config.Path, "log.json"), |
104 | 108 |
LogFormat: runc.JSON, |
105 | 109 |
PdeathSignal: syscall.SIGKILL, |
106 |
- Root: filepath.Join(s.config.RuntimeRoot, s.config.Namespace), |
|
110 |
+ Root: filepath.Join(root, s.config.Namespace), |
|
107 | 111 |
Criu: s.config.Criu, |
108 | 112 |
SystemdCgroup: s.config.SystemdCgroup, |
109 | 113 |
} |
... | ... |
@@ -32,6 +32,16 @@ var empty = &google_protobuf.Empty{} |
32 | 32 |
// RuncRoot is the path to the root runc state directory |
33 | 33 |
const RuncRoot = "/run/containerd/runc" |
34 | 34 |
|
35 |
+// Config contains shim specific configuration |
|
36 |
+type Config struct { |
|
37 |
+ Path string |
|
38 |
+ Namespace string |
|
39 |
+ WorkDir string |
|
40 |
+ Criu string |
|
41 |
+ RuntimeRoot string |
|
42 |
+ SystemdCgroup bool |
|
43 |
+} |
|
44 |
+ |
|
35 | 45 |
// NewService returns a new shim service that can be used via GRPC |
36 | 46 |
func NewService(config Config, publisher events.Publisher) (*Service, error) { |
37 | 47 |
if config.Namespace == "" { |
... | ... |
@@ -11,7 +11,7 @@ import ( |
11 | 11 |
"github.com/containerd/cgroups" |
12 | 12 |
"github.com/containerd/containerd/api/types/task" |
13 | 13 |
"github.com/containerd/containerd/errdefs" |
14 |
- client "github.com/containerd/containerd/linux/shim" |
|
14 |
+ "github.com/containerd/containerd/linux/shim/client" |
|
15 | 15 |
shim "github.com/containerd/containerd/linux/shim/v1" |
16 | 16 |
"github.com/containerd/containerd/runtime" |
17 | 17 |
"github.com/gogo/protobuf/types" |
... | ... |
@@ -38,6 +38,7 @@ var ( |
38 | 38 |
bucketKeyObjectContent = []byte("content") // stores content references |
39 | 39 |
bucketKeyObjectBlob = []byte("blob") // stores content links |
40 | 40 |
bucketKeyObjectIngest = []byte("ingest") // stores ingest links |
41 |
+ bucketKeyObjectLeases = []byte("leases") // stores leases |
|
41 | 42 |
|
42 | 43 |
bucketKeyDigest = []byte("digest") |
43 | 44 |
bucketKeyMediaType = []byte("mediatype") |
... | ... |
@@ -53,6 +54,7 @@ var ( |
53 | 53 |
bucketKeySnapshotter = []byte("snapshotter") |
54 | 54 |
bucketKeyTarget = []byte("target") |
55 | 55 |
bucketKeyExtensions = []byte("extensions") |
56 |
+ bucketKeyCreatedAt = []byte("createdat") |
|
56 | 57 |
) |
57 | 58 |
|
58 | 59 |
func getBucket(tx *bolt.Tx, keys ...[]byte) *bolt.Bucket { |
... | ... |
@@ -391,27 +391,31 @@ func (nw *namespacedWriter) Commit(ctx context.Context, size int64, expected dig |
391 | 391 |
return err |
392 | 392 |
} |
393 | 393 |
} |
394 |
- return nw.commit(ctx, tx, size, expected, opts...) |
|
394 |
+ dgst, err := nw.commit(ctx, tx, size, expected, opts...) |
|
395 |
+ if err != nil { |
|
396 |
+ return err |
|
397 |
+ } |
|
398 |
+ return addContentLease(ctx, tx, dgst) |
|
395 | 399 |
}) |
396 | 400 |
} |
397 | 401 |
|
398 |
-func (nw *namespacedWriter) commit(ctx context.Context, tx *bolt.Tx, size int64, expected digest.Digest, opts ...content.Opt) error { |
|
402 |
+func (nw *namespacedWriter) commit(ctx context.Context, tx *bolt.Tx, size int64, expected digest.Digest, opts ...content.Opt) (digest.Digest, error) { |
|
399 | 403 |
var base content.Info |
400 | 404 |
for _, opt := range opts { |
401 | 405 |
if err := opt(&base); err != nil { |
402 |
- return err |
|
406 |
+ return "", err |
|
403 | 407 |
} |
404 | 408 |
} |
405 | 409 |
if err := validateInfo(&base); err != nil { |
406 |
- return err |
|
410 |
+ return "", err |
|
407 | 411 |
} |
408 | 412 |
|
409 | 413 |
status, err := nw.Writer.Status() |
410 | 414 |
if err != nil { |
411 |
- return err |
|
415 |
+ return "", err |
|
412 | 416 |
} |
413 | 417 |
if size != 0 && size != status.Offset { |
414 |
- return errors.Errorf("%q failed size validation: %v != %v", nw.ref, status.Offset, size) |
|
418 |
+ return "", errors.Errorf("%q failed size validation: %v != %v", nw.ref, status.Offset, size) |
|
415 | 419 |
} |
416 | 420 |
size = status.Offset |
417 | 421 |
|
... | ... |
@@ -419,32 +423,32 @@ func (nw *namespacedWriter) commit(ctx context.Context, tx *bolt.Tx, size int64, |
419 | 419 |
|
420 | 420 |
if err := nw.Writer.Commit(ctx, size, expected); err != nil { |
421 | 421 |
if !errdefs.IsAlreadyExists(err) { |
422 |
- return err |
|
422 |
+ return "", err |
|
423 | 423 |
} |
424 | 424 |
if getBlobBucket(tx, nw.namespace, actual) != nil { |
425 |
- return errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", actual) |
|
425 |
+ return "", errors.Wrapf(errdefs.ErrAlreadyExists, "content %v", actual) |
|
426 | 426 |
} |
427 | 427 |
} |
428 | 428 |
|
429 | 429 |
bkt, err := createBlobBucket(tx, nw.namespace, actual) |
430 | 430 |
if err != nil { |
431 |
- return err |
|
431 |
+ return "", err |
|
432 | 432 |
} |
433 | 433 |
|
434 | 434 |
commitTime := time.Now().UTC() |
435 | 435 |
|
436 | 436 |
sizeEncoded, err := encodeInt(size) |
437 | 437 |
if err != nil { |
438 |
- return err |
|
438 |
+ return "", err |
|
439 | 439 |
} |
440 | 440 |
|
441 | 441 |
if err := boltutil.WriteTimestamps(bkt, commitTime, commitTime); err != nil { |
442 |
- return err |
|
442 |
+ return "", err |
|
443 | 443 |
} |
444 | 444 |
if err := boltutil.WriteLabels(bkt, base.Labels); err != nil { |
445 |
- return err |
|
445 |
+ return "", err |
|
446 | 446 |
} |
447 |
- return bkt.Put(bucketKeySize, sizeEncoded) |
|
447 |
+ return actual, bkt.Put(bucketKeySize, sizeEncoded) |
|
448 | 448 |
} |
449 | 449 |
|
450 | 450 |
func (nw *namespacedWriter) Status() (content.Status, error) { |
... | ... |
@@ -566,7 +570,7 @@ func (cs *contentStore) garbageCollect(ctx context.Context) error { |
566 | 566 |
return err |
567 | 567 |
} |
568 | 568 |
|
569 |
- if err := cs.Store.Walk(ctx, func(info content.Info) error { |
|
569 |
+ return cs.Store.Walk(ctx, func(info content.Info) error { |
|
570 | 570 |
if _, ok := seen[info.Digest.String()]; !ok { |
571 | 571 |
if err := cs.Store.Delete(ctx, info.Digest); err != nil { |
572 | 572 |
return err |
... | ... |
@@ -574,9 +578,5 @@ func (cs *contentStore) garbageCollect(ctx context.Context) error { |
574 | 574 |
log.G(ctx).WithField("digest", info.Digest).Debug("removed content") |
575 | 575 |
} |
576 | 576 |
return nil |
577 |
- }); err != nil { |
|
578 |
- return err |
|
579 |
- } |
|
580 |
- |
|
581 |
- return nil |
|
577 |
+ }) |
|
582 | 578 |
} |
... | ... |
@@ -190,6 +190,7 @@ func (m *DB) Update(fn func(*bolt.Tx) error) error { |
190 | 190 |
return m.db.Update(fn) |
191 | 191 |
} |
192 | 192 |
|
193 |
+// GarbageCollect starts garbage collection |
|
193 | 194 |
func (m *DB) GarbageCollect(ctx context.Context) error { |
194 | 195 |
lt1 := time.Now() |
195 | 196 |
m.wlock.Lock() |
... | ... |
@@ -198,39 +199,8 @@ func (m *DB) GarbageCollect(ctx context.Context) error { |
198 | 198 |
log.G(ctx).WithField("d", time.Now().Sub(lt1)).Debug("metadata garbage collected") |
199 | 199 |
}() |
200 | 200 |
|
201 |
- var marked map[gc.Node]struct{} |
|
202 |
- |
|
203 |
- if err := m.db.View(func(tx *bolt.Tx) error { |
|
204 |
- ctx, cancel := context.WithCancel(ctx) |
|
205 |
- defer cancel() |
|
206 |
- |
|
207 |
- roots := make(chan gc.Node) |
|
208 |
- errChan := make(chan error) |
|
209 |
- go func() { |
|
210 |
- defer close(errChan) |
|
211 |
- defer close(roots) |
|
212 |
- |
|
213 |
- // Call roots |
|
214 |
- if err := scanRoots(ctx, tx, roots); err != nil { |
|
215 |
- cancel() |
|
216 |
- errChan <- err |
|
217 |
- } |
|
218 |
- }() |
|
219 |
- |
|
220 |
- refs := func(ctx context.Context, n gc.Node, fn func(gc.Node)) error { |
|
221 |
- return references(ctx, tx, n, fn) |
|
222 |
- } |
|
223 |
- |
|
224 |
- reachable, err := gc.ConcurrentMark(ctx, roots, refs) |
|
225 |
- if rerr := <-errChan; rerr != nil { |
|
226 |
- return rerr |
|
227 |
- } |
|
228 |
- if err != nil { |
|
229 |
- return err |
|
230 |
- } |
|
231 |
- marked = reachable |
|
232 |
- return nil |
|
233 |
- }); err != nil { |
|
201 |
+ marked, err := m.getMarked(ctx) |
|
202 |
+ if err != nil { |
|
234 | 203 |
return err |
235 | 204 |
} |
236 | 205 |
|
... | ... |
@@ -241,15 +211,11 @@ func (m *DB) GarbageCollect(ctx context.Context) error { |
241 | 241 |
ctx, cancel := context.WithCancel(ctx) |
242 | 242 |
defer cancel() |
243 | 243 |
|
244 |
- nodeC := make(chan gc.Node) |
|
245 |
- var scanErr error |
|
246 |
- |
|
247 |
- go func() { |
|
248 |
- defer close(nodeC) |
|
249 |
- scanErr = scanAll(ctx, tx, nodeC) |
|
250 |
- }() |
|
244 |
+ rm := func(ctx context.Context, n gc.Node) error { |
|
245 |
+ if _, ok := marked[n]; ok { |
|
246 |
+ return nil |
|
247 |
+ } |
|
251 | 248 |
|
252 |
- rm := func(n gc.Node) error { |
|
253 | 249 |
if n.Type == ResourceSnapshot { |
254 | 250 |
if idx := strings.IndexRune(n.Key, '/'); idx > 0 { |
255 | 251 |
m.dirtySS[n.Key[:idx]] = struct{}{} |
... | ... |
@@ -260,12 +226,8 @@ func (m *DB) GarbageCollect(ctx context.Context) error { |
260 | 260 |
return remove(ctx, tx, n) |
261 | 261 |
} |
262 | 262 |
|
263 |
- if err := gc.Sweep(marked, nodeC, rm); err != nil { |
|
264 |
- return errors.Wrap(err, "failed to sweep") |
|
265 |
- } |
|
266 |
- |
|
267 |
- if scanErr != nil { |
|
268 |
- return errors.Wrap(scanErr, "failed to scan all") |
|
263 |
+ if err := scanAll(ctx, tx, rm); err != nil { |
|
264 |
+ return errors.Wrap(err, "failed to scan and remove") |
|
269 | 265 |
} |
270 | 266 |
|
271 | 267 |
return nil |
... | ... |
@@ -292,6 +254,54 @@ func (m *DB) GarbageCollect(ctx context.Context) error { |
292 | 292 |
return nil |
293 | 293 |
} |
294 | 294 |
|
295 |
+func (m *DB) getMarked(ctx context.Context) (map[gc.Node]struct{}, error) { |
|
296 |
+ var marked map[gc.Node]struct{} |
|
297 |
+ if err := m.db.View(func(tx *bolt.Tx) error { |
|
298 |
+ ctx, cancel := context.WithCancel(ctx) |
|
299 |
+ defer cancel() |
|
300 |
+ |
|
301 |
+ var ( |
|
302 |
+ nodes []gc.Node |
|
303 |
+ wg sync.WaitGroup |
|
304 |
+ roots = make(chan gc.Node) |
|
305 |
+ ) |
|
306 |
+ wg.Add(1) |
|
307 |
+ go func() { |
|
308 |
+ defer wg.Done() |
|
309 |
+ for n := range roots { |
|
310 |
+ nodes = append(nodes, n) |
|
311 |
+ } |
|
312 |
+ }() |
|
313 |
+ // Call roots |
|
314 |
+ if err := scanRoots(ctx, tx, roots); err != nil { |
|
315 |
+ cancel() |
|
316 |
+ return err |
|
317 |
+ } |
|
318 |
+ close(roots) |
|
319 |
+ wg.Wait() |
|
320 |
+ |
|
321 |
+ refs := func(n gc.Node) ([]gc.Node, error) { |
|
322 |
+ var sn []gc.Node |
|
323 |
+ if err := references(ctx, tx, n, func(nn gc.Node) { |
|
324 |
+ sn = append(sn, nn) |
|
325 |
+ }); err != nil { |
|
326 |
+ return nil, err |
|
327 |
+ } |
|
328 |
+ return sn, nil |
|
329 |
+ } |
|
330 |
+ |
|
331 |
+ reachable, err := gc.Tricolor(nodes, refs) |
|
332 |
+ if err != nil { |
|
333 |
+ return err |
|
334 |
+ } |
|
335 |
+ marked = reachable |
|
336 |
+ return nil |
|
337 |
+ }); err != nil { |
|
338 |
+ return nil, err |
|
339 |
+ } |
|
340 |
+ return marked, nil |
|
341 |
+} |
|
342 |
+ |
|
295 | 343 |
func (m *DB) cleanupSnapshotter(name string) { |
296 | 344 |
ctx := context.Background() |
297 | 345 |
sn, ok := m.ss[name] |
... | ... |
@@ -12,10 +12,15 @@ import ( |
12 | 12 |
) |
13 | 13 |
|
14 | 14 |
const ( |
15 |
+ // ResourceUnknown specifies an unknown resource |
|
15 | 16 |
ResourceUnknown gc.ResourceType = iota |
17 |
+ // ResourceContent specifies a content resource |
|
16 | 18 |
ResourceContent |
19 |
+ // ResourceSnapshot specifies a snapshot resource |
|
17 | 20 |
ResourceSnapshot |
21 |
+ // ResourceContainer specifies a container resource |
|
18 | 22 |
ResourceContainer |
23 |
+ // ResourceTask specifies a task resource |
|
19 | 24 |
ResourceTask |
20 | 25 |
) |
21 | 26 |
|
... | ... |
@@ -41,6 +46,55 @@ func scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error { |
41 | 41 |
nbkt := v1bkt.Bucket(k) |
42 | 42 |
ns := string(k) |
43 | 43 |
|
44 |
+ lbkt := nbkt.Bucket(bucketKeyObjectLeases) |
|
45 |
+ if lbkt != nil { |
|
46 |
+ if err := lbkt.ForEach(func(k, v []byte) error { |
|
47 |
+ if v != nil { |
|
48 |
+ return nil |
|
49 |
+ } |
|
50 |
+ libkt := lbkt.Bucket(k) |
|
51 |
+ |
|
52 |
+ cbkt := libkt.Bucket(bucketKeyObjectContent) |
|
53 |
+ if cbkt != nil { |
|
54 |
+ if err := cbkt.ForEach(func(k, v []byte) error { |
|
55 |
+ select { |
|
56 |
+ case nc <- gcnode(ResourceContent, ns, string(k)): |
|
57 |
+ case <-ctx.Done(): |
|
58 |
+ return ctx.Err() |
|
59 |
+ } |
|
60 |
+ return nil |
|
61 |
+ }); err != nil { |
|
62 |
+ return err |
|
63 |
+ } |
|
64 |
+ } |
|
65 |
+ |
|
66 |
+ sbkt := libkt.Bucket(bucketKeyObjectSnapshots) |
|
67 |
+ if sbkt != nil { |
|
68 |
+ if err := sbkt.ForEach(func(sk, sv []byte) error { |
|
69 |
+ if sv != nil { |
|
70 |
+ return nil |
|
71 |
+ } |
|
72 |
+ snbkt := sbkt.Bucket(sk) |
|
73 |
+ |
|
74 |
+ return snbkt.ForEach(func(k, v []byte) error { |
|
75 |
+ select { |
|
76 |
+ case nc <- gcnode(ResourceSnapshot, ns, fmt.Sprintf("%s/%s", sk, k)): |
|
77 |
+ case <-ctx.Done(): |
|
78 |
+ return ctx.Err() |
|
79 |
+ } |
|
80 |
+ return nil |
|
81 |
+ }) |
|
82 |
+ }); err != nil { |
|
83 |
+ return err |
|
84 |
+ } |
|
85 |
+ } |
|
86 |
+ |
|
87 |
+ return nil |
|
88 |
+ }); err != nil { |
|
89 |
+ return err |
|
90 |
+ } |
|
91 |
+ } |
|
92 |
+ |
|
44 | 93 |
ibkt := nbkt.Bucket(bucketKeyObjectImages) |
45 | 94 |
if ibkt != nil { |
46 | 95 |
if err := ibkt.ForEach(func(k, v []byte) error { |
... | ... |
@@ -174,7 +228,7 @@ func references(ctx context.Context, tx *bolt.Tx, node gc.Node, fn func(gc.Node) |
174 | 174 |
return nil |
175 | 175 |
} |
176 | 176 |
|
177 |
-func scanAll(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error { |
|
177 |
+func scanAll(ctx context.Context, tx *bolt.Tx, fn func(ctx context.Context, n gc.Node) error) error { |
|
178 | 178 |
v1bkt := tx.Bucket(bucketKeyVersion) |
179 | 179 |
if v1bkt == nil { |
180 | 180 |
return nil |
... | ... |
@@ -201,12 +255,8 @@ func scanAll(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error { |
201 | 201 |
if v != nil { |
202 | 202 |
return nil |
203 | 203 |
} |
204 |
- select { |
|
205 |
- case nc <- gcnode(ResourceSnapshot, ns, fmt.Sprintf("%s/%s", sk, k)): |
|
206 |
- case <-ctx.Done(): |
|
207 |
- return ctx.Err() |
|
208 |
- } |
|
209 |
- return nil |
|
204 |
+ node := gcnode(ResourceSnapshot, ns, fmt.Sprintf("%s/%s", sk, k)) |
|
205 |
+ return fn(ctx, node) |
|
210 | 206 |
}) |
211 | 207 |
}); err != nil { |
212 | 208 |
return err |
... | ... |
@@ -222,12 +272,8 @@ func scanAll(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Node) error { |
222 | 222 |
if v != nil { |
223 | 223 |
return nil |
224 | 224 |
} |
225 |
- select { |
|
226 |
- case nc <- gcnode(ResourceContent, ns, string(k)): |
|
227 |
- case <-ctx.Done(): |
|
228 |
- return ctx.Err() |
|
229 |
- } |
|
230 |
- return nil |
|
225 |
+ node := gcnode(ResourceContent, ns, string(k)) |
|
226 |
+ return fn(ctx, node) |
|
231 | 227 |
}); err != nil { |
232 | 228 |
return err |
233 | 229 |
} |
234 | 230 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,201 @@ |
0 |
+package metadata |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "context" |
|
4 |
+ "time" |
|
5 |
+ |
|
6 |
+ "github.com/boltdb/bolt" |
|
7 |
+ "github.com/containerd/containerd/errdefs" |
|
8 |
+ "github.com/containerd/containerd/leases" |
|
9 |
+ "github.com/containerd/containerd/metadata/boltutil" |
|
10 |
+ "github.com/containerd/containerd/namespaces" |
|
11 |
+ digest "github.com/opencontainers/go-digest" |
|
12 |
+ "github.com/pkg/errors" |
|
13 |
+) |
|
14 |
+ |
|
15 |
+// Lease retains resources to prevent garbage collection before |
|
16 |
+// the resources can be fully referenced. |
|
17 |
+type Lease struct { |
|
18 |
+ ID string |
|
19 |
+ CreatedAt time.Time |
|
20 |
+ Labels map[string]string |
|
21 |
+ |
|
22 |
+ Content []string |
|
23 |
+ Snapshots map[string][]string |
|
24 |
+} |
|
25 |
+ |
|
26 |
+// LeaseManager manages the create/delete lifecyle of leases |
|
27 |
+// and also returns existing leases |
|
28 |
+type LeaseManager struct { |
|
29 |
+ tx *bolt.Tx |
|
30 |
+} |
|
31 |
+ |
|
32 |
+// NewLeaseManager creates a new lease manager for managing leases using |
|
33 |
+// the provided database transaction. |
|
34 |
+func NewLeaseManager(tx *bolt.Tx) *LeaseManager { |
|
35 |
+ return &LeaseManager{ |
|
36 |
+ tx: tx, |
|
37 |
+ } |
|
38 |
+} |
|
39 |
+ |
|
40 |
+// Create creates a new lease using the provided lease |
|
41 |
+func (lm *LeaseManager) Create(ctx context.Context, lid string, labels map[string]string) (Lease, error) { |
|
42 |
+ namespace, err := namespaces.NamespaceRequired(ctx) |
|
43 |
+ if err != nil { |
|
44 |
+ return Lease{}, err |
|
45 |
+ } |
|
46 |
+ |
|
47 |
+ topbkt, err := createBucketIfNotExists(lm.tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases) |
|
48 |
+ if err != nil { |
|
49 |
+ return Lease{}, err |
|
50 |
+ } |
|
51 |
+ |
|
52 |
+ txbkt, err := topbkt.CreateBucket([]byte(lid)) |
|
53 |
+ if err != nil { |
|
54 |
+ if err == bolt.ErrBucketExists { |
|
55 |
+ err = errdefs.ErrAlreadyExists |
|
56 |
+ } |
|
57 |
+ return Lease{}, err |
|
58 |
+ } |
|
59 |
+ |
|
60 |
+ t := time.Now().UTC() |
|
61 |
+ createdAt, err := t.MarshalBinary() |
|
62 |
+ if err != nil { |
|
63 |
+ return Lease{}, err |
|
64 |
+ } |
|
65 |
+ if err := txbkt.Put(bucketKeyCreatedAt, createdAt); err != nil { |
|
66 |
+ return Lease{}, err |
|
67 |
+ } |
|
68 |
+ |
|
69 |
+ if labels != nil { |
|
70 |
+ if err := boltutil.WriteLabels(txbkt, labels); err != nil { |
|
71 |
+ return Lease{}, err |
|
72 |
+ } |
|
73 |
+ } |
|
74 |
+ |
|
75 |
+ return Lease{ |
|
76 |
+ ID: lid, |
|
77 |
+ CreatedAt: t, |
|
78 |
+ Labels: labels, |
|
79 |
+ }, nil |
|
80 |
+} |
|
81 |
+ |
|
82 |
+// Delete delets the lease with the provided lease ID |
|
83 |
+func (lm *LeaseManager) Delete(ctx context.Context, lid string) error { |
|
84 |
+ namespace, err := namespaces.NamespaceRequired(ctx) |
|
85 |
+ if err != nil { |
|
86 |
+ return err |
|
87 |
+ } |
|
88 |
+ |
|
89 |
+ topbkt := getBucket(lm.tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases) |
|
90 |
+ if topbkt == nil { |
|
91 |
+ return nil |
|
92 |
+ } |
|
93 |
+ if err := topbkt.DeleteBucket([]byte(lid)); err != nil && err != bolt.ErrBucketNotFound { |
|
94 |
+ return err |
|
95 |
+ } |
|
96 |
+ return nil |
|
97 |
+} |
|
98 |
+ |
|
99 |
+// List lists all active leases |
|
100 |
+func (lm *LeaseManager) List(ctx context.Context, includeResources bool, filter ...string) ([]Lease, error) { |
|
101 |
+ namespace, err := namespaces.NamespaceRequired(ctx) |
|
102 |
+ if err != nil { |
|
103 |
+ return nil, err |
|
104 |
+ } |
|
105 |
+ |
|
106 |
+ var leases []Lease |
|
107 |
+ |
|
108 |
+ topbkt := getBucket(lm.tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases) |
|
109 |
+ if topbkt == nil { |
|
110 |
+ return leases, nil |
|
111 |
+ } |
|
112 |
+ |
|
113 |
+ if err := topbkt.ForEach(func(k, v []byte) error { |
|
114 |
+ if v != nil { |
|
115 |
+ return nil |
|
116 |
+ } |
|
117 |
+ txbkt := topbkt.Bucket(k) |
|
118 |
+ |
|
119 |
+ l := Lease{ |
|
120 |
+ ID: string(k), |
|
121 |
+ } |
|
122 |
+ |
|
123 |
+ if v := txbkt.Get(bucketKeyCreatedAt); v != nil { |
|
124 |
+ t := &l.CreatedAt |
|
125 |
+ if err := t.UnmarshalBinary(v); err != nil { |
|
126 |
+ return err |
|
127 |
+ } |
|
128 |
+ } |
|
129 |
+ |
|
130 |
+ labels, err := boltutil.ReadLabels(txbkt) |
|
131 |
+ if err != nil { |
|
132 |
+ return err |
|
133 |
+ } |
|
134 |
+ l.Labels = labels |
|
135 |
+ |
|
136 |
+ // TODO: Read Snapshots |
|
137 |
+ // TODO: Read Content |
|
138 |
+ |
|
139 |
+ leases = append(leases, l) |
|
140 |
+ |
|
141 |
+ return nil |
|
142 |
+ }); err != nil { |
|
143 |
+ return nil, err |
|
144 |
+ } |
|
145 |
+ |
|
146 |
+ return leases, nil |
|
147 |
+} |
|
148 |
+ |
|
149 |
+func addSnapshotLease(ctx context.Context, tx *bolt.Tx, snapshotter, key string) error { |
|
150 |
+ lid, ok := leases.Lease(ctx) |
|
151 |
+ if !ok { |
|
152 |
+ return nil |
|
153 |
+ } |
|
154 |
+ |
|
155 |
+ namespace, ok := namespaces.Namespace(ctx) |
|
156 |
+ if !ok { |
|
157 |
+ panic("namespace must already be required") |
|
158 |
+ } |
|
159 |
+ |
|
160 |
+ bkt := getBucket(tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases, []byte(lid)) |
|
161 |
+ if bkt == nil { |
|
162 |
+ return errors.Wrap(errdefs.ErrNotFound, "lease does not exist") |
|
163 |
+ } |
|
164 |
+ |
|
165 |
+ bkt, err := bkt.CreateBucketIfNotExists(bucketKeyObjectSnapshots) |
|
166 |
+ if err != nil { |
|
167 |
+ return err |
|
168 |
+ } |
|
169 |
+ |
|
170 |
+ bkt, err = bkt.CreateBucketIfNotExists([]byte(snapshotter)) |
|
171 |
+ if err != nil { |
|
172 |
+ return err |
|
173 |
+ } |
|
174 |
+ |
|
175 |
+ return bkt.Put([]byte(key), nil) |
|
176 |
+} |
|
177 |
+ |
|
178 |
+func addContentLease(ctx context.Context, tx *bolt.Tx, dgst digest.Digest) error { |
|
179 |
+ lid, ok := leases.Lease(ctx) |
|
180 |
+ if !ok { |
|
181 |
+ return nil |
|
182 |
+ } |
|
183 |
+ |
|
184 |
+ namespace, ok := namespaces.Namespace(ctx) |
|
185 |
+ if !ok { |
|
186 |
+ panic("namespace must already be required") |
|
187 |
+ } |
|
188 |
+ |
|
189 |
+ bkt := getBucket(tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases, []byte(lid)) |
|
190 |
+ if bkt == nil { |
|
191 |
+ return errors.Wrap(errdefs.ErrNotFound, "lease does not exist") |
|
192 |
+ } |
|
193 |
+ |
|
194 |
+ bkt, err := bkt.CreateBucketIfNotExists(bucketKeyObjectContent) |
|
195 |
+ if err != nil { |
|
196 |
+ return err |
|
197 |
+ } |
|
198 |
+ |
|
199 |
+ return bkt.Put([]byte(dgst.String()), nil) |
|
200 |
+} |
... | ... |
@@ -326,6 +326,10 @@ func (s *snapshotter) createSnapshot(ctx context.Context, key, parent string, re |
326 | 326 |
return err |
327 | 327 |
} |
328 | 328 |
|
329 |
+ if err := addSnapshotLease(ctx, tx, s.name, key); err != nil { |
|
330 |
+ return err |
|
331 |
+ } |
|
332 |
+ |
|
329 | 333 |
// TODO: Consider doing this outside of transaction to lessen |
330 | 334 |
// metadata lock time |
331 | 335 |
if readonly { |
332 | 336 |
deleted file mode 100644 |
... | ... |
@@ -1,83 +0,0 @@ |
1 |
-package mount |
|
2 |
- |
|
3 |
-// On Solaris we can't invoke the mount system call directly. First, |
|
4 |
-// the mount system call takes more than 6 arguments, and go doesn't |
|
5 |
-// support invoking system calls that take more than 6 arguments. Past |
|
6 |
-// that, the mount system call is a private interfaces. For example, |
|
7 |
-// the arguments and data structures passed to the kernel to create an |
|
8 |
-// nfs mount are private and can change at any time. The only public |
|
9 |
-// and stable interface for creating mounts on Solaris is the mount.8 |
|
10 |
-// command, so we'll invoke that here. |
|
11 |
- |
|
12 |
-import ( |
|
13 |
- "bytes" |
|
14 |
- "errors" |
|
15 |
- "fmt" |
|
16 |
- "os/exec" |
|
17 |
- "strings" |
|
18 |
- |
|
19 |
- "golang.org/x/sys/unix" |
|
20 |
-) |
|
21 |
- |
|
22 |
-const ( |
|
23 |
- mountCmd = "/usr/sbin/mount" |
|
24 |
-) |
|
25 |
- |
|
26 |
-func doMount(arg ...string) error { |
|
27 |
- cmd := exec.Command(mountCmd, arg...) |
|
28 |
- |
|
29 |
- /* Setup Stdin, Stdout, and Stderr */ |
|
30 |
- stderr := new(bytes.Buffer) |
|
31 |
- cmd.Stdin = nil |
|
32 |
- cmd.Stdout = nil |
|
33 |
- cmd.Stderr = stderr |
|
34 |
- |
|
35 |
- /* |
|
36 |
- * Run the command. If the command fails create a new error |
|
37 |
- * object to return that includes stderr output. |
|
38 |
- */ |
|
39 |
- err := cmd.Start() |
|
40 |
- if err != nil { |
|
41 |
- return err |
|
42 |
- } |
|
43 |
- err = cmd.Wait() |
|
44 |
- if err != nil { |
|
45 |
- return errors.New(fmt.Sprintf("%v: %s", err, stderr.String())) |
|
46 |
- } |
|
47 |
- return nil |
|
48 |
-} |
|
49 |
- |
|
50 |
-func (m *Mount) Mount(target string) error { |
|
51 |
- var err error |
|
52 |
- |
|
53 |
- if len(m.Options) == 0 { |
|
54 |
- err = doMount("-F", m.Type, m.Source, target) |
|
55 |
- } else { |
|
56 |
- err = doMount("-F", m.Type, "-o", strings.Join(m.Options, ","), |
|
57 |
- m.Source, target) |
|
58 |
- } |
|
59 |
- return err |
|
60 |
-} |
|
61 |
- |
|
62 |
-func Unmount(mount string, flags int) error { |
|
63 |
- return unix.Unmount(mount, flags) |
|
64 |
-} |
|
65 |
- |
|
66 |
-// UnmountAll repeatedly unmounts the given mount point until there |
|
67 |
-// are no mounts remaining (EINVAL is returned by mount), which is |
|
68 |
-// useful for undoing a stack of mounts on the same mount point. |
|
69 |
-func UnmountAll(mount string, flags int) error { |
|
70 |
- for { |
|
71 |
- if err := Unmount(mount, flags); err != nil { |
|
72 |
- // EINVAL is returned if the target is not a |
|
73 |
- // mount point, indicating that we are |
|
74 |
- // done. It can also indicate a few other |
|
75 |
- // things (such as invalid flags) which we |
|
76 |
- // unfortunately end up squelching here too. |
|
77 |
- if err == unix.EINVAL { |
|
78 |
- return nil |
|
79 |
- } |
|
80 |
- return err |
|
81 |
- } |
|
82 |
- } |
|
83 |
-} |
... | ... |
@@ -5,17 +5,21 @@ package mount |
5 | 5 |
import "github.com/pkg/errors" |
6 | 6 |
|
7 | 7 |
var ( |
8 |
+ // ErrNotImplementOnUnix is returned for methods that are not implemented |
|
8 | 9 |
ErrNotImplementOnUnix = errors.New("not implemented under unix") |
9 | 10 |
) |
10 | 11 |
|
12 |
+// Mount is not implemented on this platform |
|
11 | 13 |
func (m *Mount) Mount(target string) error { |
12 | 14 |
return ErrNotImplementOnUnix |
13 | 15 |
} |
14 | 16 |
|
17 |
+// Unmount is not implemented on this platform |
|
15 | 18 |
func Unmount(mount string, flags int) error { |
16 | 19 |
return ErrNotImplementOnUnix |
17 | 20 |
} |
18 | 21 |
|
22 |
+// UnmountAll is not implemented on this platform |
|
19 | 23 |
func UnmountAll(mount string, flags int) error { |
20 | 24 |
return ErrNotImplementOnUnix |
21 | 25 |
} |
... | ... |
@@ -3,17 +3,21 @@ package mount |
3 | 3 |
import "github.com/pkg/errors" |
4 | 4 |
|
5 | 5 |
var ( |
6 |
+ // ErrNotImplementOnWindows is returned when an action is not implemented for windows |
|
6 | 7 |
ErrNotImplementOnWindows = errors.New("not implemented under windows") |
7 | 8 |
) |
8 | 9 |
|
10 |
+// Mount to the provided target |
|
9 | 11 |
func (m *Mount) Mount(target string) error { |
10 | 12 |
return ErrNotImplementOnWindows |
11 | 13 |
} |
12 | 14 |
|
15 |
+// Unmount the mount at the provided path |
|
13 | 16 |
func Unmount(mount string, flags int) error { |
14 | 17 |
return ErrNotImplementOnWindows |
15 | 18 |
} |
16 | 19 |
|
20 |
+// UnmountAll mounts at the provided path |
|
17 | 21 |
func UnmountAll(mount string, flags int) error { |
18 | 22 |
return ErrNotImplementOnWindows |
19 | 23 |
} |
20 | 24 |
deleted file mode 100644 |
... | ... |
@@ -1,50 +0,0 @@ |
1 |
-// +build solaris,cgo |
|
2 |
- |
|
3 |
-package mount |
|
4 |
- |
|
5 |
-/* |
|
6 |
-#include <stdio.h> |
|
7 |
-#include <stdlib.h> |
|
8 |
-#include <sys/mnttab.h> |
|
9 |
-*/ |
|
10 |
-import "C" |
|
11 |
- |
|
12 |
-import ( |
|
13 |
- "fmt" |
|
14 |
- "unsafe" |
|
15 |
-) |
|
16 |
- |
|
17 |
-// Self retrieves a list of mounts for the current running process. |
|
18 |
-func Self() ([]Info, error) { |
|
19 |
- path := C.CString(C.MNTTAB) |
|
20 |
- defer C.free(unsafe.Pointer(path)) |
|
21 |
- mode := C.CString("r") |
|
22 |
- defer C.free(unsafe.Pointer(mode)) |
|
23 |
- |
|
24 |
- mnttab := C.fopen(path, mode) |
|
25 |
- if mnttab == nil { |
|
26 |
- return nil, fmt.Errorf("Failed to open %s", C.MNTTAB) |
|
27 |
- } |
|
28 |
- |
|
29 |
- var out []Info |
|
30 |
- var mp C.struct_mnttab |
|
31 |
- |
|
32 |
- ret := C.getmntent(mnttab, &mp) |
|
33 |
- for ret == 0 { |
|
34 |
- var mountinfo Info |
|
35 |
- mountinfo.Mountpoint = C.GoString(mp.mnt_mountp) |
|
36 |
- mountinfo.Source = C.GoString(mp.mnt_special) |
|
37 |
- mountinfo.FSType = C.GoString(mp.mnt_fstype) |
|
38 |
- mountinfo.Options = C.GoString(mp.mnt_mntopts) |
|
39 |
- out = append(out, mountinfo) |
|
40 |
- ret = C.getmntent(mnttab, &mp) |
|
41 |
- } |
|
42 |
- |
|
43 |
- C.fclose(mnttab) |
|
44 |
- return out, nil |
|
45 |
-} |
|
46 |
- |
|
47 |
-// PID collects the mounts for a specific process ID. |
|
48 |
-func PID(pid int) ([]Info, error) { |
|
49 |
- return nil, fmt.Errorf("mountinfo.PID is not implemented on solaris") |
|
50 |
-} |
... | ... |
@@ -5,7 +5,7 @@ import ( |
5 | 5 |
"path/filepath" |
6 | 6 |
|
7 | 7 |
"github.com/containerd/containerd/errdefs" |
8 |
- "github.com/containerd/containerd/events" |
|
8 |
+ "github.com/containerd/containerd/events/exchange" |
|
9 | 9 |
"github.com/containerd/containerd/log" |
10 | 10 |
ocispec "github.com/opencontainers/image-spec/specs-go/v1" |
11 | 11 |
"github.com/pkg/errors" |
... | ... |
@@ -18,15 +18,15 @@ type InitContext struct { |
18 | 18 |
State string |
19 | 19 |
Config interface{} |
20 | 20 |
Address string |
21 |
- Events *events.Exchange |
|
21 |
+ Events *exchange.Exchange |
|
22 | 22 |
|
23 | 23 |
Meta *Meta // plugins can fill in metadata at init. |
24 | 24 |
|
25 |
- plugins *PluginSet |
|
25 |
+ plugins *Set |
|
26 | 26 |
} |
27 | 27 |
|
28 | 28 |
// NewContext returns a new plugin InitContext |
29 |
-func NewContext(ctx context.Context, r *Registration, plugins *PluginSet, root, state string) *InitContext { |
|
29 |
+func NewContext(ctx context.Context, r *Registration, plugins *Set, root, state string) *InitContext { |
|
30 | 30 |
return &InitContext{ |
31 | 31 |
Context: log.WithModule(ctx, r.URI()), |
32 | 32 |
Root: filepath.Join(root, r.URI()), |
... | ... |
@@ -61,32 +61,37 @@ type Plugin struct { |
61 | 61 |
err error // will be set if there was an error initializing the plugin |
62 | 62 |
} |
63 | 63 |
|
64 |
+// Err returns the errors during initialization. |
|
65 |
+// returns nil if not error was encountered |
|
64 | 66 |
func (p *Plugin) Err() error { |
65 | 67 |
return p.err |
66 | 68 |
} |
67 | 69 |
|
70 |
+// Instance returns the instance and any initialization error of the plugin |
|
68 | 71 |
func (p *Plugin) Instance() (interface{}, error) { |
69 | 72 |
return p.instance, p.err |
70 | 73 |
} |
71 | 74 |
|
72 |
-// PluginSet defines a plugin collection, used with InitContext. |
|
75 |
+// Set defines a plugin collection, used with InitContext. |
|
73 | 76 |
// |
74 | 77 |
// This maintains ordering and unique indexing over the set. |
75 | 78 |
// |
76 | 79 |
// After iteratively instantiating plugins, this set should represent, the |
77 | 80 |
// ordered, initialization set of plugins for a containerd instance. |
78 |
-type PluginSet struct { |
|
81 |
+type Set struct { |
|
79 | 82 |
ordered []*Plugin // order of initialization |
80 | 83 |
byTypeAndID map[Type]map[string]*Plugin |
81 | 84 |
} |
82 | 85 |
|
83 |
-func NewPluginSet() *PluginSet { |
|
84 |
- return &PluginSet{ |
|
86 |
+// NewPluginSet returns an initialized plugin set |
|
87 |
+func NewPluginSet() *Set { |
|
88 |
+ return &Set{ |
|
85 | 89 |
byTypeAndID: make(map[Type]map[string]*Plugin), |
86 | 90 |
} |
87 | 91 |
} |
88 | 92 |
|
89 |
-func (ps *PluginSet) Add(p *Plugin) error { |
|
93 |
+// Add a plugin to the set |
|
94 |
+func (ps *Set) Add(p *Plugin) error { |
|
90 | 95 |
if byID, typeok := ps.byTypeAndID[p.Registration.Type]; !typeok { |
91 | 96 |
ps.byTypeAndID[p.Registration.Type] = map[string]*Plugin{ |
92 | 97 |
p.Registration.ID: p, |
... | ... |
@@ -102,13 +107,14 @@ func (ps *PluginSet) Add(p *Plugin) error { |
102 | 102 |
} |
103 | 103 |
|
104 | 104 |
// Get returns the first plugin by its type |
105 |
-func (ps *PluginSet) Get(t Type) (interface{}, error) { |
|
105 |
+func (ps *Set) Get(t Type) (interface{}, error) { |
|
106 | 106 |
for _, v := range ps.byTypeAndID[t] { |
107 | 107 |
return v.Instance() |
108 | 108 |
} |
109 | 109 |
return nil, errors.Wrapf(errdefs.ErrNotFound, "no plugins registered for %s", t) |
110 | 110 |
} |
111 | 111 |
|
112 |
+// GetAll plugins in the set |
|
112 | 113 |
func (i *InitContext) GetAll() []*Plugin { |
113 | 114 |
return i.plugins.ordered |
114 | 115 |
} |
... | ... |
@@ -58,9 +58,13 @@ const ( |
58 | 58 |
|
59 | 59 |
// Registration contains information for registering a plugin |
60 | 60 |
type Registration struct { |
61 |
- Type Type |
|
62 |
- ID string |
|
63 |
- Config interface{} |
|
61 |
+ // Type of the plugin |
|
62 |
+ Type Type |
|
63 |
+ // ID of the plugin |
|
64 |
+ ID string |
|
65 |
+ // Config specific to the plugin |
|
66 |
+ Config interface{} |
|
67 |
+ // Requires is a list of plugins that the registered plugin requires to be available |
|
64 | 68 |
Requires []Type |
65 | 69 |
|
66 | 70 |
// InitFn is called when initializing a plugin. The registration and |
... | ... |
@@ -69,6 +73,7 @@ type Registration struct { |
69 | 69 |
InitFn func(*InitContext) (interface{}, error) |
70 | 70 |
} |
71 | 71 |
|
72 |
+// Init the registered plugin |
|
72 | 73 |
func (r *Registration) Init(ic *InitContext) *Plugin { |
73 | 74 |
p, err := r.InitFn(ic) |
74 | 75 |
return &Plugin{ |
... | ... |
@@ -9,6 +9,7 @@ import ( |
9 | 9 |
"fmt" |
10 | 10 |
"io" |
11 | 11 |
"io/ioutil" |
12 |
+ "math/rand" |
|
12 | 13 |
"strings" |
13 | 14 |
"sync" |
14 | 15 |
"time" |
... | ... |
@@ -159,7 +160,6 @@ func (c *Converter) Convert(ctx context.Context) (ocispec.Descriptor, error) { |
159 | 159 |
} |
160 | 160 |
|
161 | 161 |
labels := map[string]string{} |
162 |
- labels["containerd.io/gc.root"] = time.Now().UTC().Format(time.RFC3339) |
|
163 | 162 |
labels["containerd.io/gc.ref.content.0"] = manifest.Config.Digest.String() |
164 | 163 |
for i, ch := range manifest.Layers { |
165 | 164 |
labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i+1)] = ch.Digest.String() |
... | ... |
@@ -175,12 +175,6 @@ func (c *Converter) Convert(ctx context.Context) (ocispec.Descriptor, error) { |
175 | 175 |
return ocispec.Descriptor{}, errors.Wrap(err, "failed to write config") |
176 | 176 |
} |
177 | 177 |
|
178 |
- for _, ch := range manifest.Layers { |
|
179 |
- if _, err := c.contentStore.Update(ctx, content.Info{Digest: ch.Digest}, "labels.containerd.io/gc.root"); err != nil { |
|
180 |
- return ocispec.Descriptor{}, errors.Wrap(err, "failed to remove blob root tag") |
|
181 |
- } |
|
182 |
- } |
|
183 |
- |
|
184 | 178 |
return desc, nil |
185 | 179 |
} |
186 | 180 |
|
... | ... |
@@ -215,13 +209,26 @@ func (c *Converter) fetchManifest(ctx context.Context, desc ocispec.Descriptor) |
215 | 215 |
func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) error { |
216 | 216 |
log.G(ctx).Debug("fetch blob") |
217 | 217 |
|
218 |
- ref := remotes.MakeRefKey(ctx, desc) |
|
219 |
- |
|
220 |
- calc := newBlobStateCalculator() |
|
218 |
+ var ( |
|
219 |
+ ref = remotes.MakeRefKey(ctx, desc) |
|
220 |
+ calc = newBlobStateCalculator() |
|
221 |
+ retry = 16 |
|
222 |
+ ) |
|
221 | 223 |
|
224 |
+tryit: |
|
222 | 225 |
cw, err := c.contentStore.Writer(ctx, ref, desc.Size, desc.Digest) |
223 | 226 |
if err != nil { |
224 |
- if !errdefs.IsAlreadyExists(err) { |
|
227 |
+ if errdefs.IsUnavailable(err) { |
|
228 |
+ select { |
|
229 |
+ case <-time.After(time.Millisecond * time.Duration(rand.Intn(retry))): |
|
230 |
+ if retry < 2048 { |
|
231 |
+ retry = retry << 1 |
|
232 |
+ } |
|
233 |
+ goto tryit |
|
234 |
+ case <-ctx.Done(): |
|
235 |
+ return err |
|
236 |
+ } |
|
237 |
+ } else if !errdefs.IsAlreadyExists(err) { |
|
225 | 238 |
return err |
226 | 239 |
} |
227 | 240 |
|
... | ... |
@@ -270,10 +277,7 @@ func (c *Converter) fetchBlob(ctx context.Context, desc ocispec.Descriptor) erro |
270 | 270 |
|
271 | 271 |
eg.Go(func() error { |
272 | 272 |
defer pw.Close() |
273 |
- opt := content.WithLabels(map[string]string{ |
|
274 |
- "containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339), |
|
275 |
- }) |
|
276 |
- return content.Copy(ctx, cw, io.TeeReader(rc, pw), desc.Size, desc.Digest, opt) |
|
273 |
+ return content.Copy(ctx, cw, io.TeeReader(rc, pw), desc.Size, desc.Digest) |
|
277 | 274 |
}) |
278 | 275 |
|
279 | 276 |
if err := eg.Wait(); err != nil { |
... | ... |
@@ -5,6 +5,7 @@ import ( |
5 | 5 |
"encoding/json" |
6 | 6 |
"fmt" |
7 | 7 |
"io" |
8 |
+ "math/rand" |
|
8 | 9 |
"time" |
9 | 10 |
|
10 | 11 |
"github.com/containerd/containerd/content" |
... | ... |
@@ -44,7 +45,7 @@ func MakeRefKey(ctx context.Context, desc ocispec.Descriptor) string { |
44 | 44 |
// FetchHandler returns a handler that will fetch all content into the ingester |
45 | 45 |
// discovered in a call to Dispatch. Use with ChildrenHandler to do a full |
46 | 46 |
// recursive fetch. |
47 |
-func FetchHandler(ingester content.Ingester, fetcher Fetcher, root ocispec.Descriptor) images.HandlerFunc { |
|
47 |
+func FetchHandler(ingester content.Ingester, fetcher Fetcher) images.HandlerFunc { |
|
48 | 48 |
return func(ctx context.Context, desc ocispec.Descriptor) (subdescs []ocispec.Descriptor, err error) { |
49 | 49 |
ctx = log.WithLogger(ctx, log.G(ctx).WithFields(logrus.Fields{ |
50 | 50 |
"digest": desc.Digest, |
... | ... |
@@ -56,13 +57,13 @@ func FetchHandler(ingester content.Ingester, fetcher Fetcher, root ocispec.Descr |
56 | 56 |
case images.MediaTypeDockerSchema1Manifest: |
57 | 57 |
return nil, fmt.Errorf("%v not supported", desc.MediaType) |
58 | 58 |
default: |
59 |
- err := fetch(ctx, ingester, fetcher, desc, desc.Digest == root.Digest) |
|
59 |
+ err := fetch(ctx, ingester, fetcher, desc) |
|
60 | 60 |
return nil, err |
61 | 61 |
} |
62 | 62 |
} |
63 | 63 |
} |
64 | 64 |
|
65 |
-func fetch(ctx context.Context, ingester content.Ingester, fetcher Fetcher, desc ocispec.Descriptor, root bool) error { |
|
65 |
+func fetch(ctx context.Context, ingester content.Ingester, fetcher Fetcher, desc ocispec.Descriptor) error { |
|
66 | 66 |
log.G(ctx).Debug("fetch") |
67 | 67 |
|
68 | 68 |
var ( |
... | ... |
@@ -84,7 +85,7 @@ func fetch(ctx context.Context, ingester content.Ingester, fetcher Fetcher, desc |
84 | 84 |
// of writer and abort if not updated recently. |
85 | 85 |
|
86 | 86 |
select { |
87 |
- case <-time.After(time.Millisecond * time.Duration(retry)): |
|
87 |
+ case <-time.After(time.Millisecond * time.Duration(rand.Intn(retry))): |
|
88 | 88 |
if retry < 2048 { |
89 | 89 |
retry = retry << 1 |
90 | 90 |
} |
... | ... |
@@ -104,13 +105,13 @@ func fetch(ctx context.Context, ingester content.Ingester, fetcher Fetcher, desc |
104 | 104 |
} |
105 | 105 |
defer rc.Close() |
106 | 106 |
|
107 |
- r, opts := commitOpts(desc, rc, root) |
|
107 |
+ r, opts := commitOpts(desc, rc) |
|
108 | 108 |
return content.Copy(ctx, cw, r, desc.Size, desc.Digest, opts...) |
109 | 109 |
} |
110 | 110 |
|
111 | 111 |
// commitOpts gets the appropriate content options to alter |
112 | 112 |
// the content info on commit based on media type. |
113 |
-func commitOpts(desc ocispec.Descriptor, r io.Reader, root bool) (io.Reader, []content.Opt) { |
|
113 |
+func commitOpts(desc ocispec.Descriptor, r io.Reader) (io.Reader, []content.Opt) { |
|
114 | 114 |
var childrenF func(r io.Reader) ([]ocispec.Descriptor, error) |
115 | 115 |
|
116 | 116 |
switch desc.MediaType { |
... | ... |
@@ -162,13 +163,10 @@ func commitOpts(desc ocispec.Descriptor, r io.Reader, root bool) (io.Reader, []c |
162 | 162 |
return errors.Wrap(err, "unable to get commit labels") |
163 | 163 |
} |
164 | 164 |
|
165 |
- if len(children) > 0 || root { |
|
165 |
+ if len(children) > 0 { |
|
166 | 166 |
if info.Labels == nil { |
167 | 167 |
info.Labels = map[string]string{} |
168 | 168 |
} |
169 |
- if root { |
|
170 |
- info.Labels["containerd.io/gc.root"] = time.Now().UTC().Format(time.RFC3339) |
|
171 |
- } |
|
172 | 169 |
for i, ch := range children { |
173 | 170 |
info.Labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i)] = ch.Digest.String() |
174 | 171 |
} |
... | ... |
@@ -7,6 +7,7 @@ import ( |
7 | 7 |
"github.com/gogo/protobuf/types" |
8 | 8 |
) |
9 | 9 |
|
10 |
+// TaskInfo provides task specific information |
|
10 | 11 |
type TaskInfo struct { |
11 | 12 |
ID string |
12 | 13 |
Runtime string |
... | ... |
@@ -14,6 +15,7 @@ type TaskInfo struct { |
14 | 14 |
Namespace string |
15 | 15 |
} |
16 | 16 |
|
17 |
+// Process is a runtime object for an executing process inside a container |
|
17 | 18 |
type Process interface { |
18 | 19 |
ID() string |
19 | 20 |
// State returns the process state |
... | ... |
@@ -30,6 +32,7 @@ type Process interface { |
30 | 30 |
Wait(context.Context) (*Exit, error) |
31 | 31 |
} |
32 | 32 |
|
33 |
+// Task is the runtime object for an executing container |
|
33 | 34 |
type Task interface { |
34 | 35 |
Process |
35 | 36 |
|
... | ... |
@@ -55,27 +58,37 @@ type Task interface { |
55 | 55 |
Metrics(context.Context) (interface{}, error) |
56 | 56 |
} |
57 | 57 |
|
58 |
+// ExecOpts provides additional options for additional processes running in a task |
|
58 | 59 |
type ExecOpts struct { |
59 | 60 |
Spec *types.Any |
60 | 61 |
IO IO |
61 | 62 |
} |
62 | 63 |
|
64 |
+// ConsoleSize of a pty or windows terminal |
|
63 | 65 |
type ConsoleSize struct { |
64 | 66 |
Width uint32 |
65 | 67 |
Height uint32 |
66 | 68 |
} |
67 | 69 |
|
70 |
+// Status is the runtime status of a task and/or process |
|
68 | 71 |
type Status int |
69 | 72 |
|
70 | 73 |
const ( |
74 |
+ // CreatedStatus when a process has been created |
|
71 | 75 |
CreatedStatus Status = iota + 1 |
76 |
+ // RunningStatus when a process is running |
|
72 | 77 |
RunningStatus |
78 |
+ // StoppedStatus when a process has stopped |
|
73 | 79 |
StoppedStatus |
80 |
+ // DeletedStatus when a process has been deleted |
|
74 | 81 |
DeletedStatus |
82 |
+ // PausedStatus when a process is paused |
|
75 | 83 |
PausedStatus |
84 |
+ // PausingStatus when a process is currently pausing |
|
76 | 85 |
PausingStatus |
77 | 86 |
) |
78 | 87 |
|
88 |
+// State information for a process |
|
79 | 89 |
type State struct { |
80 | 90 |
// Status is the current status of the container |
81 | 91 |
Status Status |
... | ... |
@@ -93,6 +106,7 @@ type State struct { |
93 | 93 |
Terminal bool |
94 | 94 |
} |
95 | 95 |
|
96 |
+// ProcessInfo holds platform specific process information |
|
96 | 97 |
type ProcessInfo struct { |
97 | 98 |
// Pid is the process ID |
98 | 99 |
Pid uint32 |
... | ... |
@@ -9,21 +9,26 @@ import ( |
9 | 9 |
) |
10 | 10 |
|
11 | 11 |
var ( |
12 |
- ErrTaskNotExists = errors.New("task does not exist") |
|
12 |
+ // ErrTaskNotExists is returned when a task does not exist |
|
13 |
+ ErrTaskNotExists = errors.New("task does not exist") |
|
14 |
+ // ErrTaskAlreadyExists is returned when a task already exists |
|
13 | 15 |
ErrTaskAlreadyExists = errors.New("task already exists") |
14 | 16 |
) |
15 | 17 |
|
18 |
+// NewTaskList returns a new TaskList |
|
16 | 19 |
func NewTaskList() *TaskList { |
17 | 20 |
return &TaskList{ |
18 | 21 |
tasks: make(map[string]map[string]Task), |
19 | 22 |
} |
20 | 23 |
} |
21 | 24 |
|
25 |
+// TaskList holds and provides locking around tasks |
|
22 | 26 |
type TaskList struct { |
23 | 27 |
mu sync.Mutex |
24 | 28 |
tasks map[string]map[string]Task |
25 | 29 |
} |
26 | 30 |
|
31 |
+// Get a task |
|
27 | 32 |
func (l *TaskList) Get(ctx context.Context, id string) (Task, error) { |
28 | 33 |
l.mu.Lock() |
29 | 34 |
defer l.mu.Unlock() |
... | ... |
@@ -42,6 +47,7 @@ func (l *TaskList) Get(ctx context.Context, id string) (Task, error) { |
42 | 42 |
return t, nil |
43 | 43 |
} |
44 | 44 |
|
45 |
+// GetAll tasks under a namespace |
|
45 | 46 |
func (l *TaskList) GetAll(ctx context.Context) ([]Task, error) { |
46 | 47 |
namespace, err := namespaces.NamespaceRequired(ctx) |
47 | 48 |
if err != nil { |
... | ... |
@@ -58,6 +64,7 @@ func (l *TaskList) GetAll(ctx context.Context) ([]Task, error) { |
58 | 58 |
return o, nil |
59 | 59 |
} |
60 | 60 |
|
61 |
+// Add a task |
|
61 | 62 |
func (l *TaskList) Add(ctx context.Context, t Task) error { |
62 | 63 |
namespace, err := namespaces.NamespaceRequired(ctx) |
63 | 64 |
if err != nil { |
... | ... |
@@ -66,6 +73,7 @@ func (l *TaskList) Add(ctx context.Context, t Task) error { |
66 | 66 |
return l.AddWithNamespace(namespace, t) |
67 | 67 |
} |
68 | 68 |
|
69 |
+// AddWithNamespace adds a task with the provided namespace |
|
69 | 70 |
func (l *TaskList) AddWithNamespace(namespace string, t Task) error { |
70 | 71 |
l.mu.Lock() |
71 | 72 |
defer l.mu.Unlock() |
... | ... |
@@ -81,6 +89,7 @@ func (l *TaskList) AddWithNamespace(namespace string, t Task) error { |
81 | 81 |
return nil |
82 | 82 |
} |
83 | 83 |
|
84 |
+// Delete a task |
|
84 | 85 |
func (l *TaskList) Delete(ctx context.Context, t Task) { |
85 | 86 |
l.mu.Lock() |
86 | 87 |
defer l.mu.Unlock() |
... | ... |
@@ -33,23 +33,27 @@ type Config struct { |
33 | 33 |
md toml.MetaData |
34 | 34 |
} |
35 | 35 |
|
36 |
+// GRPCConfig provides GRPC configuration for the socket |
|
36 | 37 |
type GRPCConfig struct { |
37 | 38 |
Address string `toml:"address"` |
38 |
- Uid int `toml:"uid"` |
|
39 |
- Gid int `toml:"gid"` |
|
39 |
+ UID int `toml:"uid"` |
|
40 |
+ GID int `toml:"gid"` |
|
40 | 41 |
} |
41 | 42 |
|
43 |
+// Debug provides debug configuration |
|
42 | 44 |
type Debug struct { |
43 | 45 |
Address string `toml:"address"` |
44 |
- Uid int `toml:"uid"` |
|
45 |
- Gid int `toml:"gid"` |
|
46 |
+ UID int `toml:"uid"` |
|
47 |
+ GID int `toml:"gid"` |
|
46 | 48 |
Level string `toml:"level"` |
47 | 49 |
} |
48 | 50 |
|
51 |
+// MetricsConfig provides metrics configuration |
|
49 | 52 |
type MetricsConfig struct { |
50 | 53 |
Address string `toml:"address"` |
51 | 54 |
} |
52 | 55 |
|
56 |
+// CgroupConfig provides cgroup configuration |
|
53 | 57 |
type CgroupConfig struct { |
54 | 58 |
Path string `toml:"path"` |
55 | 59 |
} |
... | ... |
@@ -16,13 +16,14 @@ import ( |
16 | 16 |
eventsapi "github.com/containerd/containerd/api/services/events/v1" |
17 | 17 |
images "github.com/containerd/containerd/api/services/images/v1" |
18 | 18 |
introspection "github.com/containerd/containerd/api/services/introspection/v1" |
19 |
+ leasesapi "github.com/containerd/containerd/api/services/leases/v1" |
|
19 | 20 |
namespaces "github.com/containerd/containerd/api/services/namespaces/v1" |
20 | 21 |
snapshotapi "github.com/containerd/containerd/api/services/snapshot/v1" |
21 | 22 |
tasks "github.com/containerd/containerd/api/services/tasks/v1" |
22 | 23 |
version "github.com/containerd/containerd/api/services/version/v1" |
23 | 24 |
"github.com/containerd/containerd/content" |
24 | 25 |
"github.com/containerd/containerd/content/local" |
25 |
- "github.com/containerd/containerd/events" |
|
26 |
+ "github.com/containerd/containerd/events/exchange" |
|
26 | 27 |
"github.com/containerd/containerd/log" |
27 | 28 |
"github.com/containerd/containerd/metadata" |
28 | 29 |
"github.com/containerd/containerd/plugin" |
... | ... |
@@ -65,7 +66,7 @@ func New(ctx context.Context, config *Config) (*Server, error) { |
65 | 65 |
services []plugin.Service |
66 | 66 |
s = &Server{ |
67 | 67 |
rpc: rpc, |
68 |
- events: events.NewExchange(), |
|
68 |
+ events: exchange.NewExchange(), |
|
69 | 69 |
} |
70 | 70 |
initialized = plugin.NewPluginSet() |
71 | 71 |
) |
... | ... |
@@ -122,7 +123,7 @@ func New(ctx context.Context, config *Config) (*Server, error) { |
122 | 122 |
// Server is the containerd main daemon |
123 | 123 |
type Server struct { |
124 | 124 |
rpc *grpc.Server |
125 |
- events *events.Exchange |
|
125 |
+ events *exchange.Exchange |
|
126 | 126 |
} |
127 | 127 |
|
128 | 128 |
// ServeGRPC provides the containerd grpc APIs on the provided listener |
... | ... |
@@ -255,6 +256,8 @@ func interceptor( |
255 | 255 |
ctx = log.WithModule(ctx, "events") |
256 | 256 |
case introspection.IntrospectionServer: |
257 | 257 |
ctx = log.WithModule(ctx, "introspection") |
258 |
+ case leasesapi.LeasesServer: |
|
259 |
+ ctx = log.WithModule(ctx, "leases") |
|
258 | 260 |
default: |
259 | 261 |
log.G(ctx).Warnf("unknown GRPC server type: %#v\n", info.Server) |
260 | 262 |
} |
... | ... |
@@ -10,19 +10,6 @@ import ( |
10 | 10 |
specs "github.com/opencontainers/runtime-spec/specs-go" |
11 | 11 |
) |
12 | 12 |
|
13 |
-const ( |
|
14 |
- // DefaultRootDir is the default location used by containerd to store |
|
15 |
- // persistent data |
|
16 |
- DefaultRootDir = "/var/lib/containerd" |
|
17 |
- // DefaultStateDir is the default location used by containerd to store |
|
18 |
- // transient data |
|
19 |
- DefaultStateDir = "/run/containerd" |
|
20 |
- // DefaultAddress is the default unix socket address |
|
21 |
- DefaultAddress = "/run/containerd/containerd.sock" |
|
22 |
- // DefaultDebugAddress is the default unix socket address for pprof data |
|
23 |
- DefaultDebugAddress = "/run/containerd/debug.sock" |
|
24 |
-) |
|
25 |
- |
|
26 | 13 |
// apply sets config settings on the server process |
27 | 14 |
func apply(ctx context.Context, config *Config) error { |
28 | 15 |
if config.Subreaper { |
... | ... |
@@ -21,7 +21,7 @@ import ( |
21 | 21 |
"google.golang.org/grpc/codes" |
22 | 22 |
) |
23 | 23 |
|
24 |
-type Service struct { |
|
24 |
+type service struct { |
|
25 | 25 |
store content.Store |
26 | 26 |
publisher events.Publisher |
27 | 27 |
} |
... | ... |
@@ -32,7 +32,7 @@ var bufPool = sync.Pool{ |
32 | 32 |
}, |
33 | 33 |
} |
34 | 34 |
|
35 |
-var _ api.ContentServer = &Service{} |
|
35 |
+var _ api.ContentServer = &service{} |
|
36 | 36 |
|
37 | 37 |
func init() { |
38 | 38 |
plugin.Register(&plugin.Registration{ |
... | ... |
@@ -53,19 +53,20 @@ func init() { |
53 | 53 |
}) |
54 | 54 |
} |
55 | 55 |
|
56 |
-func NewService(cs content.Store, publisher events.Publisher) (*Service, error) { |
|
57 |
- return &Service{ |
|
56 |
+// NewService returns the content GRPC server |
|
57 |
+func NewService(cs content.Store, publisher events.Publisher) (api.ContentServer, error) { |
|
58 |
+ return &service{ |
|
58 | 59 |
store: cs, |
59 | 60 |
publisher: publisher, |
60 | 61 |
}, nil |
61 | 62 |
} |
62 | 63 |
|
63 |
-func (s *Service) Register(server *grpc.Server) error { |
|
64 |
+func (s *service) Register(server *grpc.Server) error { |
|
64 | 65 |
api.RegisterContentServer(server, s) |
65 | 66 |
return nil |
66 | 67 |
} |
67 | 68 |
|
68 |
-func (s *Service) Info(ctx context.Context, req *api.InfoRequest) (*api.InfoResponse, error) { |
|
69 |
+func (s *service) Info(ctx context.Context, req *api.InfoRequest) (*api.InfoResponse, error) { |
|
69 | 70 |
if err := req.Digest.Validate(); err != nil { |
70 | 71 |
return nil, grpc.Errorf(codes.InvalidArgument, "%q failed validation", req.Digest) |
71 | 72 |
} |
... | ... |
@@ -80,7 +81,7 @@ func (s *Service) Info(ctx context.Context, req *api.InfoRequest) (*api.InfoResp |
80 | 80 |
}, nil |
81 | 81 |
} |
82 | 82 |
|
83 |
-func (s *Service) Update(ctx context.Context, req *api.UpdateRequest) (*api.UpdateResponse, error) { |
|
83 |
+func (s *service) Update(ctx context.Context, req *api.UpdateRequest) (*api.UpdateResponse, error) { |
|
84 | 84 |
if err := req.Info.Digest.Validate(); err != nil { |
85 | 85 |
return nil, grpc.Errorf(codes.InvalidArgument, "%q failed validation", req.Info.Digest) |
86 | 86 |
} |
... | ... |
@@ -95,7 +96,7 @@ func (s *Service) Update(ctx context.Context, req *api.UpdateRequest) (*api.Upda |
95 | 95 |
}, nil |
96 | 96 |
} |
97 | 97 |
|
98 |
-func (s *Service) List(req *api.ListContentRequest, session api.Content_ListServer) error { |
|
98 |
+func (s *service) List(req *api.ListContentRequest, session api.Content_ListServer) error { |
|
99 | 99 |
var ( |
100 | 100 |
buffer []api.Info |
101 | 101 |
sendBlock = func(block []api.Info) error { |
... | ... |
@@ -137,7 +138,7 @@ func (s *Service) List(req *api.ListContentRequest, session api.Content_ListServ |
137 | 137 |
return nil |
138 | 138 |
} |
139 | 139 |
|
140 |
-func (s *Service) Delete(ctx context.Context, req *api.DeleteContentRequest) (*empty.Empty, error) { |
|
140 |
+func (s *service) Delete(ctx context.Context, req *api.DeleteContentRequest) (*empty.Empty, error) { |
|
141 | 141 |
if err := req.Digest.Validate(); err != nil { |
142 | 142 |
return nil, grpc.Errorf(codes.InvalidArgument, err.Error()) |
143 | 143 |
} |
... | ... |
@@ -155,7 +156,7 @@ func (s *Service) Delete(ctx context.Context, req *api.DeleteContentRequest) (*e |
155 | 155 |
return &empty.Empty{}, nil |
156 | 156 |
} |
157 | 157 |
|
158 |
-func (s *Service) Read(req *api.ReadContentRequest, session api.Content_ReadServer) error { |
|
158 |
+func (s *service) Read(req *api.ReadContentRequest, session api.Content_ReadServer) error { |
|
159 | 159 |
if err := req.Digest.Validate(); err != nil { |
160 | 160 |
return grpc.Errorf(codes.InvalidArgument, "%v: %v", req.Digest, err) |
161 | 161 |
} |
... | ... |
@@ -223,7 +224,7 @@ func (rw *readResponseWriter) Write(p []byte) (n int, err error) { |
223 | 223 |
return len(p), nil |
224 | 224 |
} |
225 | 225 |
|
226 |
-func (s *Service) Status(ctx context.Context, req *api.StatusRequest) (*api.StatusResponse, error) { |
|
226 |
+func (s *service) Status(ctx context.Context, req *api.StatusRequest) (*api.StatusResponse, error) { |
|
227 | 227 |
status, err := s.store.Status(ctx, req.Ref) |
228 | 228 |
if err != nil { |
229 | 229 |
return nil, errdefs.ToGRPCf(err, "could not get status for ref %q", req.Ref) |
... | ... |
@@ -242,7 +243,7 @@ func (s *Service) Status(ctx context.Context, req *api.StatusRequest) (*api.Stat |
242 | 242 |
return &resp, nil |
243 | 243 |
} |
244 | 244 |
|
245 |
-func (s *Service) ListStatuses(ctx context.Context, req *api.ListStatusesRequest) (*api.ListStatusesResponse, error) { |
|
245 |
+func (s *service) ListStatuses(ctx context.Context, req *api.ListStatusesRequest) (*api.ListStatusesResponse, error) { |
|
246 | 246 |
statuses, err := s.store.ListStatuses(ctx, req.Filters...) |
247 | 247 |
if err != nil { |
248 | 248 |
return nil, errdefs.ToGRPC(err) |
... | ... |
@@ -263,7 +264,7 @@ func (s *Service) ListStatuses(ctx context.Context, req *api.ListStatusesRequest |
263 | 263 |
return &resp, nil |
264 | 264 |
} |
265 | 265 |
|
266 |
-func (s *Service) Write(session api.Content_WriteServer) (err error) { |
|
266 |
+func (s *service) Write(session api.Content_WriteServer) (err error) { |
|
267 | 267 |
var ( |
268 | 268 |
ctx = session.Context() |
269 | 269 |
msg api.WriteContentResponse |
... | ... |
@@ -283,7 +284,7 @@ func (s *Service) Write(session api.Content_WriteServer) (err error) { |
283 | 283 |
// identically across all GRPC methods. |
284 | 284 |
// |
285 | 285 |
// This is pretty noisy, so we can remove it but leave it for now. |
286 |
- log.G(ctx).WithError(err).Error("(*Service).Write failed") |
|
286 |
+ log.G(ctx).WithError(err).Error("(*service).Write failed") |
|
287 | 287 |
} |
288 | 288 |
|
289 | 289 |
return |
... | ... |
@@ -319,7 +320,7 @@ func (s *Service) Write(session api.Content_WriteServer) (err error) { |
319 | 319 |
|
320 | 320 |
ctx = log.WithLogger(ctx, log.G(ctx).WithFields(fields)) |
321 | 321 |
|
322 |
- log.G(ctx).Debug("(*Service).Write started") |
|
322 |
+ log.G(ctx).Debug("(*service).Write started") |
|
323 | 323 |
// this action locks the writer for the session. |
324 | 324 |
wr, err := s.store.Writer(ctx, ref, total, expected) |
325 | 325 |
if err != nil { |
... | ... |
@@ -444,7 +445,7 @@ func (s *Service) Write(session api.Content_WriteServer) (err error) { |
444 | 444 |
} |
445 | 445 |
} |
446 | 446 |
|
447 |
-func (s *Service) Abort(ctx context.Context, req *api.AbortRequest) (*empty.Empty, error) { |
|
447 |
+func (s *service) Abort(ctx context.Context, req *api.AbortRequest) (*empty.Empty, error) { |
|
448 | 448 |
if err := s.store.Abort(ctx, req.Ref); err != nil { |
449 | 449 |
return nil, errdefs.ToGRPC(err) |
450 | 450 |
} |
... | ... |
@@ -9,7 +9,7 @@ import ( |
9 | 9 |
"golang.org/x/net/context" |
10 | 10 |
) |
11 | 11 |
|
12 |
-// NewApplierFromClient returns a new Applier which communicates |
|
12 |
+// NewDiffServiceFromClient returns a new diff service which communicates |
|
13 | 13 |
// over a GRPC connection. |
14 | 14 |
func NewDiffServiceFromClient(client diffapi.DiffClient) diff.Differ { |
15 | 15 |
return &remote{ |
... | ... |
@@ -34,24 +34,25 @@ func init() { |
34 | 34 |
}) |
35 | 35 |
} |
36 | 36 |
|
37 |
-type Service struct { |
|
37 |
+type service struct { |
|
38 | 38 |
db *metadata.DB |
39 | 39 |
publisher events.Publisher |
40 | 40 |
} |
41 | 41 |
|
42 |
+// NewService returns the GRPC image server |
|
42 | 43 |
func NewService(db *metadata.DB, publisher events.Publisher) imagesapi.ImagesServer { |
43 |
- return &Service{ |
|
44 |
+ return &service{ |
|
44 | 45 |
db: db, |
45 | 46 |
publisher: publisher, |
46 | 47 |
} |
47 | 48 |
} |
48 | 49 |
|
49 |
-func (s *Service) Register(server *grpc.Server) error { |
|
50 |
+func (s *service) Register(server *grpc.Server) error { |
|
50 | 51 |
imagesapi.RegisterImagesServer(server, s) |
51 | 52 |
return nil |
52 | 53 |
} |
53 | 54 |
|
54 |
-func (s *Service) Get(ctx context.Context, req *imagesapi.GetImageRequest) (*imagesapi.GetImageResponse, error) { |
|
55 |
+func (s *service) Get(ctx context.Context, req *imagesapi.GetImageRequest) (*imagesapi.GetImageResponse, error) { |
|
55 | 56 |
var resp imagesapi.GetImageResponse |
56 | 57 |
|
57 | 58 |
return &resp, errdefs.ToGRPC(s.withStoreView(ctx, func(ctx context.Context, store images.Store) error { |
... | ... |
@@ -65,7 +66,7 @@ func (s *Service) Get(ctx context.Context, req *imagesapi.GetImageRequest) (*ima |
65 | 65 |
})) |
66 | 66 |
} |
67 | 67 |
|
68 |
-func (s *Service) List(ctx context.Context, req *imagesapi.ListImagesRequest) (*imagesapi.ListImagesResponse, error) { |
|
68 |
+func (s *service) List(ctx context.Context, req *imagesapi.ListImagesRequest) (*imagesapi.ListImagesResponse, error) { |
|
69 | 69 |
var resp imagesapi.ListImagesResponse |
70 | 70 |
|
71 | 71 |
return &resp, errdefs.ToGRPC(s.withStoreView(ctx, func(ctx context.Context, store images.Store) error { |
... | ... |
@@ -79,7 +80,7 @@ func (s *Service) List(ctx context.Context, req *imagesapi.ListImagesRequest) (* |
79 | 79 |
})) |
80 | 80 |
} |
81 | 81 |
|
82 |
-func (s *Service) Create(ctx context.Context, req *imagesapi.CreateImageRequest) (*imagesapi.CreateImageResponse, error) { |
|
82 |
+func (s *service) Create(ctx context.Context, req *imagesapi.CreateImageRequest) (*imagesapi.CreateImageResponse, error) { |
|
83 | 83 |
if req.Image.Name == "" { |
84 | 84 |
return nil, status.Errorf(codes.InvalidArgument, "Image.Name required") |
85 | 85 |
} |
... | ... |
@@ -111,7 +112,7 @@ func (s *Service) Create(ctx context.Context, req *imagesapi.CreateImageRequest) |
111 | 111 |
|
112 | 112 |
} |
113 | 113 |
|
114 |
-func (s *Service) Update(ctx context.Context, req *imagesapi.UpdateImageRequest) (*imagesapi.UpdateImageResponse, error) { |
|
114 |
+func (s *service) Update(ctx context.Context, req *imagesapi.UpdateImageRequest) (*imagesapi.UpdateImageResponse, error) { |
|
115 | 115 |
if req.Image.Name == "" { |
116 | 116 |
return nil, status.Errorf(codes.InvalidArgument, "Image.Name required") |
117 | 117 |
} |
... | ... |
@@ -149,7 +150,7 @@ func (s *Service) Update(ctx context.Context, req *imagesapi.UpdateImageRequest) |
149 | 149 |
return &resp, nil |
150 | 150 |
} |
151 | 151 |
|
152 |
-func (s *Service) Delete(ctx context.Context, req *imagesapi.DeleteImageRequest) (*empty.Empty, error) { |
|
152 |
+func (s *service) Delete(ctx context.Context, req *imagesapi.DeleteImageRequest) (*empty.Empty, error) { |
|
153 | 153 |
if err := s.withStoreUpdate(ctx, func(ctx context.Context, store images.Store) error { |
154 | 154 |
return errdefs.ToGRPC(store.Delete(ctx, req.Name)) |
155 | 155 |
}); err != nil { |
... | ... |
@@ -169,14 +170,14 @@ func (s *Service) Delete(ctx context.Context, req *imagesapi.DeleteImageRequest) |
169 | 169 |
return &empty.Empty{}, nil |
170 | 170 |
} |
171 | 171 |
|
172 |
-func (s *Service) withStore(ctx context.Context, fn func(ctx context.Context, store images.Store) error) func(tx *bolt.Tx) error { |
|
172 |
+func (s *service) withStore(ctx context.Context, fn func(ctx context.Context, store images.Store) error) func(tx *bolt.Tx) error { |
|
173 | 173 |
return func(tx *bolt.Tx) error { return fn(ctx, metadata.NewImageStore(tx)) } |
174 | 174 |
} |
175 | 175 |
|
176 |
-func (s *Service) withStoreView(ctx context.Context, fn func(ctx context.Context, store images.Store) error) error { |
|
176 |
+func (s *service) withStoreView(ctx context.Context, fn func(ctx context.Context, store images.Store) error) error { |
|
177 | 177 |
return s.db.View(s.withStore(ctx, fn)) |
178 | 178 |
} |
179 | 179 |
|
180 |
-func (s *Service) withStoreUpdate(ctx context.Context, fn func(ctx context.Context, store images.Store) error) error { |
|
180 |
+func (s *service) withStoreUpdate(ctx context.Context, fn func(ctx context.Context, store images.Store) error) error { |
|
181 | 181 |
return s.db.Update(s.withStore(ctx, fn)) |
182 | 182 |
} |
183 | 183 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,97 @@ |
0 |
+package namespaces |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "context" |
|
4 |
+ "strings" |
|
5 |
+ |
|
6 |
+ api "github.com/containerd/containerd/api/services/namespaces/v1" |
|
7 |
+ "github.com/containerd/containerd/errdefs" |
|
8 |
+ "github.com/containerd/containerd/namespaces" |
|
9 |
+ "github.com/gogo/protobuf/types" |
|
10 |
+) |
|
11 |
+ |
|
12 |
+// NewStoreFromClient returns a new namespace store |
|
13 |
+func NewStoreFromClient(client api.NamespacesClient) namespaces.Store { |
|
14 |
+ return &remote{client: client} |
|
15 |
+} |
|
16 |
+ |
|
17 |
+type remote struct { |
|
18 |
+ client api.NamespacesClient |
|
19 |
+} |
|
20 |
+ |
|
21 |
+func (r *remote) Create(ctx context.Context, namespace string, labels map[string]string) error { |
|
22 |
+ var req api.CreateNamespaceRequest |
|
23 |
+ |
|
24 |
+ req.Namespace = api.Namespace{ |
|
25 |
+ Name: namespace, |
|
26 |
+ Labels: labels, |
|
27 |
+ } |
|
28 |
+ |
|
29 |
+ _, err := r.client.Create(ctx, &req) |
|
30 |
+ if err != nil { |
|
31 |
+ return errdefs.FromGRPC(err) |
|
32 |
+ } |
|
33 |
+ |
|
34 |
+ return nil |
|
35 |
+} |
|
36 |
+ |
|
37 |
+func (r *remote) Labels(ctx context.Context, namespace string) (map[string]string, error) { |
|
38 |
+ var req api.GetNamespaceRequest |
|
39 |
+ req.Name = namespace |
|
40 |
+ |
|
41 |
+ resp, err := r.client.Get(ctx, &req) |
|
42 |
+ if err != nil { |
|
43 |
+ return nil, errdefs.FromGRPC(err) |
|
44 |
+ } |
|
45 |
+ |
|
46 |
+ return resp.Namespace.Labels, nil |
|
47 |
+} |
|
48 |
+ |
|
49 |
+func (r *remote) SetLabel(ctx context.Context, namespace, key, value string) error { |
|
50 |
+ var req api.UpdateNamespaceRequest |
|
51 |
+ |
|
52 |
+ req.Namespace = api.Namespace{ |
|
53 |
+ Name: namespace, |
|
54 |
+ Labels: map[string]string{key: value}, |
|
55 |
+ } |
|
56 |
+ |
|
57 |
+ req.UpdateMask = &types.FieldMask{ |
|
58 |
+ Paths: []string{strings.Join([]string{"labels", key}, ".")}, |
|
59 |
+ } |
|
60 |
+ |
|
61 |
+ _, err := r.client.Update(ctx, &req) |
|
62 |
+ if err != nil { |
|
63 |
+ return errdefs.FromGRPC(err) |
|
64 |
+ } |
|
65 |
+ |
|
66 |
+ return nil |
|
67 |
+} |
|
68 |
+ |
|
69 |
+func (r *remote) List(ctx context.Context) ([]string, error) { |
|
70 |
+ var req api.ListNamespacesRequest |
|
71 |
+ |
|
72 |
+ resp, err := r.client.List(ctx, &req) |
|
73 |
+ if err != nil { |
|
74 |
+ return nil, errdefs.FromGRPC(err) |
|
75 |
+ } |
|
76 |
+ |
|
77 |
+ var namespaces []string |
|
78 |
+ |
|
79 |
+ for _, ns := range resp.Namespaces { |
|
80 |
+ namespaces = append(namespaces, ns.Name) |
|
81 |
+ } |
|
82 |
+ |
|
83 |
+ return namespaces, nil |
|
84 |
+} |
|
85 |
+ |
|
86 |
+func (r *remote) Delete(ctx context.Context, namespace string) error { |
|
87 |
+ var req api.DeleteNamespaceRequest |
|
88 |
+ |
|
89 |
+ req.Name = namespace |
|
90 |
+ _, err := r.client.Delete(ctx, &req) |
|
91 |
+ if err != nil { |
|
92 |
+ return errdefs.FromGRPC(err) |
|
93 |
+ } |
|
94 |
+ |
|
95 |
+ return nil |
|
96 |
+} |
0 | 97 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,212 @@ |
0 |
+package namespaces |
|
1 |
+ |
|
2 |
+import ( |
|
3 |
+ "strings" |
|
4 |
+ |
|
5 |
+ "github.com/boltdb/bolt" |
|
6 |
+ eventsapi "github.com/containerd/containerd/api/services/events/v1" |
|
7 |
+ api "github.com/containerd/containerd/api/services/namespaces/v1" |
|
8 |
+ "github.com/containerd/containerd/errdefs" |
|
9 |
+ "github.com/containerd/containerd/events" |
|
10 |
+ "github.com/containerd/containerd/metadata" |
|
11 |
+ "github.com/containerd/containerd/namespaces" |
|
12 |
+ "github.com/containerd/containerd/plugin" |
|
13 |
+ "github.com/golang/protobuf/ptypes/empty" |
|
14 |
+ "golang.org/x/net/context" |
|
15 |
+ "google.golang.org/grpc" |
|
16 |
+ "google.golang.org/grpc/codes" |
|
17 |
+) |
|
18 |
+ |
|
19 |
+func init() { |
|
20 |
+ plugin.Register(&plugin.Registration{ |
|
21 |
+ Type: plugin.GRPCPlugin, |
|
22 |
+ ID: "namespaces", |
|
23 |
+ Requires: []plugin.Type{ |
|
24 |
+ plugin.MetadataPlugin, |
|
25 |
+ }, |
|
26 |
+ InitFn: func(ic *plugin.InitContext) (interface{}, error) { |
|
27 |
+ m, err := ic.Get(plugin.MetadataPlugin) |
|
28 |
+ if err != nil { |
|
29 |
+ return nil, err |
|
30 |
+ } |
|
31 |
+ return NewService(m.(*metadata.DB), ic.Events), nil |
|
32 |
+ }, |
|
33 |
+ }) |
|
34 |
+} |
|
35 |
+ |
|
36 |
+type service struct { |
|
37 |
+ db *metadata.DB |
|
38 |
+ publisher events.Publisher |
|
39 |
+} |
|
40 |
+ |
|
41 |
+var _ api.NamespacesServer = &service{} |
|
42 |
+ |
|
43 |
+// NewService returns the GRPC namespaces server |
|
44 |
+func NewService(db *metadata.DB, publisher events.Publisher) api.NamespacesServer { |
|
45 |
+ return &service{ |
|
46 |
+ db: db, |
|
47 |
+ publisher: publisher, |
|
48 |
+ } |
|
49 |
+} |
|
50 |
+ |
|
51 |
+func (s *service) Register(server *grpc.Server) error { |
|
52 |
+ api.RegisterNamespacesServer(server, s) |
|
53 |
+ return nil |
|
54 |
+} |
|
55 |
+ |
|
56 |
+func (s *service) Get(ctx context.Context, req *api.GetNamespaceRequest) (*api.GetNamespaceResponse, error) { |
|
57 |
+ var resp api.GetNamespaceResponse |
|
58 |
+ |
|
59 |
+ return &resp, s.withStoreView(ctx, func(ctx context.Context, store namespaces.Store) error { |
|
60 |
+ labels, err := store.Labels(ctx, req.Name) |
|
61 |
+ if err != nil { |
|
62 |
+ return errdefs.ToGRPC(err) |
|
63 |
+ } |
|
64 |
+ |
|
65 |
+ resp.Namespace = api.Namespace{ |
|
66 |
+ Name: req.Name, |
|
67 |
+ Labels: labels, |
|
68 |
+ } |
|
69 |
+ |
|
70 |
+ return nil |
|
71 |
+ }) |
|
72 |
+} |
|
73 |
+ |
|
74 |
+func (s *service) List(ctx context.Context, req *api.ListNamespacesRequest) (*api.ListNamespacesResponse, error) { |
|
75 |
+ var resp api.ListNamespacesResponse |
|
76 |
+ |
|
77 |
+ return &resp, s.withStoreView(ctx, func(ctx context.Context, store namespaces.Store) error { |
|
78 |
+ namespaces, err := store.List(ctx) |
|
79 |
+ if err != nil { |
|
80 |
+ return err |
|
81 |
+ } |
|
82 |
+ |
|
83 |
+ for _, namespace := range namespaces { |
|
84 |
+ labels, err := store.Labels(ctx, namespace) |
|
85 |
+ if err != nil { |
|
86 |
+ // In general, this should be unlikely, since we are holding a |
|
87 |
+ // transaction to service this request. |
|
88 |
+ return errdefs.ToGRPC(err) |
|
89 |
+ } |
|
90 |
+ |
|
91 |
+ resp.Namespaces = append(resp.Namespaces, api.Namespace{ |
|
92 |
+ Name: namespace, |
|
93 |
+ Labels: labels, |
|
94 |
+ }) |
|
95 |
+ } |
|
96 |
+ |
|
97 |
+ return nil |
|
98 |
+ }) |
|
99 |
+} |
|
100 |
+ |
|
101 |
+func (s *service) Create(ctx context.Context, req *api.CreateNamespaceRequest) (*api.CreateNamespaceResponse, error) { |
|
102 |
+ var resp api.CreateNamespaceResponse |
|
103 |
+ |
|
104 |
+ if err := s.withStoreUpdate(ctx, func(ctx context.Context, store namespaces.Store) error { |
|
105 |
+ if err := store.Create(ctx, req.Namespace.Name, req.Namespace.Labels); err != nil { |
|
106 |
+ return errdefs.ToGRPC(err) |
|
107 |
+ } |
|
108 |
+ |
|
109 |
+ for k, v := range req.Namespace.Labels { |
|
110 |
+ if err := store.SetLabel(ctx, req.Namespace.Name, k, v); err != nil { |
|
111 |
+ return err |
|
112 |
+ } |
|
113 |
+ } |
|
114 |
+ |
|
115 |
+ resp.Namespace = req.Namespace |
|
116 |
+ return nil |
|
117 |
+ }); err != nil { |
|
118 |
+ return &resp, err |
|
119 |
+ } |
|
120 |
+ |
|
121 |
+ if err := s.publisher.Publish(ctx, "/namespaces/create", &eventsapi.NamespaceCreate{ |
|
122 |
+ Name: req.Namespace.Name, |
|
123 |
+ Labels: req.Namespace.Labels, |
|
124 |
+ }); err != nil { |
|
125 |
+ return &resp, err |
|
126 |
+ } |
|
127 |
+ |
|
128 |
+ return &resp, nil |
|
129 |
+ |
|
130 |
+} |
|
131 |
+ |
|
132 |
+func (s *service) Update(ctx context.Context, req *api.UpdateNamespaceRequest) (*api.UpdateNamespaceResponse, error) { |
|
133 |
+ var resp api.UpdateNamespaceResponse |
|
134 |
+ if err := s.withStoreUpdate(ctx, func(ctx context.Context, store namespaces.Store) error { |
|
135 |
+ if req.UpdateMask != nil && len(req.UpdateMask.Paths) > 0 { |
|
136 |
+ for _, path := range req.UpdateMask.Paths { |
|
137 |
+ switch { |
|
138 |
+ case strings.HasPrefix(path, "labels."): |
|
139 |
+ key := strings.TrimPrefix(path, "labels.") |
|
140 |
+ if err := store.SetLabel(ctx, req.Namespace.Name, key, req.Namespace.Labels[key]); err != nil { |
|
141 |
+ return err |
|
142 |
+ } |
|
143 |
+ default: |
|
144 |
+ return grpc.Errorf(codes.InvalidArgument, "cannot update %q field", path) |
|
145 |
+ } |
|
146 |
+ } |
|
147 |
+ } else { |
|
148 |
+ // clear out the existing labels and then set them to the incoming request. |
|
149 |
+ // get current set of labels |
|
150 |
+ labels, err := store.Labels(ctx, req.Namespace.Name) |
|
151 |
+ if err != nil { |
|
152 |
+ return errdefs.ToGRPC(err) |
|
153 |
+ } |
|
154 |
+ |
|
155 |
+ for k := range labels { |
|
156 |
+ if err := store.SetLabel(ctx, req.Namespace.Name, k, ""); err != nil { |
|
157 |
+ return err |
|
158 |
+ } |
|
159 |
+ } |
|
160 |
+ |
|
161 |
+ for k, v := range req.Namespace.Labels { |
|
162 |
+ if err := store.SetLabel(ctx, req.Namespace.Name, k, v); err != nil { |
|
163 |
+ return err |
|
164 |
+ } |
|
165 |
+ |
|
166 |
+ } |
|
167 |
+ } |
|
168 |
+ |
|
169 |
+ return nil |
|
170 |
+ }); err != nil { |
|
171 |
+ return &resp, err |
|
172 |
+ } |
|
173 |
+ |
|
174 |
+ if err := s.publisher.Publish(ctx, "/namespaces/update", &eventsapi.NamespaceUpdate{ |
|
175 |
+ Name: req.Namespace.Name, |
|
176 |
+ Labels: req.Namespace.Labels, |
|
177 |
+ }); err != nil { |
|
178 |
+ return &resp, err |
|
179 |
+ } |
|
180 |
+ |
|
181 |
+ return &resp, nil |
|
182 |
+} |
|
183 |
+ |
|
184 |
+func (s *service) Delete(ctx context.Context, req *api.DeleteNamespaceRequest) (*empty.Empty, error) { |
|
185 |
+ if err := s.withStoreUpdate(ctx, func(ctx context.Context, store namespaces.Store) error { |
|
186 |
+ return errdefs.ToGRPC(store.Delete(ctx, req.Name)) |
|
187 |
+ }); err != nil { |
|
188 |
+ return &empty.Empty{}, err |
|
189 |
+ } |
|
190 |
+ // set the namespace in the context before publishing the event |
|
191 |
+ ctx = namespaces.WithNamespace(ctx, req.Name) |
|
192 |
+ if err := s.publisher.Publish(ctx, "/namespaces/delete", &eventsapi.NamespaceDelete{ |
|
193 |
+ Name: req.Name, |
|
194 |
+ }); err != nil { |
|
195 |
+ return &empty.Empty{}, err |
|
196 |
+ } |
|
197 |
+ |
|
198 |
+ return &empty.Empty{}, nil |
|
199 |
+} |
|
200 |
+ |
|
201 |
+func (s *service) withStore(ctx context.Context, fn func(ctx context.Context, store namespaces.Store) error) func(tx *bolt.Tx) error { |
|
202 |
+ return func(tx *bolt.Tx) error { return fn(ctx, metadata.NewNamespaceStore(tx)) } |
|
203 |
+} |
|
204 |
+ |
|
205 |
+func (s *service) withStoreView(ctx context.Context, fn func(ctx context.Context, store namespaces.Store) error) error { |
|
206 |
+ return s.db.View(s.withStore(ctx, fn)) |
|
207 |
+} |
|
208 |
+ |
|
209 |
+func (s *service) withStoreUpdate(ctx context.Context, fn func(ctx context.Context, store namespaces.Store) error) error { |
|
210 |
+ return s.db.Update(s.withStore(ctx, fn)) |
|
211 |
+} |
... | ... |
@@ -20,6 +20,9 @@ const ( |
20 | 20 |
KindCommitted |
21 | 21 |
) |
22 | 22 |
|
23 |
+// ParseKind parses the provided string into a Kind |
|
24 |
+// |
|
25 |
+// If the string cannot be parsed KindUnknown is returned |
|
23 | 26 |
func ParseKind(s string) Kind { |
24 | 27 |
s = strings.ToLower(s) |
25 | 28 |
switch s { |
... | ... |
@@ -34,6 +37,7 @@ func ParseKind(s string) Kind { |
34 | 34 |
return KindUnknown |
35 | 35 |
} |
36 | 36 |
|
37 |
+// String returns the string representation of the Kind |
|
37 | 38 |
func (k Kind) String() string { |
38 | 39 |
switch k { |
39 | 40 |
case KindView: |
... | ... |
@@ -47,10 +51,12 @@ func (k Kind) String() string { |
47 | 47 |
return "Unknown" |
48 | 48 |
} |
49 | 49 |
|
50 |
+// MarshalJSON the Kind to JSON |
|
50 | 51 |
func (k Kind) MarshalJSON() ([]byte, error) { |
51 | 52 |
return json.Marshal(k.String()) |
52 | 53 |
} |
53 | 54 |
|
55 |
+// UnmarshalJSON the Kind from JSON |
|
54 | 56 |
func (k *Kind) UnmarshalJSON(b []byte) error { |
55 | 57 |
var s string |
56 | 58 |
if err := json.Unmarshal(b, &s); err != nil { |
... | ... |
@@ -81,6 +87,7 @@ type Usage struct { |
81 | 81 |
Size int64 // provides usage, in bytes, of snapshot |
82 | 82 |
} |
83 | 83 |
|
84 |
+// Add the provided usage to the current usage |
|
84 | 85 |
func (u *Usage) Add(other Usage) { |
85 | 86 |
u.Size += other.Size |
86 | 87 |
|
... | ... |
@@ -11,17 +11,16 @@ import ( |
11 | 11 |
"path/filepath" |
12 | 12 |
"strconv" |
13 | 13 |
"strings" |
14 |
- "time" |
|
15 | 14 |
|
16 | 15 |
"golang.org/x/sys/unix" |
17 | 16 |
|
18 | 17 |
"github.com/containerd/containerd/containers" |
19 | 18 |
"github.com/containerd/containerd/content" |
19 |
+ "github.com/containerd/containerd/errdefs" |
|
20 | 20 |
"github.com/containerd/containerd/fs" |
21 | 21 |
"github.com/containerd/containerd/images" |
22 | 22 |
"github.com/containerd/containerd/namespaces" |
23 | 23 |
"github.com/containerd/containerd/platforms" |
24 |
- "github.com/containerd/containerd/snapshot" |
|
25 | 24 |
"github.com/opencontainers/image-spec/identity" |
26 | 25 |
"github.com/opencontainers/image-spec/specs-go/v1" |
27 | 26 |
"github.com/opencontainers/runc/libcontainer/user" |
... | ... |
@@ -260,19 +259,17 @@ func withRemappedSnapshotBase(id string, i Image, uid, gid uint32, readonly bool |
260 | 260 |
snapshotter = client.SnapshotService(c.Snapshotter) |
261 | 261 |
parent = identity.ChainID(diffIDs).String() |
262 | 262 |
usernsID = fmt.Sprintf("%s-%d-%d", parent, uid, gid) |
263 |
- opt = snapshot.WithLabels(map[string]string{ |
|
264 |
- "containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339), |
|
265 |
- }) |
|
266 | 263 |
) |
267 | 264 |
if _, err := snapshotter.Stat(ctx, usernsID); err == nil { |
268 |
- if _, err := snapshotter.Prepare(ctx, id, usernsID, opt); err != nil { |
|
265 |
+ if _, err := snapshotter.Prepare(ctx, id, usernsID); err == nil { |
|
266 |
+ c.SnapshotKey = id |
|
267 |
+ c.Image = i.Name() |
|
268 |
+ return nil |
|
269 |
+ } else if !errdefs.IsNotFound(err) { |
|
269 | 270 |
return err |
270 | 271 |
} |
271 |
- c.SnapshotKey = id |
|
272 |
- c.Image = i.Name() |
|
273 |
- return nil |
|
274 | 272 |
} |
275 |
- mounts, err := snapshotter.Prepare(ctx, usernsID+"-remap", parent, opt) |
|
273 |
+ mounts, err := snapshotter.Prepare(ctx, usernsID+"-remap", parent) |
|
276 | 274 |
if err != nil { |
277 | 275 |
return err |
278 | 276 |
} |
... | ... |
@@ -280,13 +277,13 @@ func withRemappedSnapshotBase(id string, i Image, uid, gid uint32, readonly bool |
280 | 280 |
snapshotter.Remove(ctx, usernsID) |
281 | 281 |
return err |
282 | 282 |
} |
283 |
- if err := snapshotter.Commit(ctx, usernsID, usernsID+"-remap", opt); err != nil { |
|
283 |
+ if err := snapshotter.Commit(ctx, usernsID, usernsID+"-remap"); err != nil { |
|
284 | 284 |
return err |
285 | 285 |
} |
286 | 286 |
if readonly { |
287 |
- _, err = snapshotter.View(ctx, id, usernsID, opt) |
|
287 |
+ _, err = snapshotter.View(ctx, id, usernsID) |
|
288 | 288 |
} else { |
289 |
- _, err = snapshotter.Prepare(ctx, id, usernsID, opt) |
|
289 |
+ _, err = snapshotter.Prepare(ctx, id, usernsID) |
|
290 | 290 |
} |
291 | 291 |
if err != nil { |
292 | 292 |
return err |
... | ... |
@@ -15,6 +15,7 @@ import ( |
15 | 15 |
specs "github.com/opencontainers/runtime-spec/specs-go" |
16 | 16 |
) |
17 | 17 |
|
18 |
+// WithImageConfig configures the spec to from the configuration of an Image |
|
18 | 19 |
func WithImageConfig(i Image) SpecOpts { |
19 | 20 |
return func(ctx context.Context, client *Client, _ *containers.Container, s *specs.Spec) error { |
20 | 21 |
var ( |
... | ... |
@@ -51,6 +52,8 @@ func WithImageConfig(i Image) SpecOpts { |
51 | 51 |
} |
52 | 52 |
} |
53 | 53 |
|
54 |
+// WithTTY sets the information on the spec as well as the environment variables for |
|
55 |
+// using a TTY |
|
54 | 56 |
func WithTTY(width, height int) SpecOpts { |
55 | 57 |
return func(_ context.Context, _ *Client, _ *containers.Container, s *specs.Spec) error { |
56 | 58 |
s.Process.Terminal = true |
... | ... |
@@ -63,6 +66,7 @@ func WithTTY(width, height int) SpecOpts { |
63 | 63 |
} |
64 | 64 |
} |
65 | 65 |
|
66 |
+// WithResources sets the provided resources on the spec for task updates |
|
66 | 67 |
func WithResources(resources *specs.WindowsResources) UpdateTaskOpts { |
67 | 68 |
return func(ctx context.Context, client *Client, r *UpdateTaskInfo) error { |
68 | 69 |
r.Resources = resources |
6 | 9 |
deleted file mode 100644 |
... | ... |
@@ -1,19 +0,0 @@ |
1 |
-// +build solaris |
|
2 |
- |
|
3 |
-package sys |
|
4 |
- |
|
5 |
-import ( |
|
6 |
- "errors" |
|
7 |
-) |
|
8 |
- |
|
9 |
-//Solaris TODO |
|
10 |
- |
|
11 |
-// GetSubreaper returns the subreaper setting for the calling process |
|
12 |
-func GetSubreaper() (int, error) { |
|
13 |
- return 0, errors.New("osutils GetSubreaper not implemented on Solaris") |
|
14 |
-} |
|
15 |
- |
|
16 |
-// SetSubreaper sets the value i as the subreaper setting for the calling process |
|
17 |
-func SetSubreaper(i int) error { |
|
18 |
- return errors.New("osutils SetSubreaper not implemented on Solaris") |
|
19 |
-} |
... | ... |
@@ -6,14 +6,17 @@ import ( |
6 | 6 |
"syscall" |
7 | 7 |
) |
8 | 8 |
|
9 |
+// StatAtime returns the access time from a stat struct |
|
9 | 10 |
func StatAtime(st *syscall.Stat_t) syscall.Timespec { |
10 | 11 |
return st.Atimespec |
11 | 12 |
} |
12 | 13 |
|
14 |
+// StatCtime returns the created time from a stat struct |
|
13 | 15 |
func StatCtime(st *syscall.Stat_t) syscall.Timespec { |
14 | 16 |
return st.Ctimespec |
15 | 17 |
} |
16 | 18 |
|
19 |
+// StatMtime returns the modified time from a stat struct |
|
17 | 20 |
func StatMtime(st *syscall.Stat_t) syscall.Timespec { |
18 | 21 |
return st.Mtimespec |
19 | 22 |
} |
... | ... |
@@ -6,14 +6,17 @@ import ( |
6 | 6 |
"syscall" |
7 | 7 |
) |
8 | 8 |
|
9 |
+// StatAtime returns the Atim |
|
9 | 10 |
func StatAtime(st *syscall.Stat_t) syscall.Timespec { |
10 | 11 |
return st.Atim |
11 | 12 |
} |
12 | 13 |
|
14 |
+// StatCtime returns the Ctim |
|
13 | 15 |
func StatCtime(st *syscall.Stat_t) syscall.Timespec { |
14 | 16 |
return st.Ctim |
15 | 17 |
} |
16 | 18 |
|
19 |
+// StatMtime returns the Mtim |
|
17 | 20 |
func StatMtime(st *syscall.Stat_t) syscall.Timespec { |
18 | 21 |
return st.Mtim |
19 | 22 |
} |
... | ... |
@@ -18,7 +18,6 @@ import ( |
18 | 18 |
"github.com/containerd/containerd/diff" |
19 | 19 |
"github.com/containerd/containerd/errdefs" |
20 | 20 |
"github.com/containerd/containerd/images" |
21 |
- "github.com/containerd/containerd/log" |
|
22 | 21 |
"github.com/containerd/containerd/mount" |
23 | 22 |
"github.com/containerd/containerd/plugin" |
24 | 23 |
"github.com/containerd/containerd/rootfs" |
... | ... |
@@ -26,7 +25,6 @@ import ( |
26 | 26 |
google_protobuf "github.com/gogo/protobuf/types" |
27 | 27 |
digest "github.com/opencontainers/go-digest" |
28 | 28 |
"github.com/opencontainers/image-spec/specs-go/v1" |
29 |
- ocispec "github.com/opencontainers/image-spec/specs-go/v1" |
|
30 | 29 |
specs "github.com/opencontainers/runtime-spec/specs-go" |
31 | 30 |
"github.com/pkg/errors" |
32 | 31 |
) |
... | ... |
@@ -51,6 +49,7 @@ type Status struct { |
51 | 51 |
ExitTime time.Time |
52 | 52 |
} |
53 | 53 |
|
54 |
+// ProcessInfo provides platform specific process information |
|
54 | 55 |
type ProcessInfo struct { |
55 | 56 |
// Pid is the process ID |
56 | 57 |
Pid uint32 |
... | ... |
@@ -358,6 +357,12 @@ func (t *task) Resize(ctx context.Context, w, h uint32) error { |
358 | 358 |
} |
359 | 359 |
|
360 | 360 |
func (t *task) Checkpoint(ctx context.Context, opts ...CheckpointTaskOpts) (Image, error) { |
361 |
+ ctx, done, err := t.client.withLease(ctx) |
|
362 |
+ if err != nil { |
|
363 |
+ return nil, err |
|
364 |
+ } |
|
365 |
+ defer done() |
|
366 |
+ |
|
361 | 367 |
request := &tasks.CheckpointTaskRequest{ |
362 | 368 |
ContainerID: t.id, |
363 | 369 |
} |
... | ... |
@@ -391,15 +396,6 @@ func (t *task) Checkpoint(ctx context.Context, opts ...CheckpointTaskOpts) (Imag |
391 | 391 |
index := v1.Index{ |
392 | 392 |
Annotations: make(map[string]string), |
393 | 393 |
} |
394 |
- // make sure we clear the gc root labels reguardless of success |
|
395 |
- var clearRoots []ocispec.Descriptor |
|
396 |
- defer func() { |
|
397 |
- for _, r := range append(index.Manifests, clearRoots...) { |
|
398 |
- if err := clearRootGCLabel(ctx, t.client, r); err != nil { |
|
399 |
- log.G(ctx).WithError(err).WithField("dgst", r.Digest).Warnf("failed to remove root marker") |
|
400 |
- } |
|
401 |
- } |
|
402 |
- }() |
|
403 | 394 |
if err := t.checkpointTask(ctx, &index, request); err != nil { |
404 | 395 |
return nil, err |
405 | 396 |
} |
... | ... |
@@ -418,7 +414,6 @@ func (t *task) Checkpoint(ctx context.Context, opts ...CheckpointTaskOpts) (Imag |
418 | 418 |
if err != nil { |
419 | 419 |
return nil, err |
420 | 420 |
} |
421 |
- clearRoots = append(clearRoots, desc) |
|
422 | 421 |
im := images.Image{ |
423 | 422 |
Name: i.Name, |
424 | 423 |
Target: desc, |
... | ... |
@@ -534,9 +529,6 @@ func (t *task) checkpointTask(ctx context.Context, index *v1.Index, request *tas |
534 | 534 |
func (t *task) checkpointRWSnapshot(ctx context.Context, index *v1.Index, snapshotterName string, id string) error { |
535 | 535 |
opts := []diff.Opt{ |
536 | 536 |
diff.WithReference(fmt.Sprintf("checkpoint-rw-%s", id)), |
537 |
- diff.WithLabels(map[string]string{ |
|
538 |
- "containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339), |
|
539 |
- }), |
|
540 | 537 |
} |
541 | 538 |
rw, err := rootfs.Diff(ctx, id, t.client.SnapshotService(snapshotterName), t.client.DiffService(), opts...) |
542 | 539 |
if err != nil { |
... | ... |
@@ -563,9 +555,7 @@ func (t *task) checkpointImage(ctx context.Context, index *v1.Index, image strin |
563 | 563 |
} |
564 | 564 |
|
565 | 565 |
func (t *task) writeIndex(ctx context.Context, index *v1.Index) (d v1.Descriptor, err error) { |
566 |
- labels := map[string]string{ |
|
567 |
- "containerd.io/gc.root": time.Now().UTC().Format(time.RFC3339), |
|
568 |
- } |
|
566 |
+ labels := map[string]string{} |
|
569 | 567 |
for i, m := range index.Manifests { |
570 | 568 |
labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i)] = m.Digest.String() |
571 | 569 |
} |
... | ... |
@@ -595,9 +585,3 @@ func writeContent(ctx context.Context, store content.Store, mediaType, ref strin |
595 | 595 |
Size: size, |
596 | 596 |
}, nil |
597 | 597 |
} |
598 |
- |
|
599 |
-func clearRootGCLabel(ctx context.Context, client *Client, desc ocispec.Descriptor) error { |
|
600 |
- info := content.Info{Digest: desc.Digest} |
|
601 |
- _, err := client.ContentStore().Update(ctx, info, "labels.containerd.io/gc.root") |
|
602 |
- return err |
|
603 |
-} |
... | ... |
@@ -16,14 +16,14 @@ github.com/docker/go-units v0.3.1 |
16 | 16 |
github.com/gogo/protobuf d2e1ade2d719b78fe5b061b4c18a9f7111b5bdc8 |
17 | 17 |
github.com/golang/protobuf 5a0f697c9ed9d68fef0116532c6e05cfeae00e55 |
18 | 18 |
github.com/opencontainers/runtime-spec v1.0.0 |
19 |
-github.com/opencontainers/runc 0351df1c5a66838d0c392b4ac4cf9450de844e2d |
|
19 |
+github.com/opencontainers/runc 74a17296470088de3805e138d3d87c62e613dfc4 |
|
20 | 20 |
github.com/sirupsen/logrus v1.0.0 |
21 | 21 |
github.com/containerd/btrfs cc52c4dea2ce11a44e6639e561bb5c2af9ada9e3 |
22 | 22 |
github.com/stretchr/testify v1.1.4 |
23 | 23 |
github.com/davecgh/go-spew v1.1.0 |
24 | 24 |
github.com/pmezard/go-difflib v1.0.0 |
25 | 25 |
github.com/containerd/fifo fbfb6a11ec671efbe94ad1c12c2e98773f19e1e6 |
26 |
-github.com/urfave/cli 8ba6f23b6e36d03666a14bd9421f5e3efcb59aca |
|
26 |
+github.com/urfave/cli 7bc6a0acffa589f415f88aca16cc1de5ffd66f9c |
|
27 | 27 |
golang.org/x/net 7dcfb8076726a3fdd9353b6b8a1f1b6be6811bd6 |
28 | 28 |
google.golang.org/grpc v1.3.0 |
29 | 29 |
github.com/pkg/errors v0.8.0 |