diff --git a/internal/provider/resource_archive_file_test.go b/internal/provider/resource_archive_file_test.go index 9e9ce08e..84f6c71d 100644 --- a/internal/provider/resource_archive_file_test.go +++ b/internal/provider/resource_archive_file_test.go @@ -1041,6 +1041,379 @@ func TestResource_ArchiveFile_SymlinkFile_Absolute_ExcludeSymlinkDirectories(t * }) } +// TestResource_ArchiveFile_SymlinkDirectory_Relative_ExcludeSymlinkDirectories verifies that an empty archive +// is generated when trying to archive a directory which only contains a symlink to a directory. +func TestResource_ArchiveFile_SymlinkDirectory_Relative_ExcludeSymlinkDirectories(t *testing.T) { + td := t.TempDir() + + f := filepath.Join(td, "zip_file_acc_test.zip") + + r.ParallelTest(t, r.TestCase{ + ProtoV5ProviderFactories: protoV5ProviderFactories(), + Steps: []r.TestStep{ + { + Config: fmt.Sprintf(` + resource "archive_file" "foo" { + type = "zip" + source_dir = "%s" + output_path = "%s" + output_file_mode = "0666" + exclude_symlink_directories = true + } + `, filepath.ToSlash("test-fixtures/test-symlink-dir"), filepath.ToSlash(f)), + ExpectError: regexp.MustCompile(`.*error creating archive: error archiving directory: archive has not been\ncreated as it would be empty`), + }, + }, + }) +} + +// TestResource_ArchiveFile_SymlinkDirectory_Absolute_ExcludeSymlinkDirectories verifies that an empty archive +// is generated when trying to archive a directory which only contains a symlink to a directory. +func TestResource_ArchiveFile_SymlinkDirectory_Absolute_ExcludeSymlinkDirectories(t *testing.T) { + td := t.TempDir() + + f := filepath.Join(td, "zip_file_acc_test.zip") + + symlinkDirWithRegularFilesAbs, err := filepath.Abs("test-fixtures/test-symlink-dir") + if err != nil { + t.Fatal(err) + } + + r.ParallelTest(t, r.TestCase{ + ProtoV5ProviderFactories: protoV5ProviderFactories(), + Steps: []r.TestStep{ + { + Config: fmt.Sprintf(` + resource "archive_file" "foo" { + type = "zip" + source_dir = "%s" + output_path = "%s" + output_file_mode = "0666" + exclude_symlink_directories = true + } + `, filepath.ToSlash(symlinkDirWithRegularFilesAbs), filepath.ToSlash(f)), + ExpectError: regexp.MustCompile(`.*error creating archive: error archiving directory: archive has not been\ncreated as it would be empty`), + }, + }, + }) +} + +// TestResource_ArchiveFile_DirectoryWithSymlinkFile_Relative_ExcludeSymlinkDirectories verifies that a relative path to a +// directory containing a symlink file generates an archive which includes the files in the directory. +func TestResource_ArchiveFile_DirectoryWithSymlinkFile_Relative_ExcludeSymlinkDirectories(t *testing.T) { + td := t.TempDir() + + f := filepath.Join(td, "zip_file_acc_test.zip") + + var fileSize string + + r.ParallelTest(t, r.TestCase{ + ProtoV5ProviderFactories: protoV5ProviderFactories(), + Steps: []r.TestStep{ + { + Config: fmt.Sprintf(` + resource "archive_file" "foo" { + type = "zip" + source_dir = "%s" + output_path = "%s" + output_file_mode = "0666" + exclude_symlink_directories = true + } + `, filepath.ToSlash("test-fixtures/test-dir-with-symlink-file"), filepath.ToSlash(f)), + Check: r.ComposeTestCheckFunc( + testAccArchiveFileSize(f, &fileSize), + r.TestCheckResourceAttrPtr("archive_file.foo", "output_size", &fileSize), + r.TestCheckResourceAttrWith("archive_file.foo", "output_path", func(value string) error { + ensureContents(t, value, map[string][]byte{ + "test-file.txt": []byte(`This is test content`), + "test-symlink.txt": []byte(`This is test content`), + }) + ensureFileMode(t, value, "0666") + return nil + }), + ), + }, + }, + }) +} + +// TestResource_ArchiveFile_DirectoryWithSymlinkFile_Absolute_ExcludeSymlinkDirectories verifies that an absolute path to a +// directory containing a symlink file generates an archive which includes the files in the directory. +func TestResource_ArchiveFile_DirectoryWithSymlinkFile_Absolute_ExcludeSymlinkDirectories(t *testing.T) { + td := t.TempDir() + + f := filepath.Join(td, "zip_file_acc_test.zip") + + symlinkDirWithSymlinkFilesAbs, err := filepath.Abs("test-fixtures/test-dir-with-symlink-file") + if err != nil { + t.Fatal(err) + } + + var fileSize string + + r.ParallelTest(t, r.TestCase{ + ProtoV5ProviderFactories: protoV5ProviderFactories(), + Steps: []r.TestStep{ + { + Config: fmt.Sprintf(` + resource "archive_file" "foo" { + type = "zip" + source_dir = "%s" + output_path = "%s" + output_file_mode = "0666" + exclude_symlink_directories = true + } + `, filepath.ToSlash(symlinkDirWithSymlinkFilesAbs), filepath.ToSlash(f)), + Check: r.ComposeTestCheckFunc( + testAccArchiveFileSize(f, &fileSize), + r.TestCheckResourceAttrPtr("archive_file.foo", "output_size", &fileSize), + r.TestCheckResourceAttrWith("archive_file.foo", "output_path", func(value string) error { + ensureContents(t, value, map[string][]byte{ + "test-file.txt": []byte(`This is test content`), + "test-symlink.txt": []byte(`This is test content`), + }) + ensureFileMode(t, value, "0666") + return nil + }), + ), + }, + }, + }) +} + +// TestResource_ArchiveFile_SymlinkDirectoryWithSymlinkFile_Relative_ExcludeSymlinkDirectories verifies that a relative path +// to a symlink file in a symlink directory generates an archive which includes the files in the directory. +func TestResource_ArchiveFile_SymlinkDirectoryWithSymlinkFile_Relative_ExcludeSymlinkDirectories(t *testing.T) { + td := t.TempDir() + + f := filepath.Join(td, "zip_file_acc_test.zip") + + var fileSize string + + r.ParallelTest(t, r.TestCase{ + ProtoV5ProviderFactories: protoV5ProviderFactories(), + Steps: []r.TestStep{ + { + Config: fmt.Sprintf(` + resource "archive_file" "foo" { + type = "zip" + source_file = "%s" + output_path = "%s" + output_file_mode = "0666" + exclude_symlink_directories = true + } + `, filepath.ToSlash("test-fixtures/test-symlink-dir-with-symlink-file/test-symlink.txt"), filepath.ToSlash(f)), + Check: r.ComposeTestCheckFunc( + testAccArchiveFileSize(f, &fileSize), + r.TestCheckResourceAttrPtr("archive_file.foo", "output_size", &fileSize), + r.TestCheckResourceAttrWith("archive_file.foo", "output_path", func(value string) error { + ensureContents(t, value, map[string][]byte{ + "test-symlink.txt": []byte(`This is test content`), + }) + ensureFileMode(t, value, "0666") + return nil + }), + ), + }, + }, + }) +} + +// TestResource_ArchiveFile_SymlinkDirectoryWithSymlinkFile_Absolute_ExcludeSymlinkDirectories verifies that an absolute path +// to a symlink file in a symlink directory generates an archive which includes the files in the directory. +func TestResource_ArchiveFile_SymlinkDirectoryWithSymlinkFile_Absolute_ExcludeSymlinkDirectories(t *testing.T) { + td := t.TempDir() + + f := filepath.Join(td, "zip_file_acc_test.zip") + + symlinkFileInSymlinkDirAbs, err := filepath.Abs("test-fixtures/test-symlink-dir-with-symlink-file/test-symlink.txt") + if err != nil { + t.Fatal(err) + } + + var fileSize string + + r.ParallelTest(t, r.TestCase{ + ProtoV5ProviderFactories: protoV5ProviderFactories(), + Steps: []r.TestStep{ + { + Config: fmt.Sprintf(` + resource "archive_file" "foo" { + type = "zip" + source_file = "%s" + output_path = "%s" + output_file_mode = "0666" + exclude_symlink_directories = true + } + `, filepath.ToSlash(symlinkFileInSymlinkDirAbs), filepath.ToSlash(f)), + Check: r.ComposeTestCheckFunc( + testAccArchiveFileSize(f, &fileSize), + r.TestCheckResourceAttrPtr("archive_file.foo", "output_size", &fileSize), + r.TestCheckResourceAttrWith("archive_file.foo", "output_path", func(value string) error { + ensureContents(t, value, map[string][]byte{ + "test-symlink.txt": []byte(`This is test content`), + }) + ensureFileMode(t, value, "0666") + return nil + }), + ), + }, + }, + }) +} + +// TestResource_ArchiveFile_DirectoryWithSymlinkDirectory_Relative_ExcludeSymlinkDirectories verifies that an empty archive +// is generated when trying to archive a directory which only contains a symlink to a directory. +func TestResource_ArchiveFile_DirectoryWithSymlinkDirectory_Relative_ExcludeSymlinkDirectories(t *testing.T) { + td := t.TempDir() + + f := filepath.Join(td, "zip_file_acc_test.zip") + + r.ParallelTest(t, r.TestCase{ + ProtoV5ProviderFactories: protoV5ProviderFactories(), + Steps: []r.TestStep{ + { + Config: fmt.Sprintf(` + resource "archive_file" "foo" { + type = "zip" + source_dir = "%s" + output_path = "%s" + exclude_symlink_directories = true + } + `, filepath.ToSlash("test-fixtures/test-dir-with-symlink-dir"), filepath.ToSlash(f)), + ExpectError: regexp.MustCompile(`.*error creating archive: error archiving directory: archive has not been\ncreated as it would be empty`), + }, + }, + }) +} + +// TestResource_ArchiveFile_IncludeDirectoryWithSymlinkDirectory_Absolute_ExcludeSymlinkDirectories verifies that an empty archive +// is generated when trying to archive a directory which only contains a symlink to a directory. +func TestResource_ArchiveFile_IncludeDirectoryWithSymlinkDirectory_Absolute_ExcludeSymlinkDirectories(t *testing.T) { + td := t.TempDir() + + f := filepath.Join(td, "zip_file_acc_test.zip") + + symlinkDirInRegularDirAbs, err := filepath.Abs("test-fixtures/test-dir-with-symlink-dir") + if err != nil { + t.Fatal(err) + } + + r.ParallelTest(t, r.TestCase{ + ProtoV5ProviderFactories: protoV5ProviderFactories(), + Steps: []r.TestStep{ + { + Config: fmt.Sprintf(` + resource "archive_file" "foo" { + type = "zip" + source_dir = "%s" + output_path = "%s" + exclude_symlink_directories = true + } + `, filepath.ToSlash(symlinkDirInRegularDirAbs), filepath.ToSlash(f)), + ExpectError: regexp.MustCompile(`.*error creating archive: error archiving directory: archive has not been\ncreated as it would be empty`), + }, + }, + }) +} + +// TestResource_ArchiveFile_Multiple_Relative_ExcludeSymlinkDirectories verifies that +// symlinked directories are excluded. +func TestResource_ArchiveFile_Multiple_Relative_ExcludeSymlinkDirectories(t *testing.T) { + td := t.TempDir() + + f := filepath.Join(td, "zip_file_acc_test.zip") + + var fileSize string + + r.ParallelTest(t, r.TestCase{ + ProtoV5ProviderFactories: protoV5ProviderFactories(), + Steps: []r.TestStep{ + { + Config: fmt.Sprintf(` + resource "archive_file" "foo" { + type = "zip" + source_dir = "%s" + output_path = "%s" + output_file_mode = "0666" + exclude_symlink_directories = true + } + `, filepath.ToSlash("test-fixtures"), filepath.ToSlash(f)), + Check: r.ComposeTestCheckFunc( + testAccArchiveFileSize(f, &fileSize), + r.TestCheckResourceAttrPtr("archive_file.foo", "output_size", &fileSize), + r.TestCheckResourceAttrWith("archive_file.foo", "output_path", func(value string) error { + ensureContents(t, value, map[string][]byte{ + "test-dir/test-dir1/file1.txt": []byte("This is file 1"), + "test-dir/test-dir1/file2.txt": []byte("This is file 2"), + "test-dir/test-dir1/file3.txt": []byte("This is file 3"), + "test-dir/test-dir2/file1.txt": []byte("This is file 1"), + "test-dir/test-dir2/file2.txt": []byte("This is file 2"), + "test-dir/test-dir2/file3.txt": []byte("This is file 3"), + "test-dir/test-file.txt": []byte("This is test content"), + "test-dir-with-symlink-file/test-file.txt": []byte("This is test content"), + "test-dir-with-symlink-file/test-symlink.txt": []byte("This is test content"), + }) + ensureFileMode(t, value, "0666") + return nil + }), + ), + }, + }, + }) +} + +// TestResource_ArchiveFile_Multiple_Relative_ExcludeSymlinkDirectories verifies that +// symlinked directories are excluded. +func TestResource_ArchiveFile_Multiple_Absolute_ExcludeSymlinkDirectories(t *testing.T) { + td := t.TempDir() + + f := filepath.Join(td, "zip_file_acc_test.zip") + + multipleDirsAndFilesAbs, err := filepath.Abs("test-fixtures") + if err != nil { + t.Fatal(err) + } + + var fileSize string + + r.ParallelTest(t, r.TestCase{ + ProtoV5ProviderFactories: protoV5ProviderFactories(), + Steps: []r.TestStep{ + { + Config: fmt.Sprintf(` + resource "archive_file" "foo" { + type = "zip" + source_dir = "%s" + output_path = "%s" + output_file_mode = "0666" + exclude_symlink_directories = true + } + `, filepath.ToSlash(multipleDirsAndFilesAbs), filepath.ToSlash(f)), + Check: r.ComposeTestCheckFunc( + testAccArchiveFileSize(f, &fileSize), + r.TestCheckResourceAttrPtr("archive_file.foo", "output_size", &fileSize), + r.TestCheckResourceAttrWith("archive_file.foo", "output_path", func(value string) error { + ensureContents(t, value, map[string][]byte{ + "test-dir/test-dir1/file1.txt": []byte("This is file 1"), + "test-dir/test-dir1/file2.txt": []byte("This is file 2"), + "test-dir/test-dir1/file3.txt": []byte("This is file 3"), + "test-dir/test-dir2/file1.txt": []byte("This is file 1"), + "test-dir/test-dir2/file2.txt": []byte("This is file 2"), + "test-dir/test-dir2/file3.txt": []byte("This is file 3"), + "test-dir/test-file.txt": []byte("This is test content"), + "test-dir-with-symlink-file/test-file.txt": []byte("This is test content"), + "test-dir-with-symlink-file/test-symlink.txt": []byte("This is test content"), + }) + ensureFileMode(t, value, "0666") + return nil + }), + ), + }, + }, + }) +} + func alterFileContents(content, path string) { f, err := os.Create(path) if err != nil {