Skip to content

Commit 2da2de8

Browse files
saleemrashidazr
andauthored
CDConfig: Add cd_content for file templating (#61)
* CDConfig: Add cd_content for file templating + tests Co-authored-by: Adrien Delorme <azr@users.noreply.github.com>
1 parent 7aedbfb commit 2da2de8

4 files changed

Lines changed: 89 additions & 8 deletions

File tree

cmd/packer-sdc/internal/renderdocs/docs-partials/packer-plugin-sdk/multistep/commonsteps/CDConfig-not-required.mdx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,22 @@
4444
* hdiutil (normally found in macOS)
4545
* oscdimg (normally found in Windows as part of the Windows ADK)
4646

47+
- `cd_content` (map[string]string) - Key/Values to add to the CD. The keys represent the paths, and the values
48+
contents. It can be used alongside `cd_files`, which is useful to add large
49+
files without loading them into memory. If any paths are specified by both,
50+
the contents in `cd_content` will take precedence.
51+
52+
Usage example (HCL):
53+
54+
```hcl
55+
cd_files = ["vendor-data"]
56+
cd_content = {
57+
"meta-data" = jsonencode(local.instance_data)
58+
"user-data" = templatefile("user-data", { packages = ["nginx"] })
59+
}
60+
cd_label = "cidata"
61+
```
62+
4763
- `cd_label` (string) - CD Label
4864

4965
<!-- End of code generated from the comments of the CDConfig struct in multistep/commonsteps/extra_iso_config.go; -->

multistep/commonsteps/extra_iso_config.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,23 @@ type CDConfig struct {
6565
// * hdiutil (normally found in macOS)
6666
// * oscdimg (normally found in Windows as part of the Windows ADK)
6767
CDFiles []string `mapstructure:"cd_files"`
68-
CDLabel string `mapstructure:"cd_label"`
68+
// Key/Values to add to the CD. The keys represent the paths, and the values
69+
// contents. It can be used alongside `cd_files`, which is useful to add large
70+
// files without loading them into memory. If any paths are specified by both,
71+
// the contents in `cd_content` will take precedence.
72+
//
73+
// Usage example (HCL):
74+
//
75+
// ```hcl
76+
// cd_files = ["vendor-data"]
77+
// cd_content = {
78+
// "meta-data" = jsonencode(local.instance_data)
79+
// "user-data" = templatefile("user-data", { packages = ["nginx"] })
80+
// }
81+
// cd_label = "cidata"
82+
// ```
83+
CDContent map[string]string `mapstructure:"cd_content"`
84+
CDLabel string `mapstructure:"cd_label"`
6985
}
7086

7187
func (c *CDConfig) Prepare(ctx *interpolate.Context) []error {

multistep/commonsteps/step_create_cdrom.go

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"io"
7+
"io/ioutil"
78
"log"
89
"os"
910
"os/exec"
@@ -22,16 +23,17 @@ type StepCreateCD struct {
2223
// Files can be either files or directories. Any files provided here will
2324
// be written to the root of the CD. Directories will be written to the
2425
// root of the CD as well, but will retain their subdirectory structure.
25-
Files []string
26-
Label string
26+
Files []string
27+
Content map[string]string
28+
Label string
2729

2830
CDPath string
2931

3032
rootFolder string
3133
}
3234

3335
func (s *StepCreateCD) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
34-
if len(s.Files) == 0 {
36+
if len(s.Files) == 0 && len(s.Content) == 0 {
3537
log.Println("No CD files specified. CD disk will not be made.")
3638
return multistep.ActionContinue
3739
}
@@ -79,6 +81,15 @@ func (s *StepCreateCD) Run(ctx context.Context, state multistep.StateBag) multis
7981
}
8082
}
8183

84+
for path, content := range s.Content {
85+
err = s.AddContent(rootFolder, path, content)
86+
if err != nil {
87+
state.Put("error",
88+
fmt.Errorf("Error creating temporary file for CD: %s", err))
89+
return multistep.ActionHalt
90+
}
91+
}
92+
8293
cmd, err := retrieveCDISOCreationCommand(s.Label, rootFolder, CDPath)
8394
if err != nil {
8495
state.Put("error", err)
@@ -291,3 +302,18 @@ func (s *StepCreateCD) AddFile(dst, src string) error {
291302

292303
return filepath.Walk(src, visit)
293304
}
305+
306+
func (s *StepCreateCD) AddContent(dst, path, content string) error {
307+
// Join Cleans the path so we can join it without path traversal issues.
308+
dstPath := filepath.Join(dst, path)
309+
dstDir := filepath.Dir(dstPath)
310+
err := os.MkdirAll(dstDir, 0777)
311+
if err != nil {
312+
return fmt.Errorf("error creating new directory %s: %s", dstDir, err)
313+
}
314+
err = ioutil.WriteFile(dstPath, []byte(content), 0666)
315+
if err != nil {
316+
return fmt.Errorf("Error writing file %s on CD: %s", path, err)
317+
}
318+
return nil
319+
}

multistep/commonsteps/step_create_cdrom_test.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,17 +92,25 @@ func TestStepCreateCD(t *testing.T) {
9292
}
9393
defer os.RemoveAll(dir)
9494

95-
expected := map[string]string{
95+
createFiles(t, dir, map[string]string{
9696
"test folder/b/test1": "1",
9797
"test folder/b/test2": "2",
9898
"test folder 2/x": "3",
9999
"test_cd_roms.tmp": "4",
100100
"test cd files.tmp": "5",
101101
"Test-Test-Test5.tmp": "6",
102+
"subfolder/meta-data": "subfolder/meta-data from files",
103+
"subfolder/user-data": "subfolder/user-data from files",
104+
"user-data": "user-data from files",
105+
"vendor-data": "vendor-data from files",
106+
})
107+
step.Content = map[string]string{
108+
"subfolder not created by files/test.tmp": "test",
109+
"subfolder/meta-data": "subfolder/meta-data from content",
110+
"user-data": "user-data from content",
102111
}
103112

104-
createFiles(t, dir, expected)
105-
files := []string{"test folder", "test folder 2/", "test_cd_roms.tmp", "test cd files.tmp", "Test-Test-Test5.tmp"}
113+
files := []string{"test folder", "test folder 2/", "test_cd_roms.tmp", "test cd files.tmp", "Test-Test-Test5.tmp", "subfolder", "user-data", "vendor-data"}
106114

107115
step.Files = make([]string, len(files))
108116
for i, fname := range files {
@@ -124,7 +132,19 @@ func TestStepCreateCD(t *testing.T) {
124132
t.Fatalf("file not found: %s for %v", CD_path, step.Files)
125133
}
126134

127-
checkFiles(t, step.rootFolder, expected)
135+
checkFiles(t, step.rootFolder, map[string]string{
136+
"test folder/b/test1": "1",
137+
"test folder/b/test2": "2",
138+
"test folder 2/x": "3",
139+
"test_cd_roms.tmp": "4",
140+
"test cd files.tmp": "5",
141+
"Test-Test-Test5.tmp": "6",
142+
"subfolder not created by files/test.tmp": "test",
143+
"subfolder/meta-data": "subfolder/meta-data from content",
144+
"subfolder/user-data": "subfolder/user-data from files",
145+
"user-data": "user-data from content",
146+
"vendor-data": "vendor-data from files",
147+
})
128148

129149
step.Cleanup(state)
130150

@@ -150,6 +170,9 @@ func TestStepCreateCD_missing(t *testing.T) {
150170
defer os.RemoveAll(dir)
151171

152172
step.Files = []string{"missing file.tmp"}
173+
step.Content = map[string]string{
174+
"test_cd_roms.tmp": "should not be created",
175+
}
153176
if action := step.Run(context.Background(), state); action != multistep.ActionHalt {
154177
t.Fatalf("bad action: %#v for %v", action, step.Files)
155178
}

0 commit comments

Comments
 (0)