Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bugfix: populate volume error #2087

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 3 additions & 9 deletions daemon/mgr/container_storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@ import (
"fmt"
"io/ioutil"
"os"
"os/exec"
"path"
"path/filepath"
"regexp"
"strconv"

"github.com/alibaba/pouch/apis/opts"
"github.com/alibaba/pouch/apis/types"
"github.com/alibaba/pouch/pkg/archive"
"github.com/alibaba/pouch/pkg/errtypes"
"github.com/alibaba/pouch/pkg/randomid"
"github.com/alibaba/pouch/pkg/system"
Expand Down Expand Up @@ -672,15 +672,9 @@ func copyImageContent(source, destination string) error {
return err
}
if len(dstList) == 0 {
// TODO: refactor

// If the source volume is empty, copies files from the root into the volume
commandLine := fmt.Sprintf("cp -r %s/* %s", source, destination)

cmd := exec.Command("sh", "-c", commandLine)
out, err := cmd.CombinedOutput()
err := archive.CopyWithTar(source, destination)
if err != nil {
logrus.Errorf("copyImageContent: %s, %v", string(out), err)
logrus.Errorf("copyImageContent: %v", err)
return err
}
}
Expand Down
116 changes: 116 additions & 0 deletions pkg/archive/archive.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
package archive
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add unit-test for this package, thanks a lot!


import (
"archive/tar"
"bytes"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)

func tarFromDir(src string, writer io.Writer) error {
// ensure the src actually exists before trying to tar it
if _, err := os.Stat(src); err != nil {
return fmt.Errorf("failed to stat source file %s: %v", src, err)
}

tw := tar.NewWriter(writer)
defer tw.Close()

// walk path
return filepath.Walk(src, func(file string, fi os.FileInfo, err error) error {
if err != nil {
return err
}

// create a new dir/file header
header, err := tar.FileInfoHeader(fi, fi.Name())
if err != nil {
return err
}

// update the name to correctly reflect the desired destination when untaring
header.Name = strings.TrimPrefix(strings.Replace(file, src, "", 1), string(filepath.Separator))
// write the header
if err := tw.WriteHeader(header); err != nil {
return err
}

if !fi.Mode().IsRegular() {
return nil
}

// open files for taring
f, err := os.Open(file)
if err != nil {
return err
}
defer f.Close()

// copy file data into tar writer
if _, err := io.Copy(tw, f); err != nil {
return err
}

return nil
})
}

func untarToDir(dst string, r io.Reader) error {
tr := tar.NewReader(r)

for {
header, err := tr.Next()

switch {
case err == io.EOF:
return nil
case err != nil:
return err
case header == nil:
continue
}

// the target location where the dir/file should be created
target := filepath.Join(dst, header.Name)

// check the file type
switch header.Typeflag {
case tar.TypeDir:
if _, err := os.Stat(target); err != nil {
if err := os.MkdirAll(target, 0755); err != nil {
return err
}
}
case tar.TypeReg:
f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode))
if err != nil {
return err
}
defer f.Close()

if _, err := io.Copy(f, tr); err != nil {
return err
}
}
}
}

// CopyWithTar create a tar from src directory,
// and untar it in dst directory.
func CopyWithTar(src, dst string) error {
buf := new(bytes.Buffer)

if err := tarFromDir(src, buf); err != nil {
return err
}

if err := untarToDir(dst, buf); err != nil {
return err
}

return nil

}
79 changes: 79 additions & 0 deletions pkg/archive/archive_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
package archive

import (
"io/ioutil"
"os"
"path"
"path/filepath"
"strings"
"testing"

"github.com/alibaba/pouch/pkg/utils"
)

func TestCopyWithTar(t *testing.T) {
source, err := ioutil.TempDir("", "source")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(source)

destination, err := ioutil.TempDir("", "destination")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(destination)

files := []string{"file1", "file2", "dir1/file3", "dir2/file4"}

err = makeFiles(source, files)
if err != nil {
t.Fatal(err)
}

err = CopyWithTar(source, destination)
if err != nil {
t.Fatal(err)
}
actualFiles := targetFiles(destination)

if !utils.StringSliceEqual(files, actualFiles) {
t.Fatalf(" TestCopyWithTar expected get %v, but got %v", files, actualFiles)
}
}

func makeFiles(baseDir string, files []string) error {
for _, file := range files {
fullPath := path.Join(baseDir, file)

dir := path.Dir(fullPath)

// create dir.
err := os.MkdirAll(dir, 0755)
if err != nil {
return err
}

// create file.
fi, err := os.Create(fullPath)
if err != nil {
return err
}
fi.Close()
}

return nil
}

func targetFiles(baseDir string) []string {
files := []string{}

filepath.Walk(baseDir, func(name string, fi os.FileInfo, err error) error {
if fi.Mode().IsRegular() {
files = append(files, strings.TrimPrefix(name, baseDir+"/"))
}
return nil
})

return files
}
29 changes: 29 additions & 0 deletions pkg/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,3 +301,32 @@ func IsFileExist(file string) bool {

return false
}

// StringSliceEqual compare two string slice, ignore the order.
func StringSliceEqual(s1, s2 []string) bool {
if s1 == nil && s2 == nil {
return true
}

if s1 == nil || s2 == nil {
return false
}

if len(s1) != len(s2) {
return false
}

for _, s := range s1 {
if !StringInSlice(s2, s) {
return false
}
}

for _, s := range s2 {
if !StringInSlice(s1, s) {
return false
}
}

return true
}
21 changes: 21 additions & 0 deletions pkg/utils/utils_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -523,3 +523,24 @@ func TestIsFileExist(t *testing.T) {
assert.Equal(IsFileExist(t.path), t.exist)
}
}

func TestStringSliceEqual(t *testing.T) {
tests := []struct {
s1 []string
s2 []string
equal bool
}{
{nil, nil, true},
{nil, []string{"a"}, false},
{[]string{"a"}, []string{"a"}, true},
{[]string{"a"}, []string{"b", "a"}, false},
{[]string{"a", "b"}, []string{"b", "a"}, true},
}

for _, test := range tests {
result := StringSliceEqual(test.s1, test.s2)
if result != test.equal {
t.Fatalf("StringSliceEqual(%v, %v) expected: %v, but got %v", test.s1, test.s2, test.equal, result)
}
}
}