github.com/vincentwoo/docker@v0.7.3-0.20160116130405-82401a4b13c0/layer/migration_test.go (about)

     1  package layer
     2  
     3  import (
     4  	"bytes"
     5  	"compress/gzip"
     6  	"fmt"
     7  	"io"
     8  	"io/ioutil"
     9  	"os"
    10  	"path/filepath"
    11  	"testing"
    12  
    13  	"github.com/docker/docker/daemon/graphdriver"
    14  	"github.com/docker/docker/pkg/archive"
    15  	"github.com/docker/docker/pkg/stringid"
    16  	"github.com/vbatts/tar-split/tar/asm"
    17  	"github.com/vbatts/tar-split/tar/storage"
    18  )
    19  
    20  func writeTarSplitFile(name string, tarContent []byte) error {
    21  	f, err := os.OpenFile(name, os.O_TRUNC|os.O_CREATE|os.O_WRONLY, 0644)
    22  	if err != nil {
    23  		return err
    24  	}
    25  	defer f.Close()
    26  
    27  	fz := gzip.NewWriter(f)
    28  
    29  	metaPacker := storage.NewJSONPacker(fz)
    30  	defer fz.Close()
    31  
    32  	rdr, err := asm.NewInputTarStream(bytes.NewReader(tarContent), metaPacker, nil)
    33  	if err != nil {
    34  		return err
    35  	}
    36  
    37  	if _, err := io.Copy(ioutil.Discard, rdr); err != nil {
    38  		return err
    39  	}
    40  
    41  	return nil
    42  }
    43  
    44  func TestLayerMigration(t *testing.T) {
    45  	td, err := ioutil.TempDir("", "migration-test-")
    46  	if err != nil {
    47  		t.Fatal(err)
    48  	}
    49  	defer os.RemoveAll(td)
    50  
    51  	layer1Files := []FileApplier{
    52  		newTestFile("/root/.bashrc", []byte("# Boring configuration"), 0644),
    53  		newTestFile("/etc/profile", []byte("# Base configuration"), 0644),
    54  	}
    55  
    56  	layer2Files := []FileApplier{
    57  		newTestFile("/root/.bashrc", []byte("# Updated configuration"), 0644),
    58  	}
    59  
    60  	tar1, err := tarFromFiles(layer1Files...)
    61  	if err != nil {
    62  		t.Fatal(err)
    63  	}
    64  
    65  	tar2, err := tarFromFiles(layer2Files...)
    66  	if err != nil {
    67  		t.Fatal(err)
    68  	}
    69  
    70  	graph, err := newVFSGraphDriver(filepath.Join(td, "graphdriver-"))
    71  	if err != nil {
    72  		t.Fatal(err)
    73  	}
    74  
    75  	graphID1 := stringid.GenerateRandomID()
    76  	if err := graph.Create(graphID1, "", ""); err != nil {
    77  		t.Fatal(err)
    78  	}
    79  	if _, err := graph.ApplyDiff(graphID1, "", archive.Reader(bytes.NewReader(tar1))); err != nil {
    80  		t.Fatal(err)
    81  	}
    82  
    83  	tf1 := filepath.Join(td, "tar1.json.gz")
    84  	if err := writeTarSplitFile(tf1, tar1); err != nil {
    85  		t.Fatal(err)
    86  	}
    87  
    88  	fms, err := NewFSMetadataStore(filepath.Join(td, "layers"))
    89  	if err != nil {
    90  		t.Fatal(err)
    91  	}
    92  	ls, err := NewStoreFromGraphDriver(fms, graph)
    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, ""); err != nil {
   122  		t.Fatal(err)
   123  	}
   124  	if _, err := graph.ApplyDiff(graphID2, graphID1, archive.Reader(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, ""); err != nil {
   164  		return nil, err
   165  	}
   166  	if _, err := graph.ApplyDiff(graphID, parentID, archive.Reader(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  	td, err := ioutil.TempDir("", "migration-test-")
   181  	if err != nil {
   182  		t.Fatal(err)
   183  	}
   184  	defer os.RemoveAll(td)
   185  
   186  	layer1Files := []FileApplier{
   187  		newTestFile("/root/.bashrc", []byte("# Boring configuration"), 0644),
   188  		newTestFile("/etc/profile", []byte("# Base configuration"), 0644),
   189  	}
   190  
   191  	layer2Files := []FileApplier{
   192  		newTestFile("/root/.bashrc", []byte("# Updated configuration"), 0644),
   193  	}
   194  
   195  	graph, err := newVFSGraphDriver(filepath.Join(td, "graphdriver-"))
   196  	if err != nil {
   197  		t.Fatal(err)
   198  	}
   199  	graphID1 := stringid.GenerateRandomID()
   200  	graphID2 := stringid.GenerateRandomID()
   201  
   202  	tar1, err := tarFromFilesInGraph(graph, graphID1, "", layer1Files...)
   203  	if err != nil {
   204  		t.Fatal(err)
   205  	}
   206  
   207  	tar2, err := tarFromFilesInGraph(graph, graphID2, graphID1, layer2Files...)
   208  	if err != nil {
   209  		t.Fatal(err)
   210  	}
   211  
   212  	fms, err := NewFSMetadataStore(filepath.Join(td, "layers"))
   213  	if err != nil {
   214  		t.Fatal(err)
   215  	}
   216  	ls, err := NewStoreFromGraphDriver(fms, graph)
   217  	if err != nil {
   218  		t.Fatal(err)
   219  	}
   220  
   221  	newTarDataPath := filepath.Join(td, ".migration-tardata")
   222  	diffID, size, err := ls.(*layerStore).ChecksumForGraphID(graphID1, "", "", newTarDataPath)
   223  	if err != nil {
   224  		t.Fatal(err)
   225  	}
   226  
   227  	layer1a, err := ls.(*layerStore).RegisterByGraphID(graphID1, "", diffID, newTarDataPath, size)
   228  	if err != nil {
   229  		t.Fatal(err)
   230  	}
   231  
   232  	layer1b, err := ls.Register(bytes.NewReader(tar1), "")
   233  	if err != nil {
   234  		t.Fatal(err)
   235  	}
   236  
   237  	assertReferences(t, layer1a, layer1b)
   238  
   239  	// Attempt register, should be same
   240  	layer2a, err := ls.Register(bytes.NewReader(tar2), layer1a.ChainID())
   241  	if err != nil {
   242  		t.Fatal(err)
   243  	}
   244  
   245  	diffID, size, err = ls.(*layerStore).ChecksumForGraphID(graphID2, graphID1, "", newTarDataPath)
   246  	if err != nil {
   247  		t.Fatal(err)
   248  	}
   249  
   250  	layer2b, err := ls.(*layerStore).RegisterByGraphID(graphID2, layer1a.ChainID(), diffID, newTarDataPath, size)
   251  	if err != nil {
   252  		t.Fatal(err)
   253  	}
   254  	assertReferences(t, layer2a, layer2b)
   255  
   256  	if metadata, err := ls.Release(layer2a); err != nil {
   257  		t.Fatal(err)
   258  	} else if len(metadata) > 0 {
   259  		t.Fatalf("Unexpected layer removal after first release: %#v", metadata)
   260  	}
   261  
   262  	metadata, err := ls.Release(layer2b)
   263  	if err != nil {
   264  		t.Fatal(err)
   265  	}
   266  
   267  	assertMetadata(t, metadata, createMetadata(layer2a))
   268  }
   269  
   270  func TestMountMigration(t *testing.T) {
   271  	ls, cleanup := newTestStore(t)
   272  	defer cleanup()
   273  
   274  	baseFiles := []FileApplier{
   275  		newTestFile("/root/.bashrc", []byte("# Boring configuration"), 0644),
   276  		newTestFile("/etc/profile", []byte("# Base configuration"), 0644),
   277  	}
   278  	initFiles := []FileApplier{
   279  		newTestFile("/etc/hosts", []byte{}, 0644),
   280  		newTestFile("/etc/resolv.conf", []byte{}, 0644),
   281  	}
   282  	mountFiles := []FileApplier{
   283  		newTestFile("/etc/hosts", []byte("localhost 127.0.0.1"), 0644),
   284  		newTestFile("/root/.bashrc", []byte("# Updated configuration"), 0644),
   285  		newTestFile("/root/testfile1.txt", []byte("nothing valuable"), 0644),
   286  	}
   287  
   288  	initTar, err := tarFromFiles(initFiles...)
   289  	if err != nil {
   290  		t.Fatal(err)
   291  	}
   292  
   293  	mountTar, err := tarFromFiles(mountFiles...)
   294  	if err != nil {
   295  		t.Fatal(err)
   296  	}
   297  
   298  	graph := ls.(*layerStore).driver
   299  
   300  	layer1, err := createLayer(ls, "", initWithFiles(baseFiles...))
   301  	if err != nil {
   302  		t.Fatal(err)
   303  	}
   304  
   305  	graphID1 := layer1.(*referencedCacheLayer).cacheID
   306  
   307  	containerID := stringid.GenerateRandomID()
   308  	containerInit := fmt.Sprintf("%s-init", containerID)
   309  
   310  	if err := graph.Create(containerInit, graphID1, ""); err != nil {
   311  		t.Fatal(err)
   312  	}
   313  	if _, err := graph.ApplyDiff(containerInit, graphID1, archive.Reader(bytes.NewReader(initTar))); err != nil {
   314  		t.Fatal(err)
   315  	}
   316  
   317  	if err := graph.Create(containerID, containerInit, ""); err != nil {
   318  		t.Fatal(err)
   319  	}
   320  	if _, err := graph.ApplyDiff(containerID, containerInit, archive.Reader(bytes.NewReader(mountTar))); err != nil {
   321  		t.Fatal(err)
   322  	}
   323  
   324  	if err := ls.(*layerStore).CreateRWLayerByGraphID("migration-mount", containerID, layer1.ChainID()); err != nil {
   325  		t.Fatal(err)
   326  	}
   327  
   328  	rwLayer1, err := ls.GetRWLayer("migration-mount")
   329  	if err != nil {
   330  		t.Fatal(err)
   331  	}
   332  
   333  	if _, err := rwLayer1.Mount(""); err != nil {
   334  		t.Fatal(err)
   335  	}
   336  
   337  	changes, err := rwLayer1.Changes()
   338  	if err != nil {
   339  		t.Fatal(err)
   340  	}
   341  
   342  	if expected := 5; len(changes) != expected {
   343  		t.Logf("Changes %#v", changes)
   344  		t.Fatalf("Wrong number of changes %d, expected %d", len(changes), expected)
   345  	}
   346  
   347  	sortChanges(changes)
   348  
   349  	assertChange(t, changes[0], archive.Change{
   350  		Path: "/etc",
   351  		Kind: archive.ChangeModify,
   352  	})
   353  	assertChange(t, changes[1], archive.Change{
   354  		Path: "/etc/hosts",
   355  		Kind: archive.ChangeModify,
   356  	})
   357  	assertChange(t, changes[2], archive.Change{
   358  		Path: "/root",
   359  		Kind: archive.ChangeModify,
   360  	})
   361  	assertChange(t, changes[3], archive.Change{
   362  		Path: "/root/.bashrc",
   363  		Kind: archive.ChangeModify,
   364  	})
   365  	assertChange(t, changes[4], archive.Change{
   366  		Path: "/root/testfile1.txt",
   367  		Kind: archive.ChangeAdd,
   368  	})
   369  
   370  	assertActivityCount(t, rwLayer1, 1)
   371  
   372  	if _, err := ls.CreateRWLayer("migration-mount", layer1.ChainID(), "", nil); err == nil {
   373  		t.Fatal("Expected error creating mount with same name")
   374  	} else if err != ErrMountNameConflict {
   375  		t.Fatal(err)
   376  	}
   377  
   378  	rwLayer2, err := ls.GetRWLayer("migration-mount")
   379  	if err != nil {
   380  		t.Fatal(err)
   381  	}
   382  
   383  	if getMountLayer(rwLayer1) != getMountLayer(rwLayer2) {
   384  		t.Fatal("Expected same layer from get with same name as from migrate")
   385  	}
   386  
   387  	if _, err := rwLayer2.Mount(""); err != nil {
   388  		t.Fatal(err)
   389  	}
   390  
   391  	assertActivityCount(t, rwLayer2, 1)
   392  	assertActivityCount(t, rwLayer1, 1)
   393  
   394  	if _, err := rwLayer2.Mount(""); err != nil {
   395  		t.Fatal(err)
   396  	}
   397  
   398  	assertActivityCount(t, rwLayer2, 2)
   399  	assertActivityCount(t, rwLayer1, 1)
   400  
   401  	if metadata, err := ls.Release(layer1); err != nil {
   402  		t.Fatal(err)
   403  	} else if len(metadata) > 0 {
   404  		t.Fatalf("Expected no layers to be deleted, deleted %#v", metadata)
   405  	}
   406  
   407  	if err := rwLayer1.Unmount(); err != nil {
   408  		t.Fatal(err)
   409  	}
   410  	assertActivityCount(t, rwLayer2, 2)
   411  	assertActivityCount(t, rwLayer1, 0)
   412  
   413  	if _, err := ls.ReleaseRWLayer(rwLayer1); err != nil {
   414  		t.Fatal(err)
   415  	}
   416  
   417  	if err := rwLayer2.Unmount(); err != nil {
   418  		t.Fatal(err)
   419  	}
   420  	if _, err := ls.ReleaseRWLayer(rwLayer2); err == nil {
   421  		t.Fatal("Expected error deleting active mount")
   422  	}
   423  	if err := rwLayer2.Unmount(); err != nil {
   424  		t.Fatal(err)
   425  	}
   426  	metadata, err := ls.ReleaseRWLayer(rwLayer2)
   427  	if err != nil {
   428  		t.Fatal(err)
   429  	}
   430  	if len(metadata) == 0 {
   431  		t.Fatal("Expected base layer to be deleted when deleting mount")
   432  	}
   433  
   434  	assertMetadata(t, metadata, createMetadata(layer1))
   435  }