-
Notifications
You must be signed in to change notification settings - Fork 64
Description
Terraform CLI and Provider Versions
All Terraform versions covered by the CI test suite (0.12.31
, 0.13.7
, 0.14.11
, 0.15.1
).
Terraform Configuration
data "archive_file" "foo" {
type = "zip"
source_dir = "${path.module}/foo"
output_path = "${path.module}/foo/bar.zip"
}
Expected Behavior
The output archive bar.zip
's contents should exactly replicate the files contained in /foo
prior to Terraform execution.
For example, if the /foo
directory structure looks like:
/foo
- baz.txt
then the expected output archive contents should look like:
/foo
- baz.txt
Specifically, if the /foo
source directory does not contain an empty file named bar.zip
prior to Terraform execution, then the output archive bar.zip
's contents should also not contain an empty file named bar.zip
.
Also, ideally, if the /foo
source directory does contain a file named bar.zip
prior to Terraform execution, then the output archive bar.zip
's contents should also contain a file named bar.zip
with the same file contents.
Actual Behavior
The output archive bar.zip
's contents includes an extra (empty) file named bar.zip
.
For example, if the /foo
directory structure looks like:
/foo
- baz.txt
then the actual output archive contents looks like:
/foo
- bar.zip
- baz.txt
Steps to Reproduce
This can be replicated with an extra unit test in internal/provider/zip_archiver_test.go
:
func TestZipArchiver_Dir_OutputSameDir(t *testing.T) {
zipfilepath := "./test-fixtures/test-dir/archive-dir.zip"
archiver := NewZipArchiver(zipfilepath)
defer os.Remove(zipfilepath)
if err := archiver.ArchiveDir("./test-fixtures/test-dir", []string{""}); err != nil {
t.Fatalf("unexpected error: %s", err)
}
ensureContents(t, zipfilepath, map[string][]byte{
"file1.txt": []byte("This is file 1"),
"file2.txt": []byte("This is file 2"),
"file3.txt": []byte("This is file 3"),
})
}
which produces the following test output:
$ go test -v -cover ./internal/provider/
...
=== RUN TestZipArchiver_FileModified
--- PASS: TestZipArchiver_FileModified (0.00s)
=== RUN TestZipArchiver_Dir
--- PASS: TestZipArchiver_Dir (0.00s)
=== RUN TestZipArchiver_Dir_OutputSameDir
zip_archiver_test.go:121: mismatched file count, got 4, want 3
zip_archiver_test.go:121: additional file in zip: archive-dir.zip
=== RUN TestZipArchiver_Dir_Exclude
--- PASS: TestZipArchiver_Dir_Exclude (0.00s)
=== RUN TestZipArchiver_Dir_Exclude_With_Directory
--- PASS: TestZipArchiver_Dir_Exclude_With_Directory (0.00s)
How much impact is this issue causing?
Medium
Logs
No response
Additional Information
The reason this bug occurs is because in the ArchiveDir()
implementation (see internal/provider/zip_archiver.go
), a.open()
is called before filepath.Walk()
.
a.open()
calls os.Create(a.filepath)
and therefore creates the empty file in the source directory. filepath.Walk()
then proceeds to iterate through the source directory including this new empty file.
Potential solutions
-
Replace
os.Create(a.filepath)
withos.CreateTemp("", "*.zip")
to initially build the archive file in a temporary location. Once built, callos.Rename()
(orio.Copy()
plusos.Remove()
) to move the archive file to the target path. -
Dynamically append the output path
a.filepath
to the excludes list, so that it will exclude itself. (However, this solution won't handle the scenario when there is a legitimate source file at patha.filepath
that needs to be included.)
Code of Conduct
- I agree to follow this project's Code of Conduct