github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/layer/migration_test.go (about)

     1  package layer // import "github.com/docker/docker/layer"
     2  
     3  import (
     4  	"bytes"
     5  	"compress/gzip"
     6  	"io"
     7  	"io/ioutil"
     8  	"os"
     9  	"path/filepath"
    10  	"runtime"
    11  	"testing"
    12  
    13  	"github.com/docker/docker/daemon/graphdriver"
    14  	"github.com/docker/docker/pkg/stringid"
    15  	"github.com/vbatts/tar-split/tar/asm"
    16  	"github.com/vbatts/tar-split/tar/storage"
    17  )
    18  
    19  func writeTarSplitFile(name string, tarContent []byte) error {
    20  	f, err := os.OpenFile(name, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644)
    21  	if err != nil {
    22  		return err
    23  	}
    24  	defer f.Close()
    25  
    26  	fz := gzip.NewWriter(f)
    27  
    28  	metaPacker := storage.NewJSONPacker(fz)
    29  	defer fz.Close()
    30  
    31  	rdr, err := asm.NewInputTarStream(bytes.NewReader(tarContent), metaPacker, nil)
    32  	if err != nil {
    33  		return err
    34  	}
    35  
    36  	if _, err := io.Copy(ioutil.Discard, rdr); err != nil {
    37  		return err
    38  	}
    39  
    40  	return nil
    41  }
    42  
    43  func TestLayerMigration(t *testing.T) {
    44  	// TODO Windows: Figure out why this is failing
    45  	if runtime.GOOS == "windows" {
    46  		t.Skip("Failing on Windows")
    47  	}
    48  	td, err := ioutil.TempDir("", "migration-test-")
    49  	if err != nil {
    50  		t.Fatal(err)
    51  	}
    52  	defer os.RemoveAll(td)
    53  
    54  	layer1Files := []FileApplier{
    55  		newTestFile("/root/.bashrc", []byte("# Boring configuration"), 0644),
    56  		newTestFile("/etc/profile", []byte("# Base configuration"), 0644),
    57  	}
    58  
    59  	layer2Files := []FileApplier{
    60  		newTestFile("/root/.bashrc", []byte("# Updated configuration"), 0644),
    61  	}
    62  
    63  	tar1, err := tarFromFiles(layer1Files...)
    64  	if err != nil {
    65  		t.Fatal(err)
    66  	}
    67  
    68  	tar2, err := tarFromFiles(layer2Files...)
    69  	if err != nil {
    70  		t.Fatal(err)
    71  	}
    72  
    73  	graph, err := newVFSGraphDriver(filepath.Join(td, "graphdriver-"))
    74  	if err != nil {
    75  		t.Fatal(err)
    76  	}
    77  
    78  	graphID1 := stringid.GenerateRandomID()
    79  	if err := graph.Create(graphID1, "", nil); err != nil {
    80  		t.Fatal(err)
    81  	}
    82  	if _, err := graph.ApplyDiff(graphID1, "", bytes.NewReader(tar1)); err != nil {
    83  		t.Fatal(err)
    84  	}
    85  
    86  	tf1 := filepath.Join(td, "tar1.json.gz")
    87  	if err := writeTarSplitFile(tf1, tar1); err != nil {
    88  		t.Fatal(err)
    89  	}
    90  
    91  	root := filepath.Join(td, "layers")
    92  	ls, err := newStoreFromGraphDriver(root, graph, runtime.GOOS)
    93  	if err != nil {
    94  		t.Fatal(err)
    95  	}
    96  
    97  	newTarDataPath := filepath.Join(td, ".migration-tardata")
    98  	diffID, size, err := ls.(*layerStore).ChecksumForGraphID(graphID1, "", tf1, newTarDataPath)
    99  	if err != nil {
   100  		t.Fatal(err)
   101  	}
   102  
   103  	layer1a, err := ls.(*layerStore).RegisterByGraphID(graphID1, "", diffID, newTarDataPath, size)
   104  	if err != nil {
   105  		t.Fatal(err)
   106  	}
   107  
   108  	layer1b, err := ls.Register(bytes.NewReader(tar1), "")
   109  	if err != nil {
   110  		t.Fatal(err)
   111  	}
   112  
   113  	assertReferences(t, layer1a, layer1b)
   114  	// Attempt register, should be same
   115  	layer2a, err := ls.Register(bytes.NewReader(tar2), layer1a.ChainID())
   116  	if err != nil {
   117  		t.Fatal(err)
   118  	}
   119  
   120  	graphID2 := stringid.GenerateRandomID()
   121  	if err := graph.Create(graphID2, graphID1, nil); err != nil {
   122  		t.Fatal(err)
   123  	}
   124  	if _, err := graph.ApplyDiff(graphID2, graphID1, bytes.NewReader(tar2)); err != nil {
   125  		t.Fatal(err)
   126  	}
   127  
   128  	tf2 := filepath.Join(td, "tar2.json.gz")
   129  	if err := writeTarSplitFile(tf2, tar2); err != nil {
   130  		t.Fatal(err)
   131  	}
   132  	diffID, size, err = ls.(*layerStore).ChecksumForGraphID(graphID2, graphID1, tf2, newTarDataPath)
   133  	if err != nil {
   134  		t.Fatal(err)
   135  	}
   136  
   137  	layer2b, err := ls.(*layerStore).RegisterByGraphID(graphID2, layer1a.ChainID(), diffID, tf2, size)
   138  	if err != nil {
   139  		t.Fatal(err)
   140  	}
   141  	assertReferences(t, layer2a, layer2b)
   142  
   143  	if metadata, err := ls.Release(layer2a); err != nil {
   144  		t.Fatal(err)
   145  	} else if len(metadata) > 0 {
   146  		t.Fatalf("Unexpected layer removal after first release: %#v", metadata)
   147  	}
   148  
   149  	metadata, err := ls.Release(layer2b)
   150  	if err != nil {
   151  		t.Fatal(err)
   152  	}
   153  
   154  	assertMetadata(t, metadata, createMetadata(layer2a))
   155  }
   156  
   157  func tarFromFilesInGraph(graph graphdriver.Driver, graphID, parentID string, files ...FileApplier) ([]byte, error) {
   158  	t, err := tarFromFiles(files...)
   159  	if err != nil {
   160  		return nil, err
   161  	}
   162  
   163  	if err := graph.Create(graphID, parentID, nil); err != nil {
   164  		return nil, err
   165  	}
   166  	if _, err := graph.ApplyDiff(graphID, parentID, bytes.NewReader(t)); err != nil {
   167  		return nil, err
   168  	}
   169  
   170  	ar, err := graph.Diff(graphID, parentID)
   171  	if err != nil {
   172  		return nil, err
   173  	}
   174  	defer ar.Close()
   175  
   176  	return ioutil.ReadAll(ar)
   177  }
   178  
   179  func TestLayerMigrationNoTarsplit(t *testing.T) {
   180  	// TODO Windows: Figure out why this is failing
   181  	if runtime.GOOS == "windows" {
   182  		t.Skip("Failing on Windows")
   183  	}
   184  	td, err := ioutil.TempDir("", "migration-test-")
   185  	if err != nil {
   186  		t.Fatal(err)
   187  	}
   188  	defer os.RemoveAll(td)
   189  
   190  	layer1Files := []FileApplier{
   191  		newTestFile("/root/.bashrc", []byte("# Boring configuration"), 0644),
   192  		newTestFile("/etc/profile", []byte("# Base configuration"), 0644),
   193  	}
   194  
   195  	layer2Files := []FileApplier{
   196  		newTestFile("/root/.bashrc", []byte("# Updated configuration"), 0644),
   197  	}
   198  
   199  	graph, err := newVFSGraphDriver(filepath.Join(td, "graphdriver-"))
   200  	if err != nil {
   201  		t.Fatal(err)
   202  	}
   203  	graphID1 := stringid.GenerateRandomID()
   204  	graphID2 := stringid.GenerateRandomID()
   205  
   206  	tar1, err := tarFromFilesInGraph(graph, graphID1, "", layer1Files...)
   207  	if err != nil {
   208  		t.Fatal(err)
   209  	}
   210  
   211  	tar2, err := tarFromFilesInGraph(graph, graphID2, graphID1, layer2Files...)
   212  	if err != nil {
   213  		t.Fatal(err)
   214  	}
   215  
   216  	root := filepath.Join(td, "layers")
   217  	ls, err := newStoreFromGraphDriver(root, graph, runtime.GOOS)
   218  	if err != nil {
   219  		t.Fatal(err)
   220  	}
   221  
   222  	newTarDataPath := filepath.Join(td, ".migration-tardata")
   223  	diffID, size, err := ls.(*layerStore).ChecksumForGraphID(graphID1, "", "", newTarDataPath)
   224  	if err != nil {
   225  		t.Fatal(err)
   226  	}
   227  
   228  	layer1a, err := ls.(*layerStore).RegisterByGraphID(graphID1, "", diffID, newTarDataPath, size)
   229  	if err != nil {
   230  		t.Fatal(err)
   231  	}
   232  
   233  	layer1b, err := ls.Register(bytes.NewReader(tar1), "")
   234  	if err != nil {
   235  		t.Fatal(err)
   236  	}
   237  
   238  	assertReferences(t, layer1a, layer1b)
   239  
   240  	// Attempt register, should be same
   241  	layer2a, err := ls.Register(bytes.NewReader(tar2), layer1a.ChainID())
   242  	if err != nil {
   243  		t.Fatal(err)
   244  	}
   245  
   246  	diffID, size, err = ls.(*layerStore).ChecksumForGraphID(graphID2, graphID1, "", newTarDataPath)
   247  	if err != nil {
   248  		t.Fatal(err)
   249  	}
   250  
   251  	layer2b, err := ls.(*layerStore).RegisterByGraphID(graphID2, layer1a.ChainID(), diffID, newTarDataPath, size)
   252  	if err != nil {
   253  		t.Fatal(err)
   254  	}
   255  	assertReferences(t, layer2a, layer2b)
   256  
   257  	if metadata, err := ls.Release(layer2a); err != nil {
   258  		t.Fatal(err)
   259  	} else if len(metadata) > 0 {
   260  		t.Fatalf("Unexpected layer removal after first release: %#v", metadata)
   261  	}
   262  
   263  	metadata, err := ls.Release(layer2b)
   264  	if err != nil {
   265  		t.Fatal(err)
   266  	}
   267  
   268  	assertMetadata(t, metadata, createMetadata(layer2a))
   269  }