github.com/lalkh/containerd@v1.4.3/diff.go (about)

     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 containerd
    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  	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
    28  )
    29  
    30  // DiffService handles the computation and application of diffs
    31  type DiffService interface {
    32  	diff.Comparer
    33  	diff.Applier
    34  }
    35  
    36  // NewDiffServiceFromClient returns a new diff service which communicates
    37  // over a GRPC connection.
    38  func NewDiffServiceFromClient(client diffapi.DiffClient) DiffService {
    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  	req := &diffapi.ApplyRequest{
    56  		Diff:     fromDescriptor(desc),
    57  		Mounts:   fromMounts(mounts),
    58  		Payloads: config.ProcessorPayloads,
    59  	}
    60  	resp, err := r.client.Apply(ctx, req)
    61  	if err != nil {
    62  		return ocispec.Descriptor{}, errdefs.FromGRPC(err)
    63  	}
    64  	return toDescriptor(resp.Applied), nil
    65  }
    66  
    67  func (r *diffRemote) Compare(ctx context.Context, a, b []mount.Mount, opts ...diff.Opt) (ocispec.Descriptor, error) {
    68  	var config diff.Config
    69  	for _, opt := range opts {
    70  		if err := opt(&config); err != nil {
    71  			return ocispec.Descriptor{}, err
    72  		}
    73  	}
    74  	req := &diffapi.DiffRequest{
    75  		Left:      fromMounts(a),
    76  		Right:     fromMounts(b),
    77  		MediaType: config.MediaType,
    78  		Ref:       config.Reference,
    79  		Labels:    config.Labels,
    80  	}
    81  	resp, err := r.client.Diff(ctx, req)
    82  	if err != nil {
    83  		return ocispec.Descriptor{}, errdefs.FromGRPC(err)
    84  	}
    85  	return toDescriptor(resp.Diff), nil
    86  }
    87  
    88  func toDescriptor(d *types.Descriptor) ocispec.Descriptor {
    89  	return ocispec.Descriptor{
    90  		MediaType:   d.MediaType,
    91  		Digest:      d.Digest,
    92  		Size:        d.Size_,
    93  		Annotations: d.Annotations,
    94  	}
    95  }
    96  
    97  func fromDescriptor(d ocispec.Descriptor) *types.Descriptor {
    98  	return &types.Descriptor{
    99  		MediaType:   d.MediaType,
   100  		Digest:      d.Digest,
   101  		Size_:       d.Size,
   102  		Annotations: d.Annotations,
   103  	}
   104  }
   105  
   106  func fromMounts(mounts []mount.Mount) []*types.Mount {
   107  	apiMounts := make([]*types.Mount, len(mounts))
   108  	for i, m := range mounts {
   109  		apiMounts[i] = &types.Mount{
   110  			Type:    m.Type,
   111  			Source:  m.Source,
   112  			Options: m.Options,
   113  		}
   114  	}
   115  	return apiMounts
   116  }