Skip to content
Merged
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
2 changes: 2 additions & 0 deletions .web-docs/components/builder/vagrant/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ the Compress post-processor will not work with this builder.
be found here. The template variables available to you are
`{{ .BoxName }}`, `{{ .SyncedFolder }}`, and `{{.InsertKey}}`, which
correspond to the Packer options box_name, synced_folder, and insert_key.
Alternatively, the template variable `{{.DefaultTemplate}}` is available for
use if you wish to extend the default generated template.

- `synced_folder` (string) - Path to the folder to be synced to the guest. The path can be absolute
or relative to the directory Packer is being run from.
Expand Down
2 changes: 2 additions & 0 deletions builder/vagrant/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ type Config struct {
// be found here. The template variables available to you are
// `{{ .BoxName }}`, `{{ .SyncedFolder }}`, and `{{.InsertKey}}`, which
// correspond to the Packer options box_name, synced_folder, and insert_key.
// Alternatively, the template variable `{{.DefaultTemplate}}` is available for
// use if you wish to extend the default generated template.
Template string `mapstructure:"template" required:"false"`
// Path to the folder to be synced to the guest. The path can be absolute
// or relative to the directory Packer is being run from.
Expand Down
91 changes: 53 additions & 38 deletions builder/vagrant/step_create_vagrantfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,37 @@ package vagrant
import (
"context"
"fmt"
"io"
"log"
"os"
"path/filepath"
"strings"
"text/template"

"github.com/hashicorp/packer-plugin-sdk/multistep"
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
)

type StepCreateVagrantfile struct {
Template string
OutputDir string
SyncedFolder string
GlobalID string
SourceBox string
BoxName string
InsertKey bool
Template string
OutputDir string
SyncedFolder string
GlobalID string
SourceBox string
BoxName string
InsertKey bool
defaultTemplateContent string
}

var DEFAULT_TEMPLATE = `Vagrant.configure("2") do |config|
type VagrantfileOptions struct {
SyncedFolder string
SourceBox string
BoxName string
InsertKey bool
DefaultTemplate string
}

const DEFAULT_TEMPLATE = `Vagrant.configure("2") do |config|
config.vm.define "source", autostart: false do |source|
source.vm.box = "{{.SourceBox}}"
config.ssh.insert_key = {{.InsertKey}}
Expand All @@ -42,51 +53,55 @@ var DEFAULT_TEMPLATE = `Vagrant.configure("2") do |config|
{{- end}}
end`

type VagrantfileOptions struct {
SyncedFolder string
SourceBox string
BoxName string
InsertKey bool
}
var defaultTemplate = template.Must(template.New("VagrantTpl").Parse(DEFAULT_TEMPLATE))

func (s *StepCreateVagrantfile) createVagrantfile() (tplPath string, err error) {
tplPath, err = filepath.Abs(filepath.Join(s.OutputDir, "Vagrantfile"))
if err != nil {
return
}

func (s *StepCreateVagrantfile) createVagrantfile() (string, error) {
tplPath := filepath.Join(s.OutputDir, "Vagrantfile")
templateFile, err := os.Create(tplPath)
if err != nil {
retErr := fmt.Errorf("Error creating vagrantfile %s", err.Error())
return "", retErr
err = fmt.Errorf("Error creating vagrantfile %s", err.Error())
return
}

if s.defaultTemplateContent, err = s.renderDefaultTemplate(); err != nil {
return
}

var tpl *template.Template
if s.Template == "" {
// Generate vagrantfile template based on our default
tpl = template.Must(template.New("VagrantTpl").Parse(DEFAULT_TEMPLATE))
// Generate vagrantfile template based on our default template
_, err = templateFile.WriteString(s.defaultTemplateContent)
} else {
// Read in the template from provided file.
// Otherwise, read in the template from provided file.
var tpl *template.Template
tpl, err = template.ParseFiles(s.Template)
if err != nil {
return "", err
if err == nil {
err = s.executeTemplate(tpl, templateFile)
}
}
return
}

func (s *StepCreateVagrantfile) executeTemplate(tpl *template.Template, file io.Writer) error {
opts := &VagrantfileOptions{
SyncedFolder: s.SyncedFolder,
BoxName: s.BoxName,
SourceBox: s.SourceBox,
InsertKey: s.InsertKey,
}

err = tpl.Execute(templateFile, opts)
if err != nil {
return "", err
SyncedFolder: s.SyncedFolder,
BoxName: s.BoxName,
SourceBox: s.SourceBox,
InsertKey: s.InsertKey,
DefaultTemplate: s.defaultTemplateContent,
}
return tpl.Execute(file, opts)
}

abspath, err := filepath.Abs(tplPath)
if err != nil {
return "", err
func (s *StepCreateVagrantfile) renderDefaultTemplate() (string, error) {
buf := new(strings.Builder)
if err := s.executeTemplate(defaultTemplate, buf); err != nil {
return "", fmt.Errorf("Error rendering default template %w", err)
}

return abspath, nil
return buf.String(), nil
}

func (s *StepCreateVagrantfile) Run(ctx context.Context, state multistep.StateBag) multistep.StepAction {
Expand Down
60 changes: 60 additions & 0 deletions builder/vagrant/step_create_vagrantfile_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ package vagrant
import (
"io/ioutil"
"os"
"path/filepath"
"strings"
"testing"

Expand Down Expand Up @@ -116,3 +117,62 @@ end`
t.Fatalf("EXPECTED: \n%s\n\n RECEIVED: \n%s\n\n", expected, actual)
}
}

func TestCreateFile_customTemplate(t *testing.T) {
workdir := t.TempDir()
vagrantfileTemplatePath := filepath.Join(workdir, "Vagrantfile.tpl")
f, err := os.Create(vagrantfileTemplatePath)
if err != nil {
t.Fatal(err.Error())
}
defer f.Close()

var TEMPLATE = `{{ .DefaultTemplate }}
Vagrant.configure("2") do |config|
config.vm.provider "virtualbox" do |vb|
vb.customize ['modifyvm', :id, '--nested-hw-virt', 'on']
end
end`

_, err = f.WriteString(TEMPLATE)
if err != nil {
t.Fatal(err.Error())
}

testy := StepCreateVagrantfile{
OutputDir: "./",
SourceBox: "apples",
BoxName: "bananas",
Template: vagrantfileTemplatePath,
}
templatePath, err := testy.createVagrantfile()
if err != nil {
t.Fatalf(err.Error())
}
defer os.Remove(templatePath)
contents, err := ioutil.ReadFile(templatePath)
if err != nil {
t.Fatalf(err.Error())
}
actual := string(contents)
expected := `Vagrant.configure("2") do |config|
config.vm.define "source", autostart: false do |source|
source.vm.box = "apples"
config.ssh.insert_key = false
end
config.vm.define "output" do |output|
output.vm.box = "bananas"
output.vm.box_url = "file://package.box"
config.ssh.insert_key = false
end
config.vm.synced_folder ".", "/vagrant", disabled: true
end
Vagrant.configure("2") do |config|
config.vm.provider "virtualbox" do |vb|
vb.customize ['modifyvm', :id, '--nested-hw-virt', 'on']
end
end`
if ok := strings.Compare(actual, expected); ok != 0 {
t.Fatalf("EXPECTED: \n%s\n\n RECEIVED: \n%s\n\n", expected, actual)
}
}
2 changes: 2 additions & 0 deletions docs-partials/builder/vagrant/Config-not-required.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@
be found here. The template variables available to you are
`{{ .BoxName }}`, `{{ .SyncedFolder }}`, and `{{.InsertKey}}`, which
correspond to the Packer options box_name, synced_folder, and insert_key.
Alternatively, the template variable `{{.DefaultTemplate}}` is available for
use if you wish to extend the default generated template.

- `synced_folder` (string) - Path to the folder to be synced to the guest. The path can be absolute
or relative to the directory Packer is being run from.
Expand Down