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

Add path prepending support #79

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,6 @@ website/vendor
# Test exclusions
!command/test-fixtures/**/*.tfstate
!command/test-fixtures/**/.terraform/

# Archives generated by tests
internal/provider/*.zip
Binary file removed internal/provider/archive-content.zip
Binary file not shown.
Binary file removed internal/provider/archive-dir.zip
Binary file not shown.
Binary file removed internal/provider/archive-file.zip
Binary file not shown.
4 changes: 2 additions & 2 deletions internal/provider/archiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import (

type Archiver interface {
ArchiveContent(content []byte, infilename string) error
ArchiveFile(infilename string) error
ArchiveDir(indirname string, excludes []string) error
ArchiveFile(prepath string, infilename string) error
ArchiveDir(prepath string, indirname string, excludes []string) error
ArchiveMultiple(content map[string][]byte) error
}

Expand Down
17 changes: 14 additions & 3 deletions internal/provider/data_source_archive_file.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,12 @@ func dataSourceFile() *schema.Resource {
Type: schema.TypeString,
},
},
"prepended_path": {
Type: schema.TypeString,
Optional: true,
ForceNew: true,
ConflictsWith: []string{"source_content", "source_content_filename", "source_file"},
},
"output_path": {
Type: schema.TypeString,
Required: true,
Expand Down Expand Up @@ -171,20 +177,25 @@ func archive(d *schema.ResourceData) error {
return fmt.Errorf("archive type not supported: %s", archiveType)
}

var prepath string
if prepended_path, ok := d.GetOk("prepended_path"); ok {
prepath = prepended_path.(string)
}

if dir, ok := d.GetOk("source_dir"); ok {
if excludes, ok := d.GetOk("excludes"); ok {
excludeList := expandStringList(excludes.(*schema.Set).List())

if err := archiver.ArchiveDir(dir.(string), excludeList); err != nil {
if err := archiver.ArchiveDir(prepath, dir.(string), excludeList); err != nil {
return fmt.Errorf("error archiving directory: %s", err)
}
} else {
if err := archiver.ArchiveDir(dir.(string), []string{""}); err != nil {
if err := archiver.ArchiveDir(prepath, dir.(string), []string{""}); err != nil {
return fmt.Errorf("error archiving directory: %s", err)
}
}
} else if file, ok := d.GetOk("source_file"); ok {
if err := archiver.ArchiveFile(file.(string)); err != nil {
if err := archiver.ArchiveFile(prepath, file.(string)); err != nil {
return fmt.Errorf("error archiving file: %s", err)
}
} else if filename, ok := d.GetOk("source_content_filename"); ok {
Expand Down
18 changes: 18 additions & 0 deletions internal/provider/data_source_archive_file_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,13 @@ func TestAccArchiveFile_Basic(t *testing.T) {
r.TestCheckResourceAttrPtr("data.archive_file.foo", "output_size", &fileSize),
),
},
{
Config: testAccArchiveFilePrependPath(f),
Check: r.ComposeTestCheckFunc(
testAccArchiveFileExists(f, &fileSize),
r.TestCheckResourceAttrPtr("data.archive_file.foo", "output_size", &fileSize),
),
},
},
})
}
Expand Down Expand Up @@ -144,6 +151,17 @@ data "archive_file" "foo" {
`, filepath.ToSlash(outputPath))
}

func testAccArchiveFilePrependPath(outputPath string) string {
return fmt.Sprintf(`
data "archive_file" "foo" {
type = "zip"
source_dir = "test-fixtures/test-dir"
prepended_path = "pre-dir"
output_path = "%s"
}
`, filepath.ToSlash(outputPath))
}

func testTempDir(t *testing.T) string {
tmp, err := ioutil.TempDir("", "tf")
if err != nil {
Expand Down
14 changes: 8 additions & 6 deletions internal/provider/zip_archiver.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@ import (
"fmt"
"io/ioutil"
"os"
"path"
"path/filepath"
"sort"
"time"
)

type ZipArchiver struct {
prepath string
filepath string
filewriter *os.File
writer *zip.Writer
Expand All @@ -37,7 +39,7 @@ func (a *ZipArchiver) ArchiveContent(content []byte, infilename string) error {
return err
}

func (a *ZipArchiver) ArchiveFile(infilename string) error {
func (a *ZipArchiver) ArchiveFile(prepath string, infilename string) error {
fi, err := assertValidFile(infilename)
if err != nil {
return err
Expand Down Expand Up @@ -84,7 +86,7 @@ func checkMatch(fileName string, excludes []string) (value bool) {
return false
}

func (a *ZipArchiver) ArchiveDir(indirname string, excludes []string) error {
func (a *ZipArchiver) ArchiveDir(prepath string, indirname string, excludes []string) error {
_, err := assertValidDir(indirname)
if err != nil {
return err
Expand All @@ -100,13 +102,13 @@ func (a *ZipArchiver) ArchiveDir(indirname string, excludes []string) error {
}
defer a.close()

return filepath.Walk(indirname, func(path string, info os.FileInfo, err error) error {
return filepath.Walk(indirname, func(file_path string, info os.FileInfo, err error) error {

if err != nil {
return fmt.Errorf("error encountered during file walk: %s", err)
}

relname, err := filepath.Rel(indirname, path)
relname, err := filepath.Rel(indirname, file_path)
if err != nil {
return fmt.Errorf("error relativizing file for archival: %s", err)
}
Expand All @@ -132,7 +134,7 @@ func (a *ZipArchiver) ArchiveDir(indirname string, excludes []string) error {
if err != nil {
return fmt.Errorf("error creating file header: %s", err)
}
fh.Name = filepath.ToSlash(relname)
fh.Name = path.Join(prepath, filepath.ToSlash(relname))
fh.Method = zip.Deflate
// fh.Modified alone isn't enough when using a zero value
fh.SetModTime(time.Time{})
Expand All @@ -141,7 +143,7 @@ func (a *ZipArchiver) ArchiveDir(indirname string, excludes []string) error {
if err != nil {
return fmt.Errorf("error creating file inside archive: %s", err)
}
content, err := ioutil.ReadFile(path)
content, err := ioutil.ReadFile(file_path)
if err != nil {
return fmt.Errorf("error reading file for archival: %s", err)
}
Expand Down
26 changes: 21 additions & 5 deletions internal/provider/zip_archiver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"bytes"
"io/ioutil"
"os"
"path"
"path/filepath"
"testing"
"time"
Expand All @@ -25,7 +26,7 @@ func TestZipArchiver_Content(t *testing.T) {
func TestZipArchiver_File(t *testing.T) {
zipfilepath := "archive-file.zip"
archiver := NewZipArchiver(zipfilepath)
if err := archiver.ArchiveFile("./test-fixtures/test-file.txt"); err != nil {
if err := archiver.ArchiveFile("", "./test-fixtures/test-file.txt"); err != nil {
t.Fatalf("unexpected error: %s", err)
}

Expand All @@ -41,7 +42,7 @@ func TestZipArchiver_FileModified(t *testing.T) {

var zip = func() {
archiver := NewZipArchiver(zipFilePath)
if err := archiver.ArchiveFile(toZipPath); err != nil {
if err := archiver.ArchiveFile("", toZipPath); err != nil {
t.Fatalf("unexpected error: %s", err)
}
}
Expand Down Expand Up @@ -74,7 +75,7 @@ func TestZipArchiver_FileModified(t *testing.T) {
func TestZipArchiver_Dir(t *testing.T) {
zipfilepath := "archive-dir.zip"
archiver := NewZipArchiver(zipfilepath)
if err := archiver.ArchiveDir("./test-fixtures/test-dir", []string{""}); err != nil {
if err := archiver.ArchiveDir("", "./test-fixtures/test-dir", []string{""}); err != nil {
t.Fatalf("unexpected error: %s", err)
}

Expand All @@ -88,7 +89,7 @@ func TestZipArchiver_Dir(t *testing.T) {
func TestZipArchiver_Dir_Exclude(t *testing.T) {
zipfilepath := "archive-dir.zip"
archiver := NewZipArchiver(zipfilepath)
if err := archiver.ArchiveDir("./test-fixtures/test-dir", []string{"file2.txt"}); err != nil {
if err := archiver.ArchiveDir("", "./test-fixtures/test-dir", []string{"file2.txt"}); err != nil {
t.Fatalf("unexpected error: %s", err)
}

Expand All @@ -101,7 +102,7 @@ func TestZipArchiver_Dir_Exclude(t *testing.T) {
func TestZipArchiver_Dir_Exclude_With_Directory(t *testing.T) {
zipfilepath := "archive-dir.zip"
archiver := NewZipArchiver(zipfilepath)
if err := archiver.ArchiveDir("./test-fixtures/", []string{"test-dir", "test-dir2/file2.txt"}); err != nil {
if err := archiver.ArchiveDir("", "./test-fixtures/", []string{"test-dir", "test-dir2/file2.txt"}); err != nil {
t.Fatalf("unexpected error: %s", err)
}

Expand Down Expand Up @@ -129,6 +130,21 @@ func TestZipArchiver_Multiple(t *testing.T) {

}

func TestZipArchiver_Prepend_Path(t *testing.T) {
prepended_path := "prepath"
zipfilepath := "archive-pre-path.zip"
archiver := NewZipArchiver(zipfilepath)
if err := archiver.ArchiveDir(prepended_path, "./test-fixtures/", []string{"test-dir", "test-dir2/file2.txt"}); err != nil {
t.Fatalf("unexpected error: %s", err)
}

ensureContents(t, zipfilepath, map[string][]byte{
path.Join(prepended_path, "test-dir2/file1.txt"): []byte("This is file 1"),
path.Join(prepended_path, "test-dir2/file3.txt"): []byte("This is file 3"),
path.Join(prepended_path, "test-file.txt"): []byte("This is test content"),
})
}

func ensureContents(t *testing.T, zipfilepath string, wants map[string][]byte) {
r, err := zip.OpenReader(zipfilepath)
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions website/docs/d/archive_file.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ NOTE: One of `source`, `source_content_filename` (with `source_content`), `sourc

* `excludes` - (Optional) Specify files to ignore when reading the `source_dir`.

* `prepended_path` - (Optional) Specifies the path prefix to prepend to `source_file` or `source_dir` in the archive path.

The `source` block supports the following:

* `content` - (Required) Add this content to the archive with `filename` as the filename.
Expand Down