Merge pull request #434 from AkihiroSuda/terminology
snapshot: fix terminology inconsistency
This commit is contained in:
commit
7101c7a9e2
9 changed files with 102 additions and 98 deletions
|
@ -21,7 +21,7 @@ minimal API simplifies behavior without sacrificing power. This makes the
|
||||||
surface area for driver implementations smaller, ensuring that behavior is more
|
surface area for driver implementations smaller, ensuring that behavior is more
|
||||||
consistent between implementations.
|
consistent between implementations.
|
||||||
|
|
||||||
These differ from the concept of the graphdriver in that the LayerManipulator
|
These differ from the concept of the graphdriver in that the _Snapshot Manager_
|
||||||
has no knowledge of images or containers. Users simply prepare and commit
|
has no knowledge of images or containers. Users simply prepare and commit
|
||||||
directories. We also avoid the integration between graph drivers and the tar
|
directories. We also avoid the integration between graph drivers and the tar
|
||||||
format used to represent the changesets.
|
format used to represent the changesets.
|
||||||
|
@ -125,8 +125,8 @@ Per the terminology above, `tmpLocation` is known as the `target`. `layerPath`
|
||||||
is simply a tar file, representing a changset. We start by using
|
is simply a tar file, representing a changset. We start by using
|
||||||
`SnapshotManager` to prepare the temporary location as a snapshot point:
|
`SnapshotManager` to prepare the temporary location as a snapshot point:
|
||||||
|
|
||||||
lm := SnapshotManager()
|
sm := SnapshotManager()
|
||||||
mounts, err := lm.Prepare(tmpLocation, "")
|
mounts, err := sm.Prepare(tmpLocation, "")
|
||||||
if err != nil { ... }
|
if err != nil { ... }
|
||||||
|
|
||||||
Note that we provide "" as the `parent`, since we are applying the diff to an
|
Note that we provide "" as the `parent`, since we are applying the diff to an
|
||||||
|
@ -142,6 +142,8 @@ that applies the contents of the layer to target location and calculates the
|
||||||
DiffID of the unpacked layer (this is a requirement for docker
|
DiffID of the unpacked layer (this is a requirement for docker
|
||||||
implementation):
|
implementation):
|
||||||
|
|
||||||
|
layer, err := os.Open(layerPath)
|
||||||
|
if err != nil { ... }
|
||||||
digest, err := unpackLayer(tmpLocation, layer) // unpack into layer location
|
digest, err := unpackLayer(tmpLocation, layer) // unpack into layer location
|
||||||
if err != nil { ... }
|
if err != nil { ... }
|
||||||
|
|
||||||
|
@ -156,7 +158,7 @@ the actual diff. For this example, we are just going to use the layer `digest`,
|
||||||
but in practice, this will probably be the `ChainID`:
|
but in practice, this will probably be the `ChainID`:
|
||||||
|
|
||||||
diffPath := filepath.Join("/layers", digest) // name location for the uncompressed layer digest
|
diffPath := filepath.Join("/layers", digest) // name location for the uncompressed layer digest
|
||||||
if err := lm.Commit(diffPath, tmpLocation); err != nil { ... }
|
if err := sm.Commit(diffPath, tmpLocation); err != nil { ... }
|
||||||
|
|
||||||
The new layer has been imported as a _snapshot_ into the `SnapshotManager`
|
The new layer has been imported as a _snapshot_ into the `SnapshotManager`
|
||||||
under the name `diffPath`. `diffPath`, which is a user opaque directory
|
under the name `diffPath`. `diffPath`, which is a user opaque directory
|
||||||
|
@ -166,9 +168,9 @@ location, can then be used as a parent in later snapshots.
|
||||||
|
|
||||||
Making a layer depend on the above is identical to the process described
|
Making a layer depend on the above is identical to the process described
|
||||||
above except that the parent is provided as diffPath when calling
|
above except that the parent is provided as diffPath when calling
|
||||||
`Snapshot.Prepare`:
|
`SnapshotManager.Prepare`:
|
||||||
|
|
||||||
mounts, err := lm.Prepare(tmpLocation, parentDiffPath)
|
mounts, err := sm.Prepare(tmpLocation, parentDiffPath)
|
||||||
|
|
||||||
Because have a provided a `parent`, the resulting `tmpLocation`, after
|
Because have a provided a `parent`, the resulting `tmpLocation`, after
|
||||||
mounting, will have the changes from above. Any new changes will be isolated to
|
mounting, will have the changes from above. Any new changes will be isolated to
|
||||||
|
@ -182,13 +184,13 @@ To run a container, we simply provide `SnapshotManager.Prepare` the `diff` of
|
||||||
the image we want to start the container from. After mounting, the prepared
|
the image we want to start the container from. After mounting, the prepared
|
||||||
path can be used directly as the container's filesystem:
|
path can be used directly as the container's filesystem:
|
||||||
|
|
||||||
mounts, err := lm.Prepare(containerRootFS, imageDiffPath)
|
mounts, err := sm.Prepare(containerRootFS, imageDiffPath)
|
||||||
|
|
||||||
The returned mounts can then be passed directly to the container runtime. If
|
The returned mounts can then be passed directly to the container runtime. If
|
||||||
one would like to create a new image from the filesystem,
|
one would like to create a new image from the filesystem,
|
||||||
SnapshotManipulator.Commit is called:
|
`SnapshotManager.Commit` is called:
|
||||||
|
|
||||||
if err := lm.Commit(newImageDiff, containerRootFS); err != nil { ... }
|
if err := sm.Commit(newImageDiff, containerRootFS); err != nil { ... }
|
||||||
|
|
||||||
Alternatively, for most container runs, Snapshot.Rollback will be
|
Alternatively, for most container runs, `SnapshotManager.Rollback` will be
|
||||||
called to signal `SnapshotManager` to abandon the changes.
|
called to signal `SnapshotManager` to abandon the changes.
|
||||||
|
|
|
@ -19,8 +19,8 @@ func NewBtrfs(device, root string) (*Btrfs, error) {
|
||||||
return &Btrfs{device: device, root: root}, nil
|
return &Btrfs{device: device, root: root}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *Btrfs) Prepare(key, parent string) ([]containerd.Mount, error) {
|
func (b *Btrfs) Prepare(key, parent string) ([]containerd.Mount, error) {
|
||||||
active := filepath.Join(lm.root, "active")
|
active := filepath.Join(b.root, "active")
|
||||||
if err := os.MkdirAll(active, 0755); err != nil {
|
if err := os.MkdirAll(active, 0755); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -49,7 +49,7 @@ func (lm *Btrfs) Prepare(key, parent string) ([]containerd.Mount, error) {
|
||||||
return []containerd.Mount{
|
return []containerd.Mount{
|
||||||
{
|
{
|
||||||
Type: "btrfs",
|
Type: "btrfs",
|
||||||
Source: lm.device, // device?
|
Source: b.device, // device?
|
||||||
// NOTE(stevvooe): While it would be nice to use to uuids for
|
// NOTE(stevvooe): While it would be nice to use to uuids for
|
||||||
// mounts, they don't work reliably if the uuids are missing.
|
// mounts, they don't work reliably if the uuids are missing.
|
||||||
Options: []string{fmt.Sprintf("subvolid=%d", info.ID)},
|
Options: []string{fmt.Sprintf("subvolid=%d", info.ID)},
|
||||||
|
@ -57,8 +57,8 @@ func (lm *Btrfs) Prepare(key, parent string) ([]containerd.Mount, error) {
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *Btrfs) Commit(name, key string) error {
|
func (b *Btrfs) Commit(name, key string) error {
|
||||||
dir := filepath.Join(lm.root, "active", hash(key))
|
dir := filepath.Join(b.root, "active", hash(key))
|
||||||
|
|
||||||
fmt.Println("commit to", name)
|
fmt.Println("commit to", name)
|
||||||
if err := btrfs.SubvolSnapshot(name, dir, true); err != nil {
|
if err := btrfs.SubvolSnapshot(name, dir, true); err != nil {
|
||||||
|
|
|
@ -28,11 +28,11 @@ func TestBtrfs(t *testing.T) {
|
||||||
defer os.RemoveAll(root)
|
defer os.RemoveAll(root)
|
||||||
|
|
||||||
target := filepath.Join(root, "test")
|
target := filepath.Join(root, "test")
|
||||||
sm, err := NewBtrfs(device.deviceName, root)
|
b, err := NewBtrfs(device.deviceName, root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
mounts, err := sm.Prepare(target, "")
|
mounts, err := b.Prepare(target, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ func TestBtrfs(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sm.Commit(filepath.Join(root, "snapshots/committed"), filepath.Join(root, "test")); err != nil {
|
if err := b.Commit(filepath.Join(root, "snapshots/committed"), filepath.Join(root, "test")); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
|
@ -80,7 +80,7 @@ func TestBtrfs(t *testing.T) {
|
||||||
}()
|
}()
|
||||||
|
|
||||||
target = filepath.Join(root, "test2")
|
target = filepath.Join(root, "test2")
|
||||||
mounts, err = sm.Prepare(target, filepath.Join(root, "snapshots/committed"))
|
mounts, err = b.Prepare(target, filepath.Join(root, "snapshots/committed"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ func TestBtrfs(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sm.Commit(filepath.Join(root, "snapshots/committed2"), target); err != nil {
|
if err := b.Commit(filepath.Join(root, "snapshots/committed2"), target); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
|
|
|
@ -31,8 +31,8 @@ import (
|
||||||
// We then use a Manager to prepare the temporary location as a
|
// We then use a Manager to prepare the temporary location as a
|
||||||
// snapshot point:
|
// snapshot point:
|
||||||
//
|
//
|
||||||
// lm := NewManager()
|
// sm := NewManager()
|
||||||
// mounts, err := lm.Prepare(tmpLocation, "")
|
// mounts, err := sm.Prepare(tmpLocation, "")
|
||||||
// if err != nil { ... }
|
// if err != nil { ... }
|
||||||
//
|
//
|
||||||
// Note that we provide "" as the parent, since we are applying the diff to an
|
// Note that we provide "" as the parent, since we are applying the diff to an
|
||||||
|
@ -48,6 +48,8 @@ import (
|
||||||
// DiffID of the unpacked layer (this is a requirement for docker
|
// DiffID of the unpacked layer (this is a requirement for docker
|
||||||
// implementation):
|
// implementation):
|
||||||
//
|
//
|
||||||
|
// layer, err := os.Open(layerPath)
|
||||||
|
// if err != nil { ... }
|
||||||
// digest, err := unpackLayer(tmpLocation, layer) // unpack into layer location
|
// digest, err := unpackLayer(tmpLocation, layer) // unpack into layer location
|
||||||
// if err != nil { ... }
|
// if err != nil { ... }
|
||||||
//
|
//
|
||||||
|
@ -62,7 +64,7 @@ import (
|
||||||
// digest, but in practice, this will probably be the ChainID:
|
// digest, but in practice, this will probably be the ChainID:
|
||||||
//
|
//
|
||||||
// diffPath := filepath.Join("/layers", digest) // name location for the uncompressed layer digest
|
// diffPath := filepath.Join("/layers", digest) // name location for the uncompressed layer digest
|
||||||
// if err := lm.Commit(diffPath, tmpLocation); err != nil { ... }
|
// if err := sm.Commit(diffPath, tmpLocation); err != nil { ... }
|
||||||
//
|
//
|
||||||
// Now, we have a layer in the Manager that can be accessed with the
|
// Now, we have a layer in the Manager that can be accessed with the
|
||||||
// opaque diffPath provided during commit.
|
// opaque diffPath provided during commit.
|
||||||
|
@ -73,7 +75,7 @@ import (
|
||||||
// above except that the parent is provided as diffPath when calling
|
// above except that the parent is provided as diffPath when calling
|
||||||
// Manager.Prepare:
|
// Manager.Prepare:
|
||||||
//
|
//
|
||||||
// mounts, err := lm.Prepare(tmpLocation, parentDiffPath)
|
// mounts, err := sm.Prepare(tmpLocation, parentDiffPath)
|
||||||
//
|
//
|
||||||
// The diff will be captured at tmpLocation, as the layer is applied.
|
// The diff will be captured at tmpLocation, as the layer is applied.
|
||||||
//
|
//
|
||||||
|
@ -83,13 +85,13 @@ import (
|
||||||
// of the image we want to start the container from. After mounting, the
|
// of the image we want to start the container from. After mounting, the
|
||||||
// prepared path can be used directly as the container's filesystem:
|
// prepared path can be used directly as the container's filesystem:
|
||||||
//
|
//
|
||||||
// mounts, err := lm.Prepare(containerRootFS, imageDiffPath)
|
// mounts, err := sm.Prepare(containerRootFS, imageDiffPath)
|
||||||
//
|
//
|
||||||
// The returned mounts can then be passed directly to the container runtime. If
|
// The returned mounts can then be passed directly to the container runtime. If
|
||||||
// one would like to create a new image from the filesystem,
|
// one would like to create a new image from the filesystem,
|
||||||
// Manager.Commit is called:
|
// Manager.Commit is called:
|
||||||
//
|
//
|
||||||
// if err := lm.Commit(newImageDiff, containerRootFS); err != nil { ... }
|
// if err := sm.Commit(newImageDiff, containerRootFS); err != nil { ... }
|
||||||
//
|
//
|
||||||
// Alternatively, for most container runs, Manager.Rollback will be
|
// Alternatively, for most container runs, Manager.Rollback will be
|
||||||
// called to signal Manager to abandon the changes.
|
// called to signal Manager to abandon the changes.
|
||||||
|
@ -97,7 +99,7 @@ import (
|
||||||
// TODO(stevvooe): Consider an alternate API that provides an active object to
|
// TODO(stevvooe): Consider an alternate API that provides an active object to
|
||||||
// represent the lifecycle:
|
// represent the lifecycle:
|
||||||
//
|
//
|
||||||
// work, err := lm.Prepare(dst, parent)
|
// work, err := sm.Prepare(dst, parent)
|
||||||
// mountAll(work.Mounts())
|
// mountAll(work.Mounts())
|
||||||
// work.Commit() || work.Rollback()
|
// work.Commit() || work.Rollback()
|
||||||
//
|
//
|
||||||
|
@ -144,7 +146,7 @@ func NewManager(root string) (*Manager, error) {
|
||||||
//
|
//
|
||||||
// Once the writes have completed, Manager.Commit or
|
// Once the writes have completed, Manager.Commit or
|
||||||
// Manager.Rollback should be called on dst.
|
// Manager.Rollback should be called on dst.
|
||||||
func (lm *Manager) Prepare(dst, parent string) ([]containerd.Mount, error) {
|
func (sm *Manager) Prepare(dst, parent string) ([]containerd.Mount, error) {
|
||||||
// we want to build up lowerdir, upperdir and workdir options for the
|
// we want to build up lowerdir, upperdir and workdir options for the
|
||||||
// overlay mount.
|
// overlay mount.
|
||||||
//
|
//
|
||||||
|
@ -157,25 +159,25 @@ func (lm *Manager) Prepare(dst, parent string) ([]containerd.Mount, error) {
|
||||||
// workdir needs to be there but it is not really clear why.
|
// workdir needs to be there but it is not really clear why.
|
||||||
var opts []string
|
var opts []string
|
||||||
|
|
||||||
upperdir, err := ioutil.TempDir(lm.root, "diff-")
|
upperdir, err := ioutil.TempDir(sm.root, "diff-")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
opts = append(opts, "upperdir="+upperdir)
|
opts = append(opts, "upperdir="+upperdir)
|
||||||
|
|
||||||
workdir, err := ioutil.TempDir(lm.root, "work-")
|
workdir, err := ioutil.TempDir(sm.root, "work-")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
opts = append(opts, "workdir="+workdir)
|
opts = append(opts, "workdir="+workdir)
|
||||||
|
|
||||||
empty := filepath.Join(lm.root, "empty")
|
empty := filepath.Join(sm.root, "empty")
|
||||||
if err := os.MkdirAll(empty, 0777); err != nil {
|
if err := os.MkdirAll(empty, 0777); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(stevvooe): Write this metadata to disk to make it useful.
|
// TODO(stevvooe): Write this metadata to disk to make it useful.
|
||||||
lm.active[dst] = activeLayer{
|
sm.active[dst] = activeLayer{
|
||||||
parent: parent,
|
parent: parent,
|
||||||
upperdir: upperdir,
|
upperdir: upperdir,
|
||||||
workdir: workdir,
|
workdir: workdir,
|
||||||
|
@ -184,7 +186,7 @@ func (lm *Manager) Prepare(dst, parent string) ([]containerd.Mount, error) {
|
||||||
var parents []string
|
var parents []string
|
||||||
for parent != "" {
|
for parent != "" {
|
||||||
parents = append(parents, parent)
|
parents = append(parents, parent)
|
||||||
parent = lm.Parent(parent)
|
parent = sm.Parent(parent)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(parents) == 0 {
|
if len(parents) == 0 {
|
||||||
|
@ -210,18 +212,18 @@ func (lm *Manager) Prepare(dst, parent string) ([]containerd.Mount, error) {
|
||||||
//
|
//
|
||||||
// Calling Commit on dst will result in an error. Calling Rollback on dst
|
// Calling Commit on dst will result in an error. Calling Rollback on dst
|
||||||
// should be done to cleanup resources.
|
// should be done to cleanup resources.
|
||||||
func (lm *Manager) View(dst, parent string) ([]containerd.Mount, error) {
|
func (sm *Manager) View(dst, parent string) ([]containerd.Mount, error) {
|
||||||
panic("not implemented")
|
panic("not implemented")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit captures the changes between dst and its parent into the path
|
// Commit captures the changes between dst and its parent into the path
|
||||||
// provided by diff. The path diff can then be used with the layer
|
// provided by diff. The path diff can then be used with the snapshot
|
||||||
// manipulator's other methods to access the diff content.
|
// manager's other methods to access the diff content.
|
||||||
//
|
//
|
||||||
// The contents of diff are opaque to the caller and may be specific to the
|
// The contents of diff are opaque to the caller and may be specific to the
|
||||||
// implementation of the layer backend.
|
// implementation of the layer backend.
|
||||||
func (lm *Manager) Commit(diff, dst string) error {
|
func (sm *Manager) Commit(diff, dst string) error {
|
||||||
active, ok := lm.active[dst]
|
active, ok := sm.active[dst]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("%q must be an active layer", dst)
|
return fmt.Errorf("%q must be an active layer", dst)
|
||||||
}
|
}
|
||||||
|
@ -237,8 +239,8 @@ func (lm *Manager) Commit(diff, dst string) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
lm.parents[diff] = active.parent
|
sm.parents[diff] = active.parent
|
||||||
delete(lm.active, dst) // remove from active, again, consider not doing this to support multiple commits.
|
delete(sm.active, dst) // remove from active, again, consider not doing this to support multiple commits.
|
||||||
// note that allowing multiple commits would require copy for overlay.
|
// note that allowing multiple commits would require copy for overlay.
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
|
@ -246,8 +248,8 @@ func (lm *Manager) Commit(diff, dst string) error {
|
||||||
|
|
||||||
// Rollback can be called after prepare if the caller would like to abandon the
|
// Rollback can be called after prepare if the caller would like to abandon the
|
||||||
// changeset.
|
// changeset.
|
||||||
func (lm *Manager) Rollback(dst string) error {
|
func (sm *Manager) Rollback(dst string) error {
|
||||||
active, ok := lm.active[dst]
|
active, ok := sm.active[dst]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("%q must be an active layer", dst)
|
return fmt.Errorf("%q must be an active layer", dst)
|
||||||
}
|
}
|
||||||
|
@ -256,13 +258,13 @@ func (lm *Manager) Rollback(dst string) error {
|
||||||
err = os.RemoveAll(active.upperdir)
|
err = os.RemoveAll(active.upperdir)
|
||||||
err = os.RemoveAll(active.workdir)
|
err = os.RemoveAll(active.workdir)
|
||||||
|
|
||||||
delete(lm.active, dst)
|
delete(sm.active, dst)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parent returns the parent of the layer at diff.
|
// Parent returns the parent of the layer at diff.
|
||||||
func (lm *Manager) Parent(diff string) string {
|
func (sm *Manager) Parent(diff string) string {
|
||||||
return lm.parents[diff]
|
return sm.parents[diff]
|
||||||
}
|
}
|
||||||
|
|
||||||
type ChangeKind int
|
type ChangeKind int
|
||||||
|
@ -301,6 +303,6 @@ type Change struct {
|
||||||
// see this patten used in several tar'ing methods in pkg/archive.
|
// see this patten used in several tar'ing methods in pkg/archive.
|
||||||
|
|
||||||
// Changes returns the list of changes from the diff's parent.
|
// Changes returns the list of changes from the diff's parent.
|
||||||
func (lm *Manager) Changes(diff string) ([]Change, error) {
|
func (sm *Manager) Changes(diff string) ([]Change, error) {
|
||||||
panic("not implemented")
|
panic("not implemented")
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
// examples we've discussed thus far. It does perform mounts, so you must run
|
// examples we've discussed thus far. It does perform mounts, so you must run
|
||||||
// as root.
|
// as root.
|
||||||
func TestSnapshotManagerBasic(t *testing.T) {
|
func TestSnapshotManagerBasic(t *testing.T) {
|
||||||
tmpDir, err := ioutil.TempDir("", "test-layman-")
|
tmpDir, err := ioutil.TempDir("", "test-sm-")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ func TestSnapshotManagerBasic(t *testing.T) {
|
||||||
|
|
||||||
root := filepath.Join(tmpDir, "root")
|
root := filepath.Join(tmpDir, "root")
|
||||||
|
|
||||||
lm, err := NewManager(root)
|
sm, err := NewManager(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -38,7 +38,7 @@ func TestSnapshotManagerBasic(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mounts, err := lm.Prepare(preparing, "")
|
mounts, err := sm.Prepare(preparing, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -58,14 +58,14 @@ func TestSnapshotManagerBasic(t *testing.T) {
|
||||||
|
|
||||||
os.MkdirAll(preparing+"/a/b/c", 0755)
|
os.MkdirAll(preparing+"/a/b/c", 0755)
|
||||||
|
|
||||||
committed := filepath.Join(lm.root, "committed")
|
committed := filepath.Join(sm.root, "committed")
|
||||||
|
|
||||||
if err := lm.Commit(committed, preparing); err != nil {
|
if err := sm.Commit(committed, preparing); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if lm.Parent(preparing) != "" {
|
if sm.Parent(preparing) != "" {
|
||||||
t.Fatalf("parent of new layer should be empty, got lm.Parent(%q) == %q", preparing, lm.Parent(preparing))
|
t.Fatalf("parent of new layer should be empty, got sm.Parent(%q) == %q", preparing, sm.Parent(preparing))
|
||||||
}
|
}
|
||||||
|
|
||||||
next := filepath.Join(tmpDir, "nextlayer")
|
next := filepath.Join(tmpDir, "nextlayer")
|
||||||
|
@ -73,7 +73,7 @@ func TestSnapshotManagerBasic(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mounts, err = lm.Prepare(next, committed)
|
mounts, err = sm.Prepare(next, committed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -92,12 +92,12 @@ func TestSnapshotManagerBasic(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
os.RemoveAll(next + "/a/b")
|
os.RemoveAll(next + "/a/b")
|
||||||
nextCommitted := filepath.Join(lm.root, "committed-next")
|
nextCommitted := filepath.Join(sm.root, "committed-next")
|
||||||
if err := lm.Commit(nextCommitted, next); err != nil {
|
if err := sm.Commit(nextCommitted, next); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if lm.Parent(nextCommitted) != committed {
|
if sm.Parent(nextCommitted) != committed {
|
||||||
t.Fatalf("parent of new layer should be %q, got lm.Parent(%q) == %q (%#v)", committed, next, lm.Parent(next), lm.parents)
|
t.Fatalf("parent of new layer should be %q, got sm.Parent(%q) == %q (%#v)", committed, next, sm.Parent(next), sm.parents)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,8 +43,8 @@ func NewNaive(root string) (*Naive, error) {
|
||||||
//
|
//
|
||||||
// For the naive driver, the data is checked out directly into dst and no
|
// For the naive driver, the data is checked out directly into dst and no
|
||||||
// mounts are returned.
|
// mounts are returned.
|
||||||
func (lm *Naive) Prepare(dst, parent string) ([]containerd.Mount, error) {
|
func (n *Naive) Prepare(dst, parent string) ([]containerd.Mount, error) {
|
||||||
metadataRoot, err := ioutil.TempDir(lm.root, "active-")
|
metadataRoot, err := ioutil.TempDir(n.root, "active-")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.Wrap(err, "failed to created transaction dir")
|
return nil, errors.Wrap(err, "failed to created transaction dir")
|
||||||
}
|
}
|
||||||
|
@ -57,7 +57,7 @@ func (lm *Naive) Prepare(dst, parent string) ([]containerd.Mount, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if parent != "" {
|
if parent != "" {
|
||||||
if _, ok := lm.parents[parent]; !ok {
|
if _, ok := n.parents[parent]; !ok {
|
||||||
return nil, errors.Wrap(err, "specified parent does not exist")
|
return nil, errors.Wrap(err, "specified parent does not exist")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ func (lm *Naive) Prepare(dst, parent string) ([]containerd.Mount, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lm.active[dst] = activeNaiveSnapshot{
|
n.active[dst] = activeNaiveSnapshot{
|
||||||
parent: parent,
|
parent: parent,
|
||||||
metadata: metadataRoot,
|
metadata: metadataRoot,
|
||||||
}
|
}
|
||||||
|
@ -80,8 +80,8 @@ func (lm *Naive) Prepare(dst, parent string) ([]containerd.Mount, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit just moves the metadata directory to the diff location.
|
// Commit just moves the metadata directory to the diff location.
|
||||||
func (lm *Naive) Commit(diff, dst string) error {
|
func (n *Naive) Commit(diff, dst string) error {
|
||||||
active, ok := lm.active[dst]
|
active, ok := n.active[dst]
|
||||||
if !ok {
|
if !ok {
|
||||||
return errors.Errorf("%v is not an active transaction", dst)
|
return errors.Errorf("%v is not an active transaction", dst)
|
||||||
}
|
}
|
||||||
|
@ -96,22 +96,22 @@ func (lm *Naive) Commit(diff, dst string) error {
|
||||||
return errors.Wrap(err, "failed to rename metadata into diff")
|
return errors.Wrap(err, "failed to rename metadata into diff")
|
||||||
}
|
}
|
||||||
|
|
||||||
lm.parents[diff] = active.parent
|
n.parents[diff] = active.parent
|
||||||
delete(lm.active, dst)
|
delete(n.active, dst)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *Naive) Rollback(dst string) error {
|
func (n *Naive) Rollback(dst string) error {
|
||||||
active, ok := lm.active[dst]
|
active, ok := n.active[dst]
|
||||||
if !ok {
|
if !ok {
|
||||||
return fmt.Errorf("%q must be an active snapshot", dst)
|
return fmt.Errorf("%q must be an active snapshot", dst)
|
||||||
}
|
}
|
||||||
|
|
||||||
delete(lm.active, dst)
|
delete(n.active, dst)
|
||||||
return os.RemoveAll(active.metadata)
|
return os.RemoveAll(active.metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lm *Naive) Parent(diff string) string {
|
func (n *Naive) Parent(diff string) string {
|
||||||
return lm.parents[diff]
|
return n.parents[diff]
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSnapshotNaiveBasic(t *testing.T) {
|
func TestSnapshotNaiveBasic(t *testing.T) {
|
||||||
tmpDir, err := ioutil.TempDir("", "test-layman-")
|
tmpDir, err := ioutil.TempDir("", "test-naive-")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ func TestSnapshotNaiveBasic(t *testing.T) {
|
||||||
t.Log(tmpDir)
|
t.Log(tmpDir)
|
||||||
root := filepath.Join(tmpDir, "root")
|
root := filepath.Join(tmpDir, "root")
|
||||||
|
|
||||||
lm, err := NewNaive(root)
|
n, err := NewNaive(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -29,7 +29,7 @@ func TestSnapshotNaiveBasic(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mounts, err := lm.Prepare(preparing, "")
|
mounts, err := n.Prepare(preparing, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -46,14 +46,14 @@ func TestSnapshotNaiveBasic(t *testing.T) {
|
||||||
|
|
||||||
// defer os.Remove(filepath.Join(tmpDir, "foo"))
|
// defer os.Remove(filepath.Join(tmpDir, "foo"))
|
||||||
|
|
||||||
committed := filepath.Join(lm.root, "committed")
|
committed := filepath.Join(n.root, "committed")
|
||||||
|
|
||||||
if err := lm.Commit(committed, preparing); err != nil {
|
if err := n.Commit(committed, preparing); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if lm.Parent(preparing) != "" {
|
if n.Parent(preparing) != "" {
|
||||||
t.Fatalf("parent of new layer should be empty, got lm.Parent(%q) == %q", preparing, lm.Parent(preparing))
|
t.Fatalf("parent of new layer should be empty, got n.Parent(%q) == %q", preparing, n.Parent(preparing))
|
||||||
}
|
}
|
||||||
|
|
||||||
next := filepath.Join(tmpDir, "nextlayer")
|
next := filepath.Join(tmpDir, "nextlayer")
|
||||||
|
@ -61,7 +61,7 @@ func TestSnapshotNaiveBasic(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
mounts, err = lm.Prepare(next, committed)
|
mounts, err = n.Prepare(next, committed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -79,12 +79,12 @@ func TestSnapshotNaiveBasic(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
os.RemoveAll(next + "/a/b")
|
os.RemoveAll(next + "/a/b")
|
||||||
nextCommitted := filepath.Join(lm.root, "committed-next")
|
nextCommitted := filepath.Join(n.root, "committed-next")
|
||||||
if err := lm.Commit(nextCommitted, next); err != nil {
|
if err := n.Commit(nextCommitted, next); err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if lm.Parent(nextCommitted) != committed {
|
if n.Parent(nextCommitted) != committed {
|
||||||
t.Fatalf("parent of new layer should be %q, got lm.Parent(%q) == %q (%#v)", committed, next, lm.Parent(next), lm.parents)
|
t.Fatalf("parent of new layer should be %q, got n.Parent(%q) == %q (%#v)", committed, next, n.Parent(next), n.parents)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import (
|
||||||
"github.com/docker/containerd"
|
"github.com/docker/containerd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func NewOverlayfs(root string) (*Overlayfs, error) {
|
func NewOverlay(root string) (*Overlay, error) {
|
||||||
if err := os.MkdirAll(root, 0700); err != nil {
|
if err := os.MkdirAll(root, 0700); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -24,18 +24,18 @@ func NewOverlayfs(root string) (*Overlayfs, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &Overlayfs{
|
return &Overlay{
|
||||||
root: root,
|
root: root,
|
||||||
cache: newCache(),
|
cache: newCache(),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type Overlayfs struct {
|
type Overlay struct {
|
||||||
root string
|
root string
|
||||||
cache *cache
|
cache *cache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Overlayfs) Prepare(key string, parentName string) ([]containerd.Mount, error) {
|
func (o *Overlay) Prepare(key string, parentName string) ([]containerd.Mount, error) {
|
||||||
if err := validKey(key); err != nil {
|
if err := validKey(key); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -51,12 +51,12 @@ func (o *Overlayfs) Prepare(key string, parentName string) ([]containerd.Mount,
|
||||||
return active.mounts(o.cache)
|
return active.mounts(o.cache)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Overlayfs) Commit(name, key string) error {
|
func (o *Overlay) Commit(name, key string) error {
|
||||||
active := o.getActive(key)
|
active := o.getActive(key)
|
||||||
return active.commit(name)
|
return active.commit(name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Overlayfs) newActiveDir(key string) (*activeDir, error) {
|
func (o *Overlay) newActiveDir(key string) (*activeDir, error) {
|
||||||
var (
|
var (
|
||||||
hash = hash(key)
|
hash = hash(key)
|
||||||
path = filepath.Join(o.root, "active", hash)
|
path = filepath.Join(o.root, "active", hash)
|
||||||
|
@ -77,7 +77,7 @@ func (o *Overlayfs) newActiveDir(key string) (*activeDir, error) {
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *Overlayfs) getActive(key string) *activeDir {
|
func (o *Overlay) getActive(key string) *activeDir {
|
||||||
return &activeDir{
|
return &activeDir{
|
||||||
path: filepath.Join(o.root, "active", hash(key)),
|
path: filepath.Join(o.root, "active", hash(key)),
|
||||||
snapshotsDir: filepath.Join(o.root, "snapshots"),
|
snapshotsDir: filepath.Join(o.root, "snapshots"),
|
|
@ -10,13 +10,13 @@ import (
|
||||||
"github.com/docker/containerd"
|
"github.com/docker/containerd"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestOverlayfs(t *testing.T) {
|
func TestOverlay(t *testing.T) {
|
||||||
root, err := ioutil.TempDir("", "overlay")
|
root, err := ioutil.TempDir("", "overlay")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(root)
|
defer os.RemoveAll(root)
|
||||||
o, err := NewOverlayfs(root)
|
o, err := NewOverlay(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
@ -45,13 +45,13 @@ func TestOverlayfs(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOverlayfsCommit(t *testing.T) {
|
func TestOverlayCommit(t *testing.T) {
|
||||||
root, err := ioutil.TempDir("", "overlay")
|
root, err := ioutil.TempDir("", "overlay")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(root)
|
defer os.RemoveAll(root)
|
||||||
o, err := NewOverlayfs(root)
|
o, err := NewOverlay(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
@ -73,13 +73,13 @@ func TestOverlayfsCommit(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOverlayfsOverlayMount(t *testing.T) {
|
func TestOverlayOverlayMount(t *testing.T) {
|
||||||
root, err := ioutil.TempDir("", "overlay")
|
root, err := ioutil.TempDir("", "overlay")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(root)
|
defer os.RemoveAll(root)
|
||||||
o, err := NewOverlayfs(root)
|
o, err := NewOverlay(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
||||||
|
@ -125,7 +125,7 @@ func TestOverlayfsOverlayMount(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestOverlayfsOverlayRead(t *testing.T) {
|
func TestOverlayOverlayRead(t *testing.T) {
|
||||||
if os.Getuid() != 0 {
|
if os.Getuid() != 0 {
|
||||||
t.Skip("not running as root")
|
t.Skip("not running as root")
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ func TestOverlayfsOverlayRead(t *testing.T) {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
defer os.RemoveAll(root)
|
defer os.RemoveAll(root)
|
||||||
o, err := NewOverlayfs(root)
|
o, err := NewOverlay(root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Error(err)
|
t.Error(err)
|
||||||
return
|
return
|
Loading…
Reference in a new issue