Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 2 additions & 0 deletions fileutil/compressor_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ type Compressor interface {

DecompressFileToDir(path string, dir string, options CompressorOptions) (err error)

IsNonCompressedTarball(path string) (bool, error)

// CleanUp cleans up compressed file after it was used
CleanUp(path string) error
}
4 changes: 4 additions & 0 deletions fileutil/fakes/fake_compressor.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ func (fc *FakeCompressor) DecompressFileToDir(tarballPath string, dir string, op
return fc.DecompressFileToDirErr
}

func (fc *FakeCompressor) IsNonCompressedTarball(path string) (bool, error) {
return false, nil
}

func (fc *FakeCompressor) CleanUp(tarballPath string) error {
fc.CleanUpTarballPath = tarballPath
return fc.CleanUpErr
Expand Down
11 changes: 11 additions & 0 deletions fileutil/tarball_compressor.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package fileutil
import (
"fmt"
"runtime"
"strings"

bosherr "github.com/cloudfoundry/bosh-utils/errors"
boshsys "github.com/cloudfoundry/bosh-utils/system"
Expand Down Expand Up @@ -80,6 +81,16 @@ func (c tarballCompressor) DecompressFileToDir(tarballPath string, dir string, o
return nil
}

func (c tarballCompressor) IsNonCompressedTarball(path string) (bool, error) {
stdout, _, exitStatus, err := c.cmdRunner.RunCommand("file", path)
Copy link
Member

Choose a reason for hiding this comment

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

I think that this will need to be implemented in Golang, rather than using file, or have a separate path for windows.
The agent needs to be able to function on Windows stemcells.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If this is ran on a windows stemcell the file command will not be found and the cmdRunner will simply return an error. That is completely fine - the tar will be treated as compressed so same behavior as today.

This would work even if the tar was originally created with the --no-compression flag. On Windows, we'd compress it again after compilation which is not a big deal.

Copy link
Member

Choose a reason for hiding this comment

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

I agree that this is the likely outcome but I don't want to introduce a(nother) behavior difference between Linux and Windows.
Probably the cleanest option is to use a golang-native way to do this rather than shelling out to file.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Agreed. Updated the PR to detect the tar compression natively.
Tested the with bosh-agent compile on the latest lite stemcell.

if err != nil || exitStatus != 0 {
return false, err
}

fileOutputStr := strings.TrimSpace(stdout)
return strings.Contains(fileOutputStr, "POSIX tar archive"), nil
}

func (c tarballCompressor) CleanUp(tarballPath string) error {
return c.fs.RemoveAll(tarballPath)
}
118 changes: 118 additions & 0 deletions fileutil/tarball_compressor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,124 @@ var _ = Describe("tarballCompressor", func() {
})
})

Describe("IsNonCompressedTarball", func() {
It("returns true for non-compressed tarball files", func() {
cmdRunner := fakesys.NewFakeCmdRunner()
compressor := NewTarballCompressor(cmdRunner, fs)

// Mock the file command output for a non-compressed tarball
cmdRunner.AddCmdResult("file /test/file.tar", fakesys.FakeCmdResult{
Stdout: "/test/file.tar: POSIX tar archive\n",
Stderr: "",
ExitStatus: 0,
})

result, err := compressor.IsNonCompressedTarball("/test/file.tar")
Expect(err).ToNot(HaveOccurred())
Expect(result).To(BeTrue())

Expect(1).To(Equal(len(cmdRunner.RunCommands)))
Expect(cmdRunner.RunCommands[0]).To(Equal([]string{"file", "/test/file.tar"}))
})

It("returns false for compressed tarball files", func() {
cmdRunner := fakesys.NewFakeCmdRunner()
compressor := NewTarballCompressor(cmdRunner, fs)

// Mock the file command output for a compressed tarball
cmdRunner.AddCmdResult("file /test/file.tgz", fakesys.FakeCmdResult{
Stdout: "/test/file.tgz: gzip compressed data, from Unix, original size modulo 2^32 1024\n",
Stderr: "",
ExitStatus: 0,
})

result, err := compressor.IsNonCompressedTarball("/test/file.tgz")
Expect(err).ToNot(HaveOccurred())
Expect(result).To(BeFalse())

Expect(1).To(Equal(len(cmdRunner.RunCommands)))
Expect(cmdRunner.RunCommands[0]).To(Equal([]string{"file", "/test/file.tgz"}))
})

It("returns false for non-tarball files", func() {
cmdRunner := fakesys.NewFakeCmdRunner()
compressor := NewTarballCompressor(cmdRunner, fs)

// Mock the file command output for a regular text file
cmdRunner.AddCmdResult("file /test/file.txt", fakesys.FakeCmdResult{
Stdout: "/test/file.txt: ASCII text\n",
Stderr: "",
ExitStatus: 0,
})

result, err := compressor.IsNonCompressedTarball("/test/file.txt")
Expect(err).ToNot(HaveOccurred())
Expect(result).To(BeFalse())

Expect(1).To(Equal(len(cmdRunner.RunCommands)))
Expect(cmdRunner.RunCommands[0]).To(Equal([]string{"file", "/test/file.txt"}))
})

It("returns error when file command fails", func() {
cmdRunner := fakesys.NewFakeCmdRunner()
compressor := NewTarballCompressor(cmdRunner, fs)

// Mock the file command to return an error
cmdRunner.AddCmdResult("file /test/nonexistent.tar", fakesys.FakeCmdResult{
Stdout: "",
Stderr: "file: cannot open `/test/nonexistent.tar' (No such file or directory)\n",
ExitStatus: 1,
})

result, err := compressor.IsNonCompressedTarball("/test/nonexistent.tar")
Expect(err).To(HaveOccurred())
Expect(result).To(BeFalse())

Expect(1).To(Equal(len(cmdRunner.RunCommands)))
Expect(cmdRunner.RunCommands[0]).To(Equal([]string{"file", "/test/nonexistent.tar"}))
})

It("returns error when file command execution fails", func() {
cmdRunner := fakesys.NewFakeCmdRunner()
compressor := NewTarballCompressor(cmdRunner, fs)

// Mock the file command to return an execution error
cmdRunner.AddCmdResult("file /test/file.tar", fakesys.FakeCmdResult{
Stdout: "",
Stderr: "",
ExitStatus: 0,
Error: errors.New("command execution failed"),
})

result, err := compressor.IsNonCompressedTarball("/test/file.tar")
Expect(err).To(HaveOccurred())
Expect(err.Error()).To(ContainSubstring("command execution failed"))
Expect(result).To(BeFalse())

Expect(1).To(Equal(len(cmdRunner.RunCommands)))
Expect(cmdRunner.RunCommands[0]).To(Equal([]string{"file", "/test/file.tar"}))
})

It("handles file command output with extra whitespace", func() {
cmdRunner := fakesys.NewFakeCmdRunner()
compressor := NewTarballCompressor(cmdRunner, fs)

// Mock the file command output with extra whitespace
cmdRunner.AddCmdResult("file /test/file.tar", fakesys.FakeCmdResult{
Stdout: " /test/file.tar: POSIX tar archive \n",
Stderr: "",
ExitStatus: 0,
})

result, err := compressor.IsNonCompressedTarball("/test/file.tar")
Expect(err).ToNot(HaveOccurred())
Expect(result).To(BeTrue())

Expect(1).To(Equal(len(cmdRunner.RunCommands)))
Expect(cmdRunner.RunCommands[0]).To(Equal([]string{"file", "/test/file.tar"}))
})
})

Describe("CleanUp", func() {
It("removes tarball path", func() {
fs := fakesys.NewFakeFileSystem()
Expand Down
Loading