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

     1  // +build linux
     2  
     3  /*
     4     Copyright The containerd Authors.
     5  
     6     Licensed under the Apache License, Version 2.0 (the "License");
     7     you may not use this file except in compliance with the License.
     8     You may obtain a copy of the License at
     9  
    10         http://www.apache.org/licenses/LICENSE-2.0
    11  
    12     Unless required by applicable law or agreed to in writing, software
    13     distributed under the License is distributed on an "AS IS" BASIS,
    14     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15     See the License for the specific language governing permissions and
    16     limitations under the License.
    17  */
    18  
    19  package archive
    20  
    21  import (
    22  	"bytes"
    23  	"context"
    24  	"fmt"
    25  	"io"
    26  	"io/ioutil"
    27  	"os"
    28  	"strings"
    29  	"testing"
    30  
    31  	"github.com/containerd/containerd/log/logtest"
    32  	"github.com/containerd/containerd/mount"
    33  	"github.com/containerd/containerd/pkg/testutil"
    34  	"github.com/containerd/containerd/snapshots/overlay"
    35  	"github.com/containerd/continuity/fs"
    36  	"github.com/containerd/continuity/fs/fstest"
    37  	"github.com/pkg/errors"
    38  )
    39  
    40  func TestOverlayApply(t *testing.T) {
    41  	testutil.RequiresRoot(t)
    42  
    43  	base, err := ioutil.TempDir("", "test-ovl-diff-apply-")
    44  	if err != nil {
    45  		t.Fatalf("unable to create temp dir: %+v", err)
    46  	}
    47  	defer os.RemoveAll(base)
    48  
    49  	if err := overlay.Supported(base); err != nil {
    50  		t.Skipf("skipping because overlay is not supported %v", err)
    51  	}
    52  	fstest.FSSuite(t, overlayDiffApplier{
    53  		tmp:  base,
    54  		diff: WriteDiff,
    55  		t:    t,
    56  	})
    57  }
    58  
    59  func TestOverlayApplyNoParents(t *testing.T) {
    60  	testutil.RequiresRoot(t)
    61  
    62  	base, err := ioutil.TempDir("", "test-ovl-diff-apply-")
    63  	if err != nil {
    64  		t.Fatalf("unable to create temp dir: %+v", err)
    65  	}
    66  	defer os.RemoveAll(base)
    67  
    68  	if err := overlay.Supported(base); err != nil {
    69  		t.Skipf("skipping because overlay is not supported %v", err)
    70  	}
    71  	fstest.FSSuite(t, overlayDiffApplier{
    72  		tmp: base,
    73  		diff: func(ctx context.Context, w io.Writer, a, b string) error {
    74  			cw := newChangeWriter(w, b)
    75  			cw.addedDirs = nil
    76  			err := fs.Changes(ctx, a, b, cw.HandleChange)
    77  			if err != nil {
    78  				return errors.Wrap(err, "failed to create diff tar stream")
    79  			}
    80  			return cw.Close()
    81  		},
    82  		t: t,
    83  	})
    84  }
    85  
    86  type overlayDiffApplier struct {
    87  	tmp  string
    88  	diff func(context.Context, io.Writer, string, string) error
    89  	t    *testing.T
    90  }
    91  
    92  type overlayContext struct {
    93  	merged  string
    94  	lowers  []string
    95  	mounted bool
    96  }
    97  
    98  type contextKey struct{}
    99  
   100  func (d overlayDiffApplier) TestContext(ctx context.Context) (context.Context, func(), error) {
   101  	merged, err := ioutil.TempDir(d.tmp, "merged")
   102  	if err != nil {
   103  		return ctx, nil, errors.Wrap(err, "failed to make merged dir")
   104  	}
   105  
   106  	oc := &overlayContext{
   107  		merged: merged,
   108  	}
   109  
   110  	ctx = logtest.WithT(ctx, d.t)
   111  
   112  	return context.WithValue(ctx, contextKey{}, oc), func() {
   113  		if oc.mounted {
   114  			mount.Unmount(oc.merged, 0)
   115  		}
   116  	}, nil
   117  }
   118  
   119  func (d overlayDiffApplier) Apply(ctx context.Context, a fstest.Applier) (string, func(), error) {
   120  	oc := ctx.Value(contextKey{}).(*overlayContext)
   121  
   122  	applyCopy, err := ioutil.TempDir(d.tmp, "apply-copy-")
   123  	if err != nil {
   124  		return "", nil, errors.Wrap(err, "failed to create temp dir")
   125  	}
   126  	defer os.RemoveAll(applyCopy)
   127  
   128  	base := oc.merged
   129  	if len(oc.lowers) == 1 {
   130  		base = oc.lowers[0]
   131  	}
   132  
   133  	if err = fs.CopyDir(applyCopy, base); err != nil {
   134  		return "", nil, errors.Wrap(err, "failed to copy base")
   135  	}
   136  
   137  	if err := a.Apply(applyCopy); err != nil {
   138  		return "", nil, errors.Wrap(err, "failed to apply changes to copy of base")
   139  	}
   140  
   141  	buf := bytes.NewBuffer(nil)
   142  
   143  	if err := d.diff(ctx, buf, base, applyCopy); err != nil {
   144  		return "", nil, errors.Wrap(err, "failed to create diff")
   145  	}
   146  
   147  	if oc.mounted {
   148  		if err := mount.Unmount(oc.merged, 0); err != nil {
   149  			return "", nil, errors.Wrap(err, "failed to unmount")
   150  		}
   151  		oc.mounted = false
   152  	}
   153  
   154  	next, err := ioutil.TempDir(d.tmp, "lower-")
   155  	if err != nil {
   156  		return "", nil, errors.Wrap(err, "failed to create temp dir")
   157  	}
   158  
   159  	if _, err = Apply(ctx, next, buf, WithConvertWhiteout(OverlayConvertWhiteout), WithParents(oc.lowers)); err != nil {
   160  		return "", nil, errors.Wrap(err, "failed to apply tar stream")
   161  	}
   162  
   163  	oc.lowers = append([]string{next}, oc.lowers...)
   164  
   165  	if len(oc.lowers) == 1 {
   166  		return oc.lowers[0], nil, nil
   167  	}
   168  
   169  	m := mount.Mount{
   170  		Type:   "overlay",
   171  		Source: "overlay",
   172  		Options: []string{
   173  			fmt.Sprintf("lowerdir=%s", strings.Join(oc.lowers, ":")),
   174  		},
   175  	}
   176  
   177  	if err := m.Mount(oc.merged); err != nil {
   178  		return "", nil, errors.Wrapf(err, "failed to mount: %v", m)
   179  	}
   180  	oc.mounted = true
   181  
   182  	return oc.merged, nil, nil
   183  }