Skip to content

Commit 661e505

Browse files
dmcgowandcantah
authored andcommitted
Add proxy differ
Signed-off-by: Derek McGowan <[email protected]> (cherry picked from commit 3784c1c) Signed-off-by: Danny Canter <[email protected]>
1 parent 2ecde44 commit 661e505

3 files changed

Lines changed: 140 additions & 106 deletions

File tree

diff.go

Lines changed: 2 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,9 @@
1717
package containerd
1818

1919
import (
20-
"context"
21-
2220
diffapi "github.com/containerd/containerd/api/services/diff/v1"
23-
"github.com/containerd/containerd/api/types"
2421
"github.com/containerd/containerd/diff"
25-
"github.com/containerd/containerd/errdefs"
26-
"github.com/containerd/containerd/mount"
27-
"github.com/containerd/containerd/pkg/epoch"
28-
"github.com/containerd/containerd/protobuf"
29-
ptypes "github.com/containerd/containerd/protobuf/types"
30-
"github.com/opencontainers/go-digest"
31-
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
32-
"google.golang.org/protobuf/types/known/timestamppb"
22+
"github.com/containerd/containerd/diff/proxy"
3323
)
3424

3525
// DiffService handles the computation and application of diffs
@@ -41,99 +31,5 @@ type DiffService interface {
4131
// NewDiffServiceFromClient returns a new diff service which communicates
4232
// over a GRPC connection.
4333
func NewDiffServiceFromClient(client diffapi.DiffClient) DiffService {
44-
return &diffRemote{
45-
client: client,
46-
}
47-
}
48-
49-
type diffRemote struct {
50-
client diffapi.DiffClient
51-
}
52-
53-
func (r *diffRemote) Apply(ctx context.Context, desc ocispec.Descriptor, mounts []mount.Mount, opts ...diff.ApplyOpt) (ocispec.Descriptor, error) {
54-
var config diff.ApplyConfig
55-
for _, opt := range opts {
56-
if err := opt(ctx, desc, &config); err != nil {
57-
return ocispec.Descriptor{}, err
58-
}
59-
}
60-
61-
payloads := make(map[string]*ptypes.Any)
62-
for k, v := range config.ProcessorPayloads {
63-
payloads[k] = protobuf.FromAny(v)
64-
}
65-
66-
req := &diffapi.ApplyRequest{
67-
Diff: fromDescriptor(desc),
68-
Mounts: fromMounts(mounts),
69-
Payloads: payloads,
70-
}
71-
resp, err := r.client.Apply(ctx, req)
72-
if err != nil {
73-
return ocispec.Descriptor{}, errdefs.FromGRPC(err)
74-
}
75-
return toDescriptor(resp.Applied), nil
76-
}
77-
78-
func (r *diffRemote) Compare(ctx context.Context, a, b []mount.Mount, opts ...diff.Opt) (ocispec.Descriptor, error) {
79-
var config diff.Config
80-
for _, opt := range opts {
81-
if err := opt(&config); err != nil {
82-
return ocispec.Descriptor{}, err
83-
}
84-
}
85-
if tm := epoch.FromContext(ctx); tm != nil && config.SourceDateEpoch == nil {
86-
config.SourceDateEpoch = tm
87-
}
88-
var sourceDateEpoch *timestamppb.Timestamp
89-
if config.SourceDateEpoch != nil {
90-
sourceDateEpoch = timestamppb.New(*config.SourceDateEpoch)
91-
}
92-
req := &diffapi.DiffRequest{
93-
Left: fromMounts(a),
94-
Right: fromMounts(b),
95-
MediaType: config.MediaType,
96-
Ref: config.Reference,
97-
Labels: config.Labels,
98-
SourceDateEpoch: sourceDateEpoch,
99-
}
100-
resp, err := r.client.Diff(ctx, req)
101-
if err != nil {
102-
return ocispec.Descriptor{}, errdefs.FromGRPC(err)
103-
}
104-
return toDescriptor(resp.Diff), nil
105-
}
106-
107-
func toDescriptor(d *types.Descriptor) ocispec.Descriptor {
108-
if d == nil {
109-
return ocispec.Descriptor{}
110-
}
111-
return ocispec.Descriptor{
112-
MediaType: d.MediaType,
113-
Digest: digest.Digest(d.Digest),
114-
Size: d.Size,
115-
Annotations: d.Annotations,
116-
}
117-
}
118-
119-
func fromDescriptor(d ocispec.Descriptor) *types.Descriptor {
120-
return &types.Descriptor{
121-
MediaType: d.MediaType,
122-
Digest: d.Digest.String(),
123-
Size: d.Size,
124-
Annotations: d.Annotations,
125-
}
126-
}
127-
128-
func fromMounts(mounts []mount.Mount) []*types.Mount {
129-
apiMounts := make([]*types.Mount, len(mounts))
130-
for i, m := range mounts {
131-
apiMounts[i] = &types.Mount{
132-
Type: m.Type,
133-
Source: m.Source,
134-
Target: m.Target,
135-
Options: m.Options,
136-
}
137-
}
138-
return apiMounts
34+
return proxy.NewDiffApplier(client).(DiffService)
13935
}

diff/proxy/differ.go

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package proxy
18+
19+
import (
20+
"context"
21+
22+
diffapi "github.com/containerd/containerd/api/services/diff/v1"
23+
"github.com/containerd/containerd/api/types"
24+
"github.com/containerd/containerd/diff"
25+
"github.com/containerd/containerd/errdefs"
26+
"github.com/containerd/containerd/mount"
27+
"github.com/containerd/containerd/pkg/epoch"
28+
"github.com/containerd/containerd/protobuf"
29+
ptypes "github.com/containerd/containerd/protobuf/types"
30+
"github.com/opencontainers/go-digest"
31+
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
32+
33+
"google.golang.org/protobuf/types/known/timestamppb"
34+
)
35+
36+
// NewDiffApplier returns a new comparer and applier which communicates
37+
// over a GRPC connection.
38+
func NewDiffApplier(client diffapi.DiffClient) interface{} {
39+
return &diffRemote{
40+
client: client,
41+
}
42+
}
43+
44+
type diffRemote struct {
45+
client diffapi.DiffClient
46+
}
47+
48+
func (r *diffRemote) Apply(ctx context.Context, desc ocispec.Descriptor, mounts []mount.Mount, opts ...diff.ApplyOpt) (ocispec.Descriptor, error) {
49+
var config diff.ApplyConfig
50+
for _, opt := range opts {
51+
if err := opt(ctx, desc, &config); err != nil {
52+
return ocispec.Descriptor{}, err
53+
}
54+
}
55+
56+
payloads := make(map[string]*ptypes.Any)
57+
for k, v := range config.ProcessorPayloads {
58+
payloads[k] = protobuf.FromAny(v)
59+
}
60+
61+
req := &diffapi.ApplyRequest{
62+
Diff: fromDescriptor(desc),
63+
Mounts: fromMounts(mounts),
64+
Payloads: payloads,
65+
}
66+
resp, err := r.client.Apply(ctx, req)
67+
if err != nil {
68+
return ocispec.Descriptor{}, errdefs.FromGRPC(err)
69+
}
70+
return toDescriptor(resp.Applied), nil
71+
}
72+
73+
func (r *diffRemote) Compare(ctx context.Context, a, b []mount.Mount, opts ...diff.Opt) (ocispec.Descriptor, error) {
74+
var config diff.Config
75+
for _, opt := range opts {
76+
if err := opt(&config); err != nil {
77+
return ocispec.Descriptor{}, err
78+
}
79+
}
80+
if tm := epoch.FromContext(ctx); tm != nil && config.SourceDateEpoch == nil {
81+
config.SourceDateEpoch = tm
82+
}
83+
var sourceDateEpoch *timestamppb.Timestamp
84+
if config.SourceDateEpoch != nil {
85+
sourceDateEpoch = timestamppb.New(*config.SourceDateEpoch)
86+
}
87+
req := &diffapi.DiffRequest{
88+
Left: fromMounts(a),
89+
Right: fromMounts(b),
90+
MediaType: config.MediaType,
91+
Ref: config.Reference,
92+
Labels: config.Labels,
93+
SourceDateEpoch: sourceDateEpoch,
94+
}
95+
resp, err := r.client.Diff(ctx, req)
96+
if err != nil {
97+
return ocispec.Descriptor{}, errdefs.FromGRPC(err)
98+
}
99+
return toDescriptor(resp.Diff), nil
100+
}
101+
102+
func toDescriptor(d *types.Descriptor) ocispec.Descriptor {
103+
return ocispec.Descriptor{
104+
MediaType: d.MediaType,
105+
Digest: digest.Digest(d.Digest),
106+
Size: d.Size,
107+
Annotations: d.Annotations,
108+
}
109+
}
110+
111+
func fromDescriptor(d ocispec.Descriptor) *types.Descriptor {
112+
return &types.Descriptor{
113+
MediaType: d.MediaType,
114+
Digest: d.Digest.String(),
115+
Size: d.Size,
116+
Annotations: d.Annotations,
117+
}
118+
}
119+
120+
func fromMounts(mounts []mount.Mount) []*types.Mount {
121+
apiMounts := make([]*types.Mount, len(mounts))
122+
for i, m := range mounts {
123+
apiMounts[i] = &types.Mount{
124+
Type: m.Type,
125+
Source: m.Source,
126+
Target: m.Target,
127+
Options: m.Options,
128+
}
129+
}
130+
return apiMounts
131+
}

services/server/server.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,13 @@ import (
3434
"time"
3535

3636
csapi "github.com/containerd/containerd/api/services/content/v1"
37+
diffapi "github.com/containerd/containerd/api/services/diff/v1"
3738
ssapi "github.com/containerd/containerd/api/services/snapshots/v1"
3839
"github.com/containerd/containerd/content/local"
3940
csproxy "github.com/containerd/containerd/content/proxy"
4041
"github.com/containerd/containerd/defaults"
4142
"github.com/containerd/containerd/diff"
43+
diffproxy "github.com/containerd/containerd/diff/proxy"
4244
"github.com/containerd/containerd/events/exchange"
4345
"github.com/containerd/containerd/log"
4446
"github.com/containerd/containerd/pkg/dialer"
@@ -426,6 +428,11 @@ func LoadPlugins(ctx context.Context, config *srvconfig.Config) ([]*plugin.Regis
426428
f = func(conn *grpc.ClientConn) interface{} {
427429
return csproxy.NewContentStore(csapi.NewContentClient(conn))
428430
}
431+
case string(plugin.DiffPlugin), "diff":
432+
t = plugin.DiffPlugin
433+
f = func(conn *grpc.ClientConn) interface{} {
434+
return diffproxy.NewDiffApplier(diffapi.NewDiffClient(conn))
435+
}
429436
default:
430437
log.G(ctx).WithField("type", pp.Type).Warn("unknown proxy plugin type")
431438
}

0 commit comments

Comments
 (0)