Skip to content

Commit 03b6dfd

Browse files
nevins-bstack72
authored andcommitted
adding (backwards compatible) support for providing multiple source filename and content (hashicorp#11271)
1 parent 87d98b1 commit 03b6dfd

5 files changed

Lines changed: 104 additions & 0 deletions

File tree

builtin/providers/archive/archiver.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ type Archiver interface {
99
ArchiveContent(content []byte, infilename string) error
1010
ArchiveFile(infilename string) error
1111
ArchiveDir(indirname string) error
12+
ArchiveMultiple(content map[string][]byte) error
1213
}
1314

1415
type ArchiverBuilder func(filepath string) Archiver

builtin/providers/archive/data_source_archive_file.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package archive
22

33
import (
4+
"bytes"
45
"crypto/md5"
56
"crypto/sha1"
67
"crypto/sha256"
@@ -11,6 +12,7 @@ import (
1112
"os"
1213
"path"
1314

15+
"github.com/hashicorp/terraform/helper/hashcode"
1416
"github.com/hashicorp/terraform/helper/schema"
1517
)
1618

@@ -24,6 +26,33 @@ func dataSourceFile() *schema.Resource {
2426
Required: true,
2527
ForceNew: true,
2628
},
29+
"source": &schema.Schema{
30+
Type: schema.TypeSet,
31+
Optional: true,
32+
Computed: true,
33+
Elem: &schema.Resource{
34+
Schema: map[string]*schema.Schema{
35+
"content": &schema.Schema{
36+
Type: schema.TypeString,
37+
Required: true,
38+
ForceNew: true,
39+
},
40+
"filename": &schema.Schema{
41+
Type: schema.TypeString,
42+
Required: true,
43+
ForceNew: true,
44+
},
45+
},
46+
},
47+
ConflictsWith: []string{"source_file", "source_dir", "source_content", "source_content_filename"},
48+
Set: func(v interface{}) int {
49+
var buf bytes.Buffer
50+
m := v.(map[string]interface{})
51+
buf.WriteString(fmt.Sprintf("%s-", m["filename"].(string)))
52+
buf.WriteString(fmt.Sprintf("%s-", m["content"].(string)))
53+
return hashcode.String(buf.String())
54+
},
55+
},
2756
"source_content": &schema.Schema{
2857
Type: schema.TypeString,
2958
Optional: true,
@@ -138,6 +167,16 @@ func archive(d *schema.ResourceData) error {
138167
if err := archiver.ArchiveContent([]byte(content), filename.(string)); err != nil {
139168
return fmt.Errorf("error archiving content: %s", err)
140169
}
170+
} else if v, ok := d.GetOk("source"); ok {
171+
vL := v.(*schema.Set).List()
172+
content := make(map[string][]byte)
173+
for _, v := range vL {
174+
src := v.(map[string]interface{})
175+
content[src["filename"].(string)] = []byte(src["content"].(string))
176+
}
177+
if err := archiver.ArchiveMultiple(content); err != nil {
178+
return fmt.Errorf("error archiving content: %s", err)
179+
}
141180
} else {
142181
return fmt.Errorf("one of 'source_dir', 'source_file', 'source_content_filename' must be specified")
143182
}

builtin/providers/archive/data_source_archive_file_test.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ func TestAccArchiveFile_Basic(t *testing.T) {
5151
r.TestCheckResourceAttrPtr("data.archive_file.foo", "output_size", &fileSize),
5252
),
5353
},
54+
r.TestStep{
55+
Config: testAccArchiveFileMultiConfig,
56+
Check: r.ComposeTestCheckFunc(
57+
testAccArchiveFileExists("zip_file_acc_test.zip", &fileSize),
58+
r.TestCheckResourceAttrPtr("data.archive_file.foo", "output_size", &fileSize),
59+
),
60+
},
5461
r.TestStep{
5562
Config: testAccArchiveFileOutputPath,
5663
Check: r.ComposeTestCheckFunc(
@@ -107,3 +114,14 @@ data "archive_file" "foo" {
107114
output_path = "zip_file_acc_test.zip"
108115
}
109116
`
117+
118+
var testAccArchiveFileMultiConfig = `
119+
data "archive_file" "foo" {
120+
type = "zip"
121+
source {
122+
filename = "content.txt"
123+
content = "This is some content"
124+
}
125+
output_path = "zip_file_acc_test.zip"
126+
}
127+
`

builtin/providers/archive/zip_archiver.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66
"io/ioutil"
77
"os"
88
"path/filepath"
9+
"sort"
910
)
1011

1112
type ZipArchiver struct {
@@ -85,6 +86,34 @@ func (a *ZipArchiver) ArchiveDir(indirname string) error {
8586

8687
}
8788

89+
func (a *ZipArchiver) ArchiveMultiple(content map[string][]byte) error {
90+
if err := a.open(); err != nil {
91+
return err
92+
}
93+
defer a.close()
94+
95+
// Ensure files are processed in the same order so hashes don't change
96+
keys := make([]string, len(content))
97+
i := 0
98+
for k := range content {
99+
keys[i] = k
100+
i++
101+
}
102+
sort.Strings(keys)
103+
104+
for _, filename := range keys {
105+
f, err := a.writer.Create(filename)
106+
if err != nil {
107+
return err
108+
}
109+
_, err = f.Write(content[filename])
110+
if err != nil {
111+
return err
112+
}
113+
}
114+
return nil
115+
}
116+
88117
func (a *ZipArchiver) open() error {
89118
f, err := os.Create(a.filepath)
90119
if err != nil {

builtin/providers/archive/zip_archiver_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,23 @@ func TestZipArchiver_Dir(t *testing.T) {
4444
})
4545
}
4646

47+
func TestZipArchiver_Multiple(t *testing.T) {
48+
zipfilepath := "archive-content.zip"
49+
content := map[string][]byte{
50+
"file1.txt": []byte("This is file 1"),
51+
"file2.txt": []byte("This is file 2"),
52+
"file3.txt": []byte("This is file 3"),
53+
}
54+
55+
archiver := NewZipArchiver(zipfilepath)
56+
if err := archiver.ArchiveMultiple(content); err != nil {
57+
t.Fatalf("unexpected error: %s", err)
58+
}
59+
60+
ensureContents(t, zipfilepath, content)
61+
62+
}
63+
4764
func ensureContents(t *testing.T, zipfilepath string, wants map[string][]byte) {
4865
r, err := zip.OpenReader(zipfilepath)
4966
if err != nil {

0 commit comments

Comments
 (0)