mirror of
https://github.com/siderolabs/talos.git
synced 2025-08-22 23:21:11 +02:00
Actual API is implemented in the `init`, as it has access to root filesystem. `osd` proxies API back to `init` with some tricks to support grpc streaming. Given some absolute path, `init` produces and streams back .tar.gz archive with filesystem contents. `osctl cp` works in two modes. First mode streams data to stdout, so that we can do e.g.: `osctl cp /etc - | tar tz`. Second mode extracts archive to specified location, dropping ownership info and adjusting permissions a bit. Timestamps are not preserved. If full dump with owner/permisisons is required, it's better to stream data to `tar xz`, for quick and dirty look into filesystem contents under unprivileged user it's easier to use in-place extraction. Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
116 lines
2.6 KiB
Go
116 lines
2.6 KiB
Go
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
// Package archiver provides a service to archive part of the filesystem into tar archive
|
|
package archiver_test
|
|
|
|
import (
|
|
"archive/tar"
|
|
"bytes"
|
|
"context"
|
|
"io"
|
|
"io/ioutil"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/suite"
|
|
"github.com/talos-systems/talos/internal/pkg/archiver"
|
|
)
|
|
|
|
type TarSuite struct {
|
|
CommonSuite
|
|
}
|
|
|
|
//nolint: gocyclo
|
|
func (suite *TarSuite) TestArchiveDir() {
|
|
ch, errCh, err := archiver.Walker(context.Background(), suite.tmpDir)
|
|
suite.Require().NoError(err)
|
|
|
|
var buf bytes.Buffer
|
|
|
|
err = archiver.Tar(context.Background(), ch, &buf)
|
|
suite.Require().NoError(err)
|
|
suite.Require().NoError(<-errCh)
|
|
|
|
pathsSeen := map[string]struct{}{}
|
|
|
|
tr := tar.NewReader(&buf)
|
|
for {
|
|
hdr, err := tr.Next()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
suite.Require().NoError(err)
|
|
|
|
if hdr.Typeflag == tar.TypeDir {
|
|
continue
|
|
}
|
|
|
|
contents, err := ioutil.ReadAll(tr)
|
|
suite.Require().NoError(err)
|
|
|
|
found := false
|
|
for _, fi := range filesFixture {
|
|
if fi.Path[1:] == hdr.Name {
|
|
found = true
|
|
pathsSeen[fi.Path] = struct{}{}
|
|
|
|
switch {
|
|
case fi.Mode&os.ModeSymlink != 0:
|
|
suite.Require().Equal(string(fi.Contents), hdr.Linkname)
|
|
case fi.Size > 0:
|
|
suite.Require().Len(contents, fi.Size)
|
|
case fi.Contents != nil:
|
|
suite.Require().EqualValues(fi.Contents, contents)
|
|
default:
|
|
suite.Require().Len(contents, 0)
|
|
}
|
|
}
|
|
}
|
|
|
|
suite.Require().True(found, "file %q", hdr.Name)
|
|
}
|
|
|
|
for _, fi := range filesFixture {
|
|
_, ok := pathsSeen[fi.Path]
|
|
suite.Require().True(ok, "path %q", fi.Path)
|
|
}
|
|
}
|
|
|
|
func (suite *TarSuite) TestArchiveFile() {
|
|
ch, errCh, err := archiver.Walker(context.Background(), filepath.Join(suite.tmpDir, "/usr/bin/cp"))
|
|
suite.Require().NoError(err)
|
|
|
|
var buf bytes.Buffer
|
|
|
|
err = archiver.Tar(context.Background(), ch, &buf)
|
|
suite.Require().NoError(err)
|
|
suite.Require().NoError(<-errCh)
|
|
|
|
tr := tar.NewReader(&buf)
|
|
for {
|
|
hdr, err := tr.Next()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
suite.Require().NoError(err)
|
|
|
|
expectedContents := []byte("ELF EXECUTABLE IIRC")
|
|
|
|
suite.Require().EqualValues(hdr.Typeflag, tar.TypeReg)
|
|
suite.Require().EqualValues(hdr.Name, "cp")
|
|
suite.Require().EqualValues(hdr.Size, len(expectedContents))
|
|
|
|
contents, err := ioutil.ReadAll(tr)
|
|
suite.Require().NoError(err)
|
|
|
|
suite.Require().Equal(expectedContents, contents)
|
|
}
|
|
}
|
|
|
|
func TestTarSuite(t *testing.T) {
|
|
suite.Run(t, new(TarSuite))
|
|
}
|