github.com/containerd/Containerd@v1.4.13/rootfs/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 rootfs
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  
    23  	"github.com/containerd/containerd/diff"
    24  	"github.com/containerd/containerd/mount"
    25  	"github.com/containerd/containerd/namespaces"
    26  	"github.com/containerd/containerd/snapshots"
    27  	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
    28  )
    29  
    30  // CreateDiff creates a layer diff for the given snapshot identifier from the
    31  // parent of the snapshot. A content ref is provided to track the progress of
    32  // the content creation and the provided snapshotter and mount differ are used
    33  // for calculating the diff. The descriptor for the layer diff is returned.
    34  func CreateDiff(ctx context.Context, snapshotID string, sn snapshots.Snapshotter, d diff.Comparer, opts ...diff.Opt) (ocispec.Descriptor, error) {
    35  	// dctx is used to handle cleanup things just in case the param ctx
    36  	// has been canceled, which causes that the defer cleanup fails.
    37  	dctx := context.Background()
    38  	if ns, ok := namespaces.Namespace(ctx); ok {
    39  		dctx = namespaces.WithNamespace(dctx, ns)
    40  	}
    41  
    42  	info, err := sn.Stat(ctx, snapshotID)
    43  	if err != nil {
    44  		return ocispec.Descriptor{}, err
    45  	}
    46  
    47  	lowerKey := fmt.Sprintf("%s-parent-view", info.Parent)
    48  	lower, err := sn.View(ctx, lowerKey, info.Parent)
    49  	if err != nil {
    50  		return ocispec.Descriptor{}, err
    51  	}
    52  	defer sn.Remove(dctx, lowerKey)
    53  
    54  	var upper []mount.Mount
    55  	if info.Kind == snapshots.KindActive {
    56  		upper, err = sn.Mounts(ctx, snapshotID)
    57  		if err != nil {
    58  			return ocispec.Descriptor{}, err
    59  		}
    60  	} else {
    61  		upperKey := fmt.Sprintf("%s-view", snapshotID)
    62  		upper, err = sn.View(ctx, upperKey, snapshotID)
    63  		if err != nil {
    64  			return ocispec.Descriptor{}, err
    65  		}
    66  		defer sn.Remove(dctx, upperKey)
    67  	}
    68  
    69  	return d.Compare(ctx, lower, upper, opts...)
    70  }